• 20210429 SpEL表达式


    主要接口:

    • org.springframework.expression.Expression
    • org.springframework.expression.ExpressionParser
    • org.springframework.expression.EvaluationContext
    • org.springframework.expression.ParserContext
    • org.springframework.expression.spel.SpelParserConfiguration

    用法说明

    创建 SpEL 解析器:

    ExpressionParser parser = new SpelExpressionParser();
    

    场景

    Company 内有 PersonPerson 内有 BirthPlace

    @Data
    public class Company {
        private String companyName;
        private List<Person> personList;
        private Map<String, Person> deptCodeLeaderMap;
    
        public boolean isMember(String name) {
            for (Person person : personList) {
                if (Objects.equals(name, person.getName())) {
                    return true;
                }
            }
            return false;
        }
    }
    
    @NoArgsConstructor
    @Data
    public class Person {
        private String name;
        private Integer age;
        private Date birthday;
        private BirthPlace birthPlace;
        private String[] books;
    
        public Person(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    
        public boolean hasBook(String book) {
            for (String item : books) {
                if (Objects.equals(item, book)) {
                    return true;
                }
            }
            return false;
        }
    }
    
    @Data
    public class BirthPlace {
        private String city;
        private String country;
    }
    

    字面值(Literal expressions)

    @Test
    public void testLiteralExpressions() {
    
        // 字符串
        String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();    // Hello World
        // double
        double d = (double) parser.parseExpression("1.234").getValue(); // 1.234
        // double,科学计数法
        double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();   // 6.0221415E23
        // 16 进制
        int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();   // 2147483647
        // 布尔值
        boolean trueValue = (Boolean) parser.parseExpression("true").getValue();    // true
        // NULL
        Object nullValue = parser.parseExpression("null").getValue();   // null
    }
    

    Properties, Arrays, Lists, Maps, and Indexers

    类属性(Properties)

    @Test
    public void testProperties() {
    
        int year = (Integer) parser.parseExpression("birthday.year + 1900").getValue(person);   // 2012
    
        String city = (String) parser.parseExpression("birthPlace.city").getValue(person);  // city0
    }
    

    列表(ArrayList)

    @Test
    public void testArrayList() {
        context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        String book2 = parser.parseExpression("books[2]").getValue(context, person, String.class);  // book2
        String person0Name = parser.parseExpression("personList[0].name").getValue(context, company, String.class);     // person0
        String person0Book2 = parser.parseExpression("personList[0].books[1]").getValue(context, company, String.class);    // book1
    
    
        // parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").setValue(context, company, "country0xx");    // org.springframework.expression.spel.SpelEvaluationException: EL1010E: Property or field 'country' cannot be set on object of type 'study.spel.bean.BirthPlace' - maybe not public or not writable?
    
    }
    

    映射(Map)

    @Test
    public void testMap() {
        Person dept0Leader = parser.parseExpression("deptCodeLeaderMap['dept0']").getValue(company, Person.class);      // Person(name=person0 ...
    
        String city = parser.parseExpression("deptCodeLeaderMap['dept0'].birthPlace.city").getValue(company, String.class);     // city0
    
        // 设置值
        parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").setValue(company, "country0xx");
    
        String dept1Country = parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").getValue(company, String.class);      // country0xx
    }
    

    内联列表(Inline Lists)

    @Test
    public void testInlineLists() {
        context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
        // evaluates to a Java list containing the four numbers
        List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);    // [1, 2, 3, 4]
    
        List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);    // [[a, b], [x, y]]
    
    }
    

    内联映射(Inline Maps)

    @Test
    public void testInlineMaps() {
        context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
        // 单层
        Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context);    // {name=Nikola, dob=10-July-1856}
    
        // 多层嵌套
        Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context);     // {name={first=Nikola, last=Tesla}, dob={day=10, month=July, year=1856}}
    
    }
    

    数组构造器(Array Construction)

    @Test
    public void testArrayConstruction() {
        context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
        int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context);    // [0, 0, 0, 0]
    
        // Array with initializer
        int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context);  // [1, 2, 3]
    
        // Multi dimensional array
        int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);     // [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
    }
    

    实例方法(Methods)

    @Test
    public void testMethods() {
    
        String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);     // bc
    
        boolean hasBook = parser.parseExpression("hasBook('book0')").getValue(person, Boolean.class);   // true
    }
    

    运算符(Operators)

    关系运算符(Relational Operators)

    /**
         * Operators - Relational Operators
         * 
         * lt(<)
         * gt(>)
         * le(<=)
         * ge(>=)
         * eq(==)
         * ne(!=)
         * div(/)
         * mod(%)
         * not(!)
         */
    @Test
    public void testOperatorsRelationalOperators() {
    
        boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);
        boolean trueValueEq = parser.parseExpression("2 eq 2").getValue(Boolean.class);
    
        boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);
    
        boolean trueValue2 = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
    
        // ----------------------------------------------------------------- //
    
        boolean falseValue2 = parser.parseExpression("'xyz' instanceof T(Integer)").getValue(Boolean.class);
    
        boolean trueValue3 = parser.parseExpression("'5.00' matches '^-?\d+(\.\d{2})?$'").getValue(Boolean.class);
    
        boolean falseValue3 = parser.parseExpression("'5.0067' matches '^-?\d+(\.\d{2})?$'").getValue(Boolean.class);
    }
    

    逻辑运算符(Logical Operators)

    /**
         * Operators - Logical Operators
         * 
         * and (&&)
         * or (||)
         * not (!)
         */
    @Test
    public void testOperatorsLogicalOperators() {
    
        // -- AND -- //
    
        boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);
    
        String expression = "isMember('person0') and isMember('person1')";
        boolean trueValue = parser.parseExpression(expression).getValue(company, Boolean.class);
    
        // -- OR -- //
    
        boolean trueValue2 = parser.parseExpression("true or false").getValue(Boolean.class);
    
        expression = "isMember('person0') or isMember('person1')";
        boolean trueValue3 = parser.parseExpression(expression).getValue(company, Boolean.class);
    
        // -- NOT -- //
        boolean falseValue2 = parser.parseExpression("!true").getValue(Boolean.class);
    
        // -- AND and NOT -- //
        expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
        boolean falseValue3 = parser.parseExpression(expression).getValue(company, Boolean.class);
    
    }
    

    数学运算符(Mathematical Operators)

    @Test
    public void testMathematicalOperators() {
        // 加法
        int two = parser.parseExpression("1 + 1").getValue(Integer.class);  // 2
        // 字符串拼接
        String testString = parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class);  // 'test string'
    
        // 减法
        int four = parser.parseExpression("1 - -3").getValue(Integer.class);  // 4
        double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class);  // -9000
    
        // 乘法
        int six = parser.parseExpression("-2 * -3").getValue(Integer.class);  // 6
        double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class);  // 24.0
    
        // 除法
        int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class);  // -2
        double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);  // 1.0
    
        // 取模
        int three = parser.parseExpression("7 % 4").getValue(Integer.class);  // 3
        int one1 = parser.parseExpression("8 / 5 % 2").getValue(Integer.class);  // 1
    
        // 运算符优先级
        int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);  // -21
    }
    

    赋值运算符(The Assignment Operator)

    /**
         * Operators - The Assignment Operator
         */
    @Test
    public void testOperatorsAssignment() {
        context = SimpleEvaluationContext.forReadWriteDataBinding().build();
    
        // 会设置 person 的 name 属性为 Aleksandar Seovic
        // parser.parseExpression("name").setValue(context, person, "Aleksandar Seovic");
    
        // 会设置 person 的 name 属性为 Aleksandar Seovic
        String aleks = parser.parseExpression("name = 'Aleksandar Seovic'").getValue(context, person, String.class);
    
    }
    

    类(Types)

    @Test
    public void testTypes() {
        Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);    // class java.util.Date
    
        Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);  // class java.lang.String
    
        boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR").getValue(Boolean.class);  // true
    
    }
    

    构造器(Constructors)

    @Test
    public void testConstructors() {
        // 通过构造器创建 Person 实例
        Person einstein = parser.parseExpression("new study.spel.bean.Person('Albert Einstein', 20)").getValue(Person.class);
    
        // 调用 company 的 personList 的 add 方法,并加入新建 person
        parser.parseExpression("PersonList.add(new study.spel.bean.Person('Albert Einstein', 20))").getValue(company);
    
    }
    

    变量(Variables)

    /**
         * Variables
         *
         * 有效的变量名称必须由以下一个或多个受支持的字符组成:
         * letters: A to Z and a to z
         * digits: 0 to 9
         * underscore: _
         * dollar sign: $
         */
    @Test
    public void testVariables() {
        context = SimpleEvaluationContext.forReadWriteDataBinding().build();
        // 设置变量
        context.setVariable("newName", "Mike Tesla");
        // 通过 #variableName 使用变量
        parser.parseExpression("name = #newName").getValue(context, person);
        System.out.println(person.getName());  // "Mike Tesla"
    }
    

    #this#root

    @Test
    public void testVariablesThisRoot() {
        context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
        List<Integer> primes = new ArrayList();
        primes.addAll(Arrays.asList(2, 3, 5, 7, 11, 13, 17));
        context.setVariable("primes", primes);
    
        // 筛选 List 中大于 10 的
        // [11, 13, 17]
        List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression("#primes.?[#this>10]").getValue(context);
    }
    

    函数(Functions)

    @Test
    public void testFunctions() throws NoSuchMethodException {
        context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        // 设置函数变量
        context.setVariable("parseInt", Integer.class.getDeclaredMethod("parseInt", String.class));
    
        // 使用函数变量,转为整型 100
        Integer parseInt = parser.parseExpression("#parseInt('100')").getValue(context, Integer.class);
    }
    

    Bean 引用(Bean References)

    @Test
    public void testBeanReferences() {
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setBeanResolver(new MyBeanResolver());
    
        // 获取 Bean
        // 会调用 org.spring.samples.spel.inventor.MyBeanResolver.resolve
        Object bean = parser.parseExpression("@something").getValue(context);
    
        // 获取 Bean 工厂
        Object bean2 = parser.parseExpression("&foo").getValue(context);
    }
    

    三元运算符(Ternary Operator)

    @Test
    public void testTernaryOperator() {
        context = SimpleEvaluationContext.forReadWriteDataBinding().withMethodResolvers(DataBindingMethodResolver.forInstanceMethodInvocation()).build();
        context.setVariable("queryName", "person0");
    
        parser.parseExpression("companyName").setValue(context, company, "IEEE");
    
    
        String expression = "isMember(#queryName)? #queryName + ' is a member of the ' " + "+ companyName + ' Society' : #queryName + ' is not a member of the ' + companyName + ' Society'";
    
        String queryResultString = parser.parseExpression(expression).getValue(context, company, String.class); // person0 is a member of the IEEE Society
    }
    

    Elvis 运算符(The Elvis Operator)

    @Test
    public void testElvisOperator() {
        context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
        String name1 = parser.parseExpression("name?:'Unknown'").getValue(new Person(), String.class);  // 'Unknown'
    
    
        String name2 = parser.parseExpression("name?:'Elvis Presley'").getValue(context, person, String.class); // person0
    
        person.setName(null);
        String name3 = parser.parseExpression("name?:'Elvis Presley'").getValue(context, person, String.class);     // Elvis Presley
    }
    

    空安全导航操作符(Safe Navigation Operator)

    /**
         * Safe Navigation Operator
         * 
         * 避免空指针异常
         */
    @Test
    public void testSafeNavigationOperator() {
        context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
        // city0
        String city1 = parser.parseExpression("birthPlace?.city").getValue(context, person, String.class);
    
        person.setBirthPlace(null);
        String city2 = parser.parseExpression("birthPlace?.city").getValue(context, person, String.class);  // null
    
        String city3 = parser.parseExpression("birthPlace.city").getValue(context, person, String.class);  // 抛出异常:SpelEvaluationException
    }
    

    集合选择(Collection Selection)

    @Test
    public void testCollectionSelection() {
    
        List<Person> list = (List<Person>) parser.parseExpression("personList.?[birthPlace.city == 'city0']").getValue(company);
    
        /*
             * map.?[value<27]  输入值小于27
             * .^[selectionExpression]  获得与所选内容匹配的第一个条目
             * .$[selectionExpression]  获得与所选内容匹配的最后一个条目
             */
    
    }
    

    集合投影(Collection Projection)

    @Test
    public void testCollectionProjection() {
        List placesOfBirth = (List) parser.parseExpression("personList.![birthPlace.city]").getValue(company);  // [city0, city1]
    }
    

    表达式模板(Expression templating)

    /**
         * Expression templating
         */
    @Test
    public void testExpressionTemplating() {
    
        String randomPhrase = parser.parseExpression("random number is #{T(java.lang.Math).random()}", new TemplateParserContext()).getValue(String.class);     // random number is 0.22093794778910136
    
    }
    

    测试案例

    项目依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.20</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13</version>
    </dependency>
    

    代码

    所有测试代码
    
    import org.junit.Before;
    import org.junit.Test;
    import org.spring.samples.spel.inventor.MyBeanResolver;
    import org.springframework.expression.EvaluationContext;
    import org.springframework.expression.ExpressionParser;
    import org.springframework.expression.common.TemplateParserContext;
    import org.springframework.expression.spel.standard.SpelExpressionParser;
    import org.springframework.expression.spel.support.DataBindingMethodResolver;
    import org.springframework.expression.spel.support.SimpleEvaluationContext;
    import org.springframework.expression.spel.support.StandardEvaluationContext;
    import study.spel.bean.BirthPlace;
    import study.spel.bean.Company;
    import study.spel.bean.Person;
    
    import java.util.*;
    
    
    public class Test3 {
        ExpressionParser parser;
        EvaluationContext context;
        Company company;
        Person person;
        BirthPlace birthPlace;
    
    
        @Before
        public void before() {
            parser = new SpelExpressionParser();
    
            company = new Company();
            person = new Person();
            birthPlace = new BirthPlace();
    
            birthPlace.setCity("city0");
            birthPlace.setCountry("country0");
    
            Calendar calendar = Calendar.getInstance();
            calendar.set(2012, 11, 12); // 2012-12-12 , month 从 0 开始
            // System.out.println(calendar.getTime());  // Wed Dec 12 09:52:23 CST 2012
    
            person.setName("person0");
            person.setBirthday(calendar.getTime());
            person.setBirthPlace(birthPlace);
            person.setBooks(new String[]{"book0", "book1", "book2"});
    
            Person person2 = new Person();
            person2.setName("person1");
            BirthPlace birthPlace2 = new BirthPlace();
    
            birthPlace2.setCity("city1");
            birthPlace2.setCountry("country1");
    
            Calendar calendar2 = Calendar.getInstance();
            calendar2.set(2022, 11, 12); // 2012-12-12 , month 从 0 开始
    
            person2.setName("person1");
            person2.setBirthday(calendar2.getTime());
            person2.setBirthPlace(birthPlace2);
            person2.setBooks(new String[]{"book20", "book21", "book22"});
    
    
            company.setCompanyName("company0");
            List<Person> personList = new ArrayList<>();
            personList.add(person);
            personList.add(person2);
            company.setPersonList(personList);
    
            Map<String, Person> deptCodeLeaderMap = new HashMap<>();
            deptCodeLeaderMap.put("dept0", person);
            deptCodeLeaderMap.put("dept1", person2);
            company.setDeptCodeLeaderMap(deptCodeLeaderMap);
        }
    
    
        // society - company
        // Inventor - person
        // placeOfBirth - birthPlace
        // officers - deptCodeLeaderMap
    
        /**
         * Expression templating
         */
        @Test
        public void testExpressionTemplating() {
    
            String randomPhrase = parser.parseExpression("random number is #{T(java.lang.Math).random()}", new TemplateParserContext()).getValue(String.class);     // random number is 0.22093794778910136
    
        }
    
        /**
         * Collection Projection
         */
        @Test
        public void testCollectionProjection() {
            List placesOfBirth = (List) parser.parseExpression("personList.![birthPlace.city]").getValue(company);  // [city0, city1]
        }
    
    
        /**
         * Collection Selection
         */
        @Test
        public void testCollectionSelection() {
    
            List<Person> list = (List<Person>) parser.parseExpression("personList.?[birthPlace.city == 'city0']").getValue(company);
    
            /*
             * map.?[value<27]  输入值小于27
             * .^[selectionExpression]  获得与所选内容匹配的第一个条目
             * .$[selectionExpression]  获得与所选内容匹配的最后一个条目
             */
    
        }
    
    
        /**
         * Safe Navigation Operator
         *
         * 避免空指针异常
         */
        @Test
        public void testSafeNavigationOperator() {
            context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
            // city0
            String city1 = parser.parseExpression("birthPlace?.city").getValue(context, person, String.class);
    
            person.setBirthPlace(null);
            String city2 = parser.parseExpression("birthPlace?.city").getValue(context, person, String.class);  // null
    
            String city3 = parser.parseExpression("birthPlace.city").getValue(context, person, String.class);  // 抛出异常:SpelEvaluationException
        }
    
    
        /**
         * The Elvis Operator
         */
        @Test
        public void testElvisOperator() {
            context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
            String name1 = parser.parseExpression("name?:'Unknown'").getValue(new Person(), String.class);  // 'Unknown'
    
    
            String name2 = parser.parseExpression("name?:'Elvis Presley'").getValue(context, person, String.class); // person0
    
            person.setName(null);
            String name3 = parser.parseExpression("name?:'Elvis Presley'").getValue(context, person, String.class);     // Elvis Presley
        }
    
        /**
         * Ternary Operator (If-Then-Else)
         */
        @Test
        public void testTernaryOperator() {
            context = SimpleEvaluationContext.forReadWriteDataBinding().withMethodResolvers(DataBindingMethodResolver.forInstanceMethodInvocation()).build();
            context.setVariable("queryName", "person0");
    
            parser.parseExpression("companyName").setValue(context, company, "IEEE");
    
    
            String expression = "isMember(#queryName)? #queryName + ' is a member of the ' " + "+ companyName + ' Society' : #queryName + ' is not a member of the ' + companyName + ' Society'";
    
            String queryResultString = parser.parseExpression(expression).getValue(context, company, String.class); // person0 is a member of the IEEE Society
        }
    
        /**
         * Bean References
         */
        @Test
        public void testBeanReferences() {
            StandardEvaluationContext context = new StandardEvaluationContext();
            context.setBeanResolver(new MyBeanResolver());
    
            // 获取 Bean
            // 会调用 org.spring.samples.spel.inventor.MyBeanResolver.resolve
            Object bean = parser.parseExpression("@something").getValue(context);
    
            // 获取 Bean 工厂
            Object bean2 = parser.parseExpression("&foo").getValue(context);
        }
    
    
        /**
         * Functions
         */
        @Test
        public void testFunctions() throws NoSuchMethodException {
            context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
            // 设置函数变量
            context.setVariable("parseInt", Integer.class.getDeclaredMethod("parseInt", String.class));
    
            // 使用函数变量,转为整型 100
            Integer parseInt = parser.parseExpression("#parseInt('100')").getValue(context, Integer.class);
        }
    
        /**
         * Variables - The #this and #root Variables
         */
        @Test
        public void testVariablesThisRoot() {
            context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
            List<Integer> primes = new ArrayList();
            primes.addAll(Arrays.asList(2, 3, 5, 7, 11, 13, 17));
            context.setVariable("primes", primes);
    
            // 筛选 List 中大于 10 的
            // [11, 13, 17]
            List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression("#primes.?[#this>10]").getValue(context);
        }
    
    
        /**
         * Variables
         *
         * 有效的变量名称必须由以下一个或多个受支持的字符组成:
         * letters: A to Z and a to z
         * digits: 0 to 9
         * underscore: _
         * dollar sign: $
         */
        @Test
        public void testVariables() {
            context = SimpleEvaluationContext.forReadWriteDataBinding().build();
            // 设置变量
            context.setVariable("newName", "Mike Tesla");
            // 通过 #variableName 使用变量
            parser.parseExpression("name = #newName").getValue(context, person);
            System.out.println(person.getName());  // "Mike Tesla"
        }
    
        /**
         * Constructors
         */
        @Test
        public void testConstructors() {
            // 通过构造器创建 Person 实例
            Person einstein = parser.parseExpression("new study.spel.bean.Person('Albert Einstein', 20)").getValue(Person.class);
    
            // 调用 company 的 personList 的 add 方法,并加入新建 person
            parser.parseExpression("PersonList.add(new study.spel.bean.Person('Albert Einstein', 20))").getValue(company);
    
        }
    
        /**
         * Types
         */
        @Test
        public void testTypes() {
            Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);    // class java.util.Date
    
            Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);  // class java.lang.String
    
            boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR").getValue(Boolean.class);  // true
    
        }
    
    
    
        /**
         * Operators - The Assignment Operator
         */
        @Test
        public void testOperatorsAssignment() {
            context = SimpleEvaluationContext.forReadWriteDataBinding().build();
    
            // 会设置 person 的 name 属性为 Aleksandar Seovic
            // parser.parseExpression("name").setValue(context, person, "Aleksandar Seovic");
    
            // 会设置 person 的 name 属性为 Aleksandar Seovic
            String aleks = parser.parseExpression("name = 'Aleksandar Seovic'").getValue(context, person, String.class);
    
        }
    
        /**
         * Operators - Mathematical Operators
         */
        @Test
        public void testMathematicalOperators() {
            // 加法
            int two = parser.parseExpression("1 + 1").getValue(Integer.class);  // 2
            // 字符串拼接
            String testString = parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class);  // 'test string'
    
            // 减法
            int four = parser.parseExpression("1 - -3").getValue(Integer.class);  // 4
            double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class);  // -9000
    
            // 乘法
            int six = parser.parseExpression("-2 * -3").getValue(Integer.class);  // 6
            double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class);  // 24.0
    
            // 除法
            int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class);  // -2
            double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);  // 1.0
    
            // 取模
            int three = parser.parseExpression("7 % 4").getValue(Integer.class);  // 3
            int one1 = parser.parseExpression("8 / 5 % 2").getValue(Integer.class);  // 1
    
            // 运算符优先级
            int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);  // -21
        }
    
        /**
         * Operators - Logical Operators
         * <p>
         * and (&&)
         * or (||)
         * not (!)
         */
        @Test
        public void testOperatorsLogicalOperators() {
    
            // -- AND -- //
    
            boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);
    
            String expression = "isMember('person0') and isMember('person1')";
            boolean trueValue = parser.parseExpression(expression).getValue(company, Boolean.class);
    
            // -- OR -- //
    
            boolean trueValue2 = parser.parseExpression("true or false").getValue(Boolean.class);
    
            expression = "isMember('person0') or isMember('person1')";
            boolean trueValue3 = parser.parseExpression(expression).getValue(company, Boolean.class);
    
            // -- NOT -- //
            boolean falseValue2 = parser.parseExpression("!true").getValue(Boolean.class);
    
            // -- AND and NOT -- //
            expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
            boolean falseValue3 = parser.parseExpression(expression).getValue(company, Boolean.class);
    
        }
    
        /**
         * Operators - Relational Operators
         * <p>
         * lt(<)
         * gt(>)
         * le(<=)
         * ge(>=)
         * eq(==)
         * ne(!=)
         * div(/)
         * mod(%)
         * not(!)
         */
        @Test
        public void testOperatorsRelationalOperators() {
    
            boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);
            boolean trueValueEq = parser.parseExpression("2 eq 2").getValue(Boolean.class);
    
            boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);
    
            boolean trueValue2 = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
    
            // ----------------------------------------------------------------- //
    
            boolean falseValue2 = parser.parseExpression("'xyz' instanceof T(Integer)").getValue(Boolean.class);
    
            boolean trueValue3 = parser.parseExpression("'5.00' matches '^-?\d+(\.\d{2})?$'").getValue(Boolean.class);
    
            boolean falseValue3 = parser.parseExpression("'5.0067' matches '^-?\d+(\.\d{2})?$'").getValue(Boolean.class);
        }
    
        /**
         * Methods
         */
        @Test
        public void testMethods() {
    
            String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);     // bc
    
            boolean hasBook = parser.parseExpression("hasBook('book0')").getValue(person, Boolean.class);   // true
        }
    
    
        /**
         * Array Construction
         */
        @Test
        public void testArrayConstruction() {
            context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
            int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context);    // [0, 0, 0, 0]
    
            // Array with initializer
            int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context);  // [1, 2, 3]
    
            // Multi dimensional array
            int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);     // [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
        }
    
        /**
         * Inline Maps
         */
        @Test
        public void testInlineMaps() {
            context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
            // 单层
            Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context);    // {name=Nikola, dob=10-July-1856}
    
            // 多层嵌套
            Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context);     // {name={first=Nikola, last=Tesla}, dob={day=10, month=July, year=1856}}
    
        }
    
        /**
         * Inline Lists
         */
        @Test
        public void testInlineLists() {
            context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
    
            // evaluates to a Java list containing the four numbers
            List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);    // [1, 2, 3, 4]
    
            List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);    // [[a, b], [x, y]]
    
        }
    
        @Test
        public void testMap() {
            Person dept0Leader = parser.parseExpression("deptCodeLeaderMap['dept0']").getValue(company, Person.class);      // Person(name=person0 ...
    
            String city = parser.parseExpression("deptCodeLeaderMap['dept0'].birthPlace.city").getValue(company, String.class);     // city0
    
            // 设置值
            parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").setValue(company, "country0xx");
    
            String dept1Country = parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").getValue(company, String.class);      // country0xx
        }
    
    
        @Test
        public void testArrayList() {
            context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
            String book2 = parser.parseExpression("books[2]").getValue(context, person, String.class);  // book2
            String person0Name = parser.parseExpression("personList[0].name").getValue(context, company, String.class);     // person0
            String person0Book2 = parser.parseExpression("personList[0].books[1]").getValue(context, company, String.class);    // book1
    
    
            // parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").setValue(context, company, "country0xx");    // org.springframework.expression.spel.SpelEvaluationException: EL1010E: Property or field 'country' cannot be set on object of type 'study.spel.bean.BirthPlace' - maybe not public or not writable?
    
        }
    
    
        /**
         * Properties, Arrays, Lists, Maps, and Indexers
         */
        @Test
        public void testProperties() {
    
            int year = (Integer) parser.parseExpression("birthday.year + 1900").getValue(person);   // 2012
    
            String city = (String) parser.parseExpression("birthPlace.city").getValue(person);  // city0
        }
    
        /**
         * 字面值
         */
        @Test
        public void testLiteralExpressions() {
    
            // 字符串
            String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();    // Hello World
            // double
            double d = (double) parser.parseExpression("1.234").getValue(); // 1.234
            // double,科学计数法
            double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();   // 6.0221415E23
            // 16 进制
            int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();   // 2147483647
            // 布尔值
            boolean trueValue = (Boolean) parser.parseExpression("true").getValue();    // true
            // NULL
            Object nullValue = parser.parseExpression("null").getValue();   // null
        }
    }
    

    参考资料

  • 相关阅读:
    hdu 1201 18岁生日
    线性代数
    关于pymongo的一些说明
    利用数组进行数据处理
    通用函数:快速的元素级数组函数
    IPython:一种交互式计算和开发环境
    关于一道面试题的思考
    wireshark中的抓包过滤器和显示过滤器
    wireshark推荐书籍
    wireshark 找不到网卡的解决办法
  • 原文地址:https://www.cnblogs.com/huangwenjie/p/14719521.html
Copyright © 2020-2023  润新知