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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM