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
    }
}

参考资料

posted @ 2021-04-29 20:24  流星<。)#)))≦  阅读(195)  评论(0编辑  收藏  举报