Fork me on GitHub

Spring之Spel表达式

正常业务场景一般不用这个技术,但需要知道有这么个东西支持Spring。

记忆力不好,抄了些套路代码便于以后用到。

package com.paic.phssp.springtest.spel;

import java.util.Arrays;
import java.util.List;

public class Account {
    private String name;
    private int footballCount;
    private Friend friend;
    private List<Friend> friends;

    public Account(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setFootballCount(int footballCount) {
        this.footballCount = footballCount;
    }

    public void addFriend(Friend friend) {

        this.friend = friend;
    }

    public int getFootballCount() {
        return footballCount;
    }

    public Friend getFriend() {
        return friend;
    }

    public void setFriend(Friend friend) {
        this.friend = friend;
    }

    public List<Friend> getFriends() {
        return friends;
    }

    public void setFriends(List<Friend> friends) {
        this.friends = friends;
    }

    public void read(){
        System.out.println("读书");
    }

    public void addFriendNames(String ... friendNames){
        System.out.println("friendNames="+ Arrays.toString(friendNames));
    }
}
package com.paic.phssp.springtest.spel;

public class Friend {
    private String name;

    public Friend(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
package com.paic.phssp.springtest.spel;

import com.paic.phssp.springtest.proxy.cglib.HeroCglibProxyFactory;
import com.paic.phssp.springtest.proxy.cglib.WickedLittleMage;
import com.paic.phssp.springtest.proxy.jdk.HeroProxyFactory;
import com.paic.phssp.springtest.proxy.jdk.IHero;
import com.paic.phssp.springtest.proxy.jdk.MonkeyHero;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.*;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpelTest {

    @Test
    public void testTextEl() {
        //文字表达式
        ExpressionParser parser = new SpelExpressionParser();

        //字符串解析
        String str = (String) parser.parseExpression("'你好'").getValue();
        System.out.println(str);

        //整型解析
        int intVal = (Integer) parser.parseExpression("0x2F").getValue();
        System.out.println(intVal);

        //双精度浮点型解析
        double doubleVal = (Double) parser.parseExpression("4329759E+22").getValue();
        System.out.println(doubleVal);

        //布尔型解析
        boolean booleanVal = (boolean) parser.parseExpression("true").getValue();
        System.out.println(booleanVal);

      /*  你好
        47
        4.329759E28
        true*/
    }

    @Test
    public void testObjEl() {
        //初始化对象
        Account account = new Account("Deniro");
        account.setFootballCount(10);
        account.addFriend(new Friend("Jack"));

        //解析器
        ExpressionParser parser = new SpelExpressionParser();
        //解析上下文
        EvaluationContext context = new StandardEvaluationContext(account);

        //获取不同类型的属性
        String name = (String) parser.parseExpression("name").getValue(context);
        System.out.println(name);
        int count = (Integer) parser.parseExpression("footballCount+1").getValue(context);
        System.out.println(count);

        //获取嵌套类中的属性
        String friend = (String) parser.parseExpression("friend.name").getValue(context);
        System.out.println(friend);

        /*Deniro
        11
        Jack*/

        //安全导航操作符,能够避免空指针异常
        account.setFriend(null);
        friend = (String) parser.parseExpression("friend?.name").getValue(context,String.class);
        System.out.println("friendName:" + friend);//friendName:null

    }

    @Test
    public void testArrMapListEl() {
        //解析器
        ExpressionParser parser = new SpelExpressionParser();

        //解析一维数组
        int[] oneArray = (int[]) parser.parseExpression("new int[]{3,4,5}").getValue();
        System.out.println("一维数组开始:");
        for (int i : oneArray) {
            System.out.print(i);
        }
        System.out.println();
        System.out.println("一维数组结束");

       /* 一维数组开始:
        345
        一维数组结束*/

        //这里会抛出 SpelParseException
        //        int[][] twoArray = (int[][]) parser.parseExpression("new int[][]{3,4,5}{3,4,5}")
        //                .getValue();

        //解析 list
        List list = (List) parser.parseExpression("{3,4,5}").getValue();
        System.out.println("list:" + list);
        //list:[3, 4, 5]

        //解析 Map
        Map map = (Map) parser.parseExpression("{account:'deniro',footballCount:10}").getValue();
        System.out.println("map:" + map);
        //map:{account=deniro, footballCount=10}

        //解析对象中的 list
        final Account account = new Account("Deniro");
        Friend friend1 = new Friend("Jack");
        Friend friend2 = new Friend("Rose");
        List<Friend> friends = new ArrayList<>();
        friends.add(friend1);
        friends.add(friend2);
        account.setFriends(friends);

        EvaluationContext context = new StandardEvaluationContext(account);
        String friendName = (String) parser.parseExpression("friends[0].name").getValue(context);
        System.out.println("friendName:" + friendName);
        //friendName:Jack
    }

    @Test
    public void testMethodEl() {
        //解析器
        ExpressionParser parser = new SpelExpressionParser();

        //调用 String 方法
        boolean isEmpty = parser.parseExpression("'Hi,everybody'.contains('Hi')").getValue(Boolean.class);
        System.out.println("isEmpty:" + isEmpty);

        /**
         * 调用对象相关方法
         */
        final Account account = new Account("Deniro");
        EvaluationContext context = new StandardEvaluationContext(account);

        //调用公开方法
        parser.parseExpression("setFootballCount(11)").getValue(context, Account.class);
        System.out.println("getFootballCount:" + account.getFootballCount());

        //调用私有方法,抛出 SpelEvaluationException: EL1004E: Method call: Method write() cannot be found on net.deniro
        // .spring4.spel.Account type
        //        parser.parseExpression("write()").getValue(context,Boolean
        //                .class);

        //调用静态方法
        parser.parseExpression("read()").getValue(context, Account.class);

        //调用待可变参数的方法
        parser.parseExpression("addFriendNames('Jack','Rose')").getValue(context, Account.class);

       /* isEmpty:true
        getFootballCount:11
        读书
        friendNames=[Jack, Rose]*/
    }

    @Test
    public void testRelationEl() {
        //关系操作符
        //解析器
        ExpressionParser parser = new SpelExpressionParser();


        //数值比较
        boolean result = parser.parseExpression("2>1").getValue(Boolean.class);
        System.out.println("2>1:" + result);  //2>1:true

        //字符串比较
        result = parser.parseExpression("'z'>'a'").getValue(Boolean.class);
        System.out.println("'z'>'a':" + result); //'z'>'a':true

        //instanceof 运算符
        result = parser.parseExpression("'str' instanceof T(String)").getValue(Boolean.class);
        System.out.println("'str' 是否为字符串 :" + result);  //'str' 是否为字符串 :true

        result = parser.parseExpression("1 instanceof T(Integer)").getValue(Boolean.class);
        System.out.println("1 是否为整型 :" + result);  //1 是否为整型 :true

        //正则表达式
        result = parser.parseExpression("22 matches '\\d{2}'").getValue(Boolean.class);
        System.out.println("22 是否为两位数字 :" + result); //22 是否为两位数字 :true
    }

    @Test
    public void testlogicEl() {
        //解析器
        ExpressionParser parser = new SpelExpressionParser();

        //与操作
        boolean result = parser.parseExpression("true && true").getValue(Boolean.class);
        System.out.println("与操作:" + result);

        //或操作
        result = parser.parseExpression("true || false").getValue(Boolean.class);
        System.out.println("或操作:" + result);

        parser.parseExpression("true or false").getValue(Boolean.class);
        System.out.println("或操作(or 关键字):" + result);

        //非操作
        result = parser.parseExpression("!false").getValue(Boolean.class);
        System.out.println("非操作:" + result);
    }

    @Test
    public void testOperateEl() {
        ExpressionParser parser = new SpelExpressionParser();
        //加法运算
        Integer iResult = parser.parseExpression("2+3").getValue(Integer.class);
        System.out.println("加法运算:" + iResult);

        String sResult = parser.parseExpression("'Hi,'+'everybody'").getValue(String.class);
        System.out.println("字符串拼接运算:" + sResult);

        //减法运算
        iResult = parser.parseExpression("2-3").getValue(Integer.class);
        System.out.println("减法运算:" + iResult);

        //乘法运算
        iResult = parser.parseExpression("2*3").getValue(Integer.class);
        System.out.println("乘法运算:" + iResult);

        //除法运算
        iResult = parser.parseExpression("4/2").getValue(Integer.class);
        System.out.println("除法运算:" + iResult);

        Double dResult = parser.parseExpression("4/2.5").getValue(Double.class);
        System.out.println("除法运算:" + dResult);

        //求余运算
        iResult = parser.parseExpression("5%2").getValue(Integer.class);
        System.out.println("求余运算:" + iResult);

        //三元运算符
        boolean result=parser.parseExpression("(1+2) == 3?true:false").getValue(Boolean.class);
        System.out.println("result:"+result);
    }

    @Test
    public void testClassEl() {
        ExpressionParser parser = new SpelExpressionParser();

        //加载 java.lang.Integer
        Class integerClass=parser.parseExpression("T(Integer)").getValue(Class
                .class);
        System.out.println(integerClass==java.lang.Integer.class);

        //加载 net.deniro.spring4.spel.Account
        Class accountClass=parser.parseExpression("T(com.paic.phssp.springtest.spel.Account)")
                .getValue(Class
                        .class);
        System.out.println(accountClass==com.paic.phssp.springtest.spel.Account.class);

        //调用类静态方法
        double result = (double) parser.parseExpression("T(Math).abs(-2.5)").getValue();
        System.out.println("result:" + result);

        //创建对象操作符
        Account account=parser.parseExpression("new com.paic.phssp.springtest.spel.Account" +
                "('Deniro')").getValue(Account.class);
        System.out.println("name:"+account.getName());
    }

    @Test
    public void testVariableEl(){
        Account account = new Account("Deniro");

        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = new StandardEvaluationContext(account);

        //定义一个新变量,名为 newVal
        context.setVariable("newVal", "Jack");

        //获取变量 newVal 的值,并赋值给 User 的 name 属性
        parser.parseExpression("name=#newVal").getValue(context);
        System.out.println("getName:" + account.getName());

        //this 操作符表示集合中的某个元素
        List<Double> scores = new ArrayList<>();
        scores.addAll(Arrays.asList(23.1, 82.3, 55.9));
        context.setVariable("scores", scores);//在上下文中定义 scores 变量
        List<Double> scoresGreat80 = (List<Double>) parser.parseExpression("#scores.?[#this>80]").getValue(context);
        System.out.println("scoresGreat80:" + scoresGreat80);
    }

    @Test
    public void testCollectSelectEl(){
        //集合选择表达式
        ExpressionParser parser = new SpelExpressionParser();
        List list = (List) parser.parseExpression("{3,4,5}").getValue();

        //----------------过滤 list 集合中的元素
        final StandardEvaluationContext listContext = new StandardEvaluationContext(list);
        List<Integer> great4List = (List<Integer>) parser.parseExpression("?[#this>4]").getValue(listContext);
        System.out.println("great4List:" + great4List);

        //获取匹配元素中的第一个值
        Integer first = (Integer) parser.parseExpression("^[#this>2]").getValue(listContext);
        System.out.println("first:" + first);

        //获取匹配元素中的最后一个值
        Integer end = (Integer) parser.parseExpression("$[#this>2]") .getValue(listContext);
        System.out.println("end:" + end);

        //----------------过滤 Map
        Map<String, Double> rank = new HashMap<String, Double>();
        rank.put("Deniro", 96.5);
        rank.put("Jack", 85.3);
        rank.put("Lily", 91.1);

        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("Rank", rank);
        //value 大于 90
        Map<String,Double> rankGreat95= (Map<String, Double>) parser.parseExpression("#Rank.?[value>90]").getValue(context);
        System.out.println("rankGreat95:" + rankGreat95);

        //key 按字母顺序,排在 L 后面
        Map<String,Double> afterL= (Map<String, Double>) parser.parseExpression("#Rank.?[key>'L']").getValue(context);
        System.out.println("afterL:"+afterL);
    }
}

参考:

https://www.jianshu.com/p/5537b2c86acd

posted @ 2019-03-20 11:56  小传风  阅读(1704)  评论(0编辑  收藏  举报