【第27章】spring-spel进阶版


前言

书接上回,这次主要讲述4.3. Language Reference中SPEL表达式的用法,有干货哦,记得看到最后,文章可能有点长,你忍一忍。


准备

package org.example.spel.po;

/**
 * Create by zjg on 2024/4/21
 */
import java.util.Date;
import java.util.GregorianCalendar;

public class Inventor {

    private String name;
    private String nationality;
    private String[] inventions;
    private Date birthdate;
    private PlaceOfBirth placeOfBirth;

    public Inventor(String name, String nationality) {
        GregorianCalendar c= new GregorianCalendar();
        this.name = name;
        this.nationality = nationality;
        this.birthdate = c.getTime();
    }

    public Inventor(String name, Date birthdate, String nationality) {
        this.name = name;
        this.nationality = nationality;
        this.birthdate = birthdate;
    }

    public Inventor() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNationality() {
        return nationality;
    }

    public void setNationality(String nationality) {
        this.nationality = nationality;
    }

    public Date getBirthdate() {
        return birthdate;
    }

    public void setBirthdate(Date birthdate) {
        this.birthdate = birthdate;
    }

    public PlaceOfBirth getPlaceOfBirth() {
        return placeOfBirth;
    }

    public void setPlaceOfBirth(PlaceOfBirth placeOfBirth) {
        this.placeOfBirth = placeOfBirth;
    }

    public void setInventions(String[] inventions) {
        this.inventions = inventions;
    }

    public String[] getInventions() {
        return inventions;
    }
    @Override
    public String toString() {
        return "Inventor{" +
                "name='" + name + '\'' +
                ", nationality='" + nationality + '\'' +
                ", inventions=" + Arrays.toString(inventions) +
                ", birthdate=" + birthdate +
                ", placeOfBirth=" + placeOfBirth +
                '}';
    }
}

package org.example.spel.po;

/**
 * Create by zjg on 2024/4/21
 */
public class PlaceOfBirth {

    private String city;
    private String country;

    public PlaceOfBirth(String city) {
        this.city=city;
    }

    public PlaceOfBirth(String city, String country) {
        this(city);
        this.country = country;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String s) {
        this.city = s;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}

package org.example.spel.po;

/**
 * Create by zjg on 2024/4/21
 */
import java.util.*;

public class Society {

    private String name;

    public static String Advisors = "advisors";
    public static String President = "president";

    private List<Inventor> members = new ArrayList<Inventor>();
    private Map officers = new HashMap();

    public List getMembers() {
        return members;
    }
    public void addMembers(Inventor inventor) {
        this.members.add(inventor);
    }

    public Map getOfficers() {
        return officers;
    }
	public void addOfficers(String key,Object value) {
        this.officers.put(key,value);
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isMember(String name) {
        for (Inventor inventor : members) {
            if (inventor.getName().equals(name)) {
                return true;
            }
        }
        return false;
    }
}

4.3. Language Reference

本节介绍Spring表达式语言的工作原理。它涵盖以下主题:

  • Literal Expressions
  • Properties, Arrays, Lists, Maps, and Indexers
  • Inline Lists
  • Inline Maps
  • Array Construction
  • Methods
  • Operators
  • Types
  • Constructors
  • Variables
  • Functions
  • Bean References
  • Ternary Operator (If-Then-Else)
  • The Elvis Operator
  • Safe Navigation Operator

4.3.1. Literal Expressions

这一步就是说无论什么类型的数据,spel都能解析并且转换出来。

package org.example.spel.language;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * Create by zjg on 2024/4/22
 */
public class LiteralExpressions {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();// evals to "Hello World"
        double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();// evals to 6.0221415E23
        int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();// evals to 2147483647
        boolean trueValue = (Boolean) parser.parseExpression("true").getValue();// evals to true
        Object nullValue = parser.parseExpression("null").getValue();// evals to null
        System.out.println(helloWorld);
        System.out.println(avogadrosNumber);
        System.out.println(maxValue);
        System.out.println(trueValue);
        System.out.println(nullValue);
    }
}


4.3.2. Properties, Arrays, Lists, Maps, and Indexers

package org.example.spel.language;

import org.example.spel.po.Inventor;
import org.example.spel.po.PlaceOfBirth;
import org.example.spel.po.Society;
import org.junit.jupiter.api.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import java.util.Date;

/**
 * Create by zjg on 2024/4/22
 */
public class Properties {
    ExpressionParser parser = new SpelExpressionParser();
    @Test
    public void test (){
        Inventor inventor = new Inventor();
        inventor.setBirthdate(new Date());
        inventor.setPlaceOfBirth(new PlaceOfBirth("beijing"));
        int year = (Integer) parser.parseExpression("birthdate.year + 1900").getValue(inventor);// evals to 2024
        String city = (String) parser.parseExpression("placeOfBirth.city").getValue(inventor);// evals to beijing
        System.out.println(year);
        System.out.println(city);
    }
    @Test
    public void arrayAndList (){
        EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        Inventor tesla=new Inventor();
        // Inventions Array
        tesla.setInventions(new String[]{"","","","Induction motor","","","Wireless communication"});
        String invention3 = parser.parseExpression("inventions[3]").getValue(context, tesla, String.class);// evaluates to "Induction motor"
        // Members List
        tesla.setName("Nikola Tesla");
        Society society=new Society();
        society.addMembers(tesla);
        String name = parser.parseExpression("members[0].name").getValue(context, society, String.class);// evaluates to "Nikola Tesla"
        // List and Array navigation
        String invention6 = parser.parseExpression("members[0].inventions[6]").getValue(context, society, String.class);// evaluates to "Wireless communication"
        System.out.println(invention3);
        System.out.println(name);
        System.out.println(invention6);
    }
    @Test
    public void dictionary (){
        Society societyContext = new Society();
        Inventor president=new Inventor();
        PlaceOfBirth placeOfBirth = new PlaceOfBirth("Shanghai");
        president.setPlaceOfBirth(placeOfBirth);
        societyContext.addOfficers("president",president);
        // Officer's Dictionary
        Inventor pupin = parser.parseExpression("officers['president']").getValue(
                societyContext, Inventor.class);// evaluates to "Idvor"
        String city = parser.parseExpression("officers['president'].placeOfBirth.city").getValue(
                societyContext, String.class);// evaluates to "Shanghai"
        // setting values
        Inventor[] advisors={president};
        societyContext.addOfficers("advisors",advisors);
        parser.parseExpression("officers['advisors'][0].placeOfBirth.country").setValue(
                societyContext, "Croatia");
        System.out.println(pupin);
        System.out.println(city);
    }
}

4.3.3. Inline Lists

package org.example.spel.language;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import java.util.Collections;
import java.util.List;

/**
 * Create by zjg on 2024/4/22
 */
public class InlineLists {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        List<Object> context = Collections.emptyList();
        // 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]]
        System.out.println(numbers);
        System.out.println(listOfLists);
    }
}


4.3.4. Inline Maps

package org.example.spel.language;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import java.util.Collections;
import java.util.Map;

/**
 * Create by zjg on 2024/4/22
 */
public class InlineMaps {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        Map<Object, Object> context = Collections.emptyMap();
        // evaluates to a Java map containing the two entries
        Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context);
        Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context);
        System.out.println(inventorInfo);//{name=Nikola, dob=10-July-1856}
        System.out.println(mapOfMaps);//{name={first=Nikola, last=Tesla}, dob={day=10, month=July, year=1856}}
    }
}

4.3.5. Array Construction

package org.example.spel.language;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * Create by zjg on 2024/4/22
 */
public class ArrayConstruction {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        int[] context=new int[5];
        int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context);
        // Array with initializer
        int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context);
        // Multi dimensional array
        int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);
        System.out.println(numbers1.length);//4
        System.out.println(numbers2.length);//3
        System.out.println(numbers3.length);//4
    }
}

4.3.6. Methods

package org.example.spel.language;

import org.example.spel.po.Inventor;
import org.example.spel.po.Society;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * Create by zjg on 2024/4/22
 */
public class Methods {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);// string literal, evaluates to "bc"
        Society societyContext = new Society();
        Inventor inventor=new Inventor();
        inventor.setName("Mihajlo Pupin");
        societyContext.addMembers(inventor);
        boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(societyContext, Boolean.class);// evaluates to true
        System.out.println(bc);
        System.out.println(isMember);
    }
}

4.3.7. Operators

package org.example.spel.language;

import org.example.spel.po.Inventor;
import org.example.spel.po.Society;
import org.junit.jupiter.api.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;

/**
 * Create by zjg on 2024/4/23
 */
class CustomValue implements Comparable<CustomValue> {
    private Integer value;

    public CustomValue(Integer value) {
        this.value = value;
    }

    public Integer getValue() {
        return value;
    }

    @Override
    public int compareTo(CustomValue o) {
        return value.compareTo(o.getValue());
    }
}

public class Operators {
    ExpressionParser parser = new SpelExpressionParser();

    @Test
    public void relationalOperators() {
        // evaluates to true
        boolean trueValue1 = parser.parseExpression("2 == 2").getValue(Boolean.class);
        // evaluates to false
        boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);
        // evaluates to true
        boolean trueValue2 = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
        // uses CustomValue:::compareTo
        boolean trueValue3 = parser.parseExpression("new org.example.spel.language.CustomValue(1) < new org.example.spel.language.CustomValue(2)").getValue(Boolean.class);
        System.out.println(trueValue1);
        System.out.println(falseValue);
        System.out.println(trueValue2);
        System.out.println(trueValue3);

        // evaluates to false
        boolean falseValue1 = parser.parseExpression("'xyz' instanceof T(Integer)").getValue(Boolean.class);
        // evaluates to true
        boolean trueValue4 = parser.parseExpression("'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
        // evaluates to false
        boolean falseValue2 = parser.parseExpression("'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
        System.out.println(falseValue1);
        System.out.println(trueValue4);
        System.out.println(falseValue2);
    }

    @Test
    public void logicalOperators() {
        Society societyContext=new Society();
        Inventor in1=new Inventor();
        Inventor in2=new Inventor();
        in1.setName("Nikola Tesla");
        in2.setName("Mihajlo Pupin");
        societyContext.addMembers(in1);
        societyContext.addMembers(in2);
        // -- AND --
        // evaluates to false
        System.out.println(parser.parseExpression("true and false").getValue(Boolean.class));;
        // evaluates to true
        String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";
        System.out.println(parser.parseExpression(expression).getValue(societyContext, Boolean.class));
        // -- OR --
        // evaluates to true
        System.out.println(parser.parseExpression("true or false").getValue(Boolean.class));
        // evaluates to true
        String expression1 = "isMember('Nikola Tesla') or isMember('Albert Einstein')";
        System.out.println(parser.parseExpression(expression1).getValue(societyContext, Boolean.class));
        // -- NOT --
        // evaluates to false
        System.out.println(parser.parseExpression("!true").getValue(Boolean.class));
        // -- AND and NOT --
        String expression2 = "!isMember('Mihajlo Pupin')";
        System.out.println(parser.parseExpression(expression2).getValue(societyContext, Boolean.class));
    }
    @Test
    public void mathematicalOperators(){
        // Addition
        int two = parser.parseExpression("1 + 1").getValue(Integer.class);  // 2
        String testString = parser.parseExpression(
                "'test' + ' ' + 'string'").getValue(String.class);  // 'test string'
        // Subtraction
        int four = parser.parseExpression("1 - -3").getValue(Integer.class);  // 4
        double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class);  // -9000.0
        // Multiplication
        int six = parser.parseExpression("-2 * -3").getValue(Integer.class);  // 6
        double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class);  // 24.0
        // Division
        int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class);  // -2
        double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);  // 1.0
        // Modulus
        int three = parser.parseExpression("7 % 4").getValue(Integer.class);  // 3
        int one1 = parser.parseExpression("8 / 5 % 2").getValue(Integer.class);  // 1
        // Operator precedence
        int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);  // -21
    }
    @Test
    public void theAssignmentOperator(){
        Inventor inventor = new Inventor();
        EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
        parser.parseExpression("name").setValue(context, inventor, "Aleksandar Seovic");
        // alternatively
        String aleks = parser.parseExpression("name = 'Aleksandar Seovic'").getValue(context, inventor, String.class);
        System.out.println(aleks);//Aleksandar Seovic
    }
}

4.3.8. Types

package org.example.spel.language;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * Create by zjg on 2024/4/23
 */
public class Types {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        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
    }
}

4.3.9. Constructors

package org.example.spel.language;

import com.mysql.cj.BindValue;
import org.example.spel.po.Inventor;
import org.example.spel.po.Society;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * Create by zjg on 2024/4/23
 */
public class Constructors {
    public static void main(String[] args) {
        Society societyContext=new Society();
        ExpressionParser p = new SpelExpressionParser();
        Inventor einstein = p.parseExpression(
                        "new org.example.spel.po.Inventor('Albert Einstein', 'German')")
                .getValue(Inventor.class);
        System.out.println(einstein);//Inventor{name='Albert Einstein', nationality='German', inventions=null, birthdate=Tue Apr 23 21:20:14 CST 2024, placeOfBirth=null}
// create new Inventor instance within the add() method of List
        Object value = p.parseExpression(
                "members.add(new org.example.spel.po.Inventor('Albert Einstein','German'))").getValue(societyContext);
        System.out.println(value);//true
    }
}

4.3.10. Variables

package org.example.spel.language;

import org.example.spel.po.Inventor;
import org.junit.jupiter.api.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;

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

/**
 * Create by zjg on 2024/4/23
 */
public class Variables {
    @Test
    public void test1(){
        ExpressionParser parser = new SpelExpressionParser();
        Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
        EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
        context.setVariable("newName", "Mike Tesla");
        parser.parseExpression("name = #newName").getValue(context, tesla);
        System.out.println(tesla.getName());  // "Mike Tesla"
    }
    @Test
    public void test2(){
        // create an array of integers
        List<Integer> primes = new ArrayList<Integer>();
        primes.addAll(Arrays.asList(2,3,5,7,11,13,17));
        // create parser and set variable 'primes' as the array of integers
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        context.setVariable("primes", primes);
        // all prime numbers > 10 from the list (using selection ?{...})
        // evaluates to [11, 13, 17]
        List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
                "#primes.?[#this>10]").getValue(context);
    }
}

4.3.11. Functions

package org.example.spel.language;

import org.example.spel.po.Inventor;
import org.junit.jupiter.api.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;

/**
 * Create by zjg on 2024/4/23
 */
public class Functions {
    @Test
    public void test1() throws NoSuchMethodException {
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        context.setVariable("reverseString",
                StringUtils.class.getDeclaredMethod("reverseString", String.class));
        String helloWorldReversed = parser.parseExpression(
                "#reverseString('hello')").getValue(context, String.class);
        System.out.println(helloWorldReversed);//olleh
    }
}
abstract class StringUtils {

    public static String reverseString(String input) {
        StringBuilder backwards = new StringBuilder(input.length());
        for (int i = 0; i < input.length(); i++) {
            backwards.append(input.charAt(input.length() - 1 - i));
        }
        return backwards.toString();
    }
}



4.3.12. Bean References

package org.example.spel.language;

import org.junit.jupiter.api.Test;
import org.springframework.expression.AccessException;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.HashMap;
import java.util.Map;

/**
 * Create by zjg on 2024/4/23
 */
class MyBeanResolver implements BeanResolver{
    private static final Map<String,Object> beanFactory=new HashMap();
    {
        beanFactory.put("something","something");
        beanFactory.put("&foo","foo");
    }
    @Override
    public Object resolve(EvaluationContext context, String beanName) throws AccessException {
        return beanFactory.get(beanName);
    }
}
public class BeanReferences {
    @Test
    public void test1() {
        ExpressionParser parser = new SpelExpressionParser();
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setBeanResolver(new MyBeanResolver());
        // This will end up calling resolve(context,"something") on MyBeanResolver during evaluation
        Object bean = parser.parseExpression("@something").getValue(context);
        System.out.println(bean);
    }
    @Test
    public void test2() {
        ExpressionParser parser = new SpelExpressionParser();
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setBeanResolver(new MyBeanResolver());
        // This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation
        Object bean = parser.parseExpression("&foo").getValue(context);
        System.out.println(bean);
    }
}

4.3.13. Ternary Operator (If-Then-Else)

package org.example.spel.language;

import org.example.spel.po.Inventor;
import org.example.spel.po.Society;
import org.junit.jupiter.api.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

/**
 * Create by zjg on 2024/4/23
 */
public class TernaryOperator {
    @Test
    public void test1()  {
        ExpressionParser parser = new SpelExpressionParser();
        String falseString = parser.parseExpression(
                "false ? 'trueExp' : 'falseExp'").getValue(String.class);//falseExp

        Society society=new Society();
        Inventor inventor=new Inventor();
        inventor.setName("Nikola Tesla");
        society.addMembers(inventor);
        EvaluationContext societyContext = new StandardEvaluationContext();
        parser.parseExpression("name").setValue(societyContext,society,"IEEE");
        societyContext.setVariable("queryName", "Nikola Tesla");
        String expression = "isMember(#queryName)? #queryName + ' is a member of the ' " +
                "+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'";
        String queryResultString = parser.parseExpression(expression)
                .getValue(societyContext,society, String.class);
        System.out.println(queryResultString);
        // queryResultString = "Nikola Tesla is a member of the IEEE Society"
    }
}

4.3.14. The Elvis Operator

package org.example.spel.language;

import org.example.spel.po.Inventor;
import org.junit.jupiter.api.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;

/**
 * Create by zjg on 2024/4/23
 */
public class TheElvisOperator {
    @Test
    public void test1()  {
        String name = "Elvis Presley";
        String displayName = (name != null ? name : "Unknown");
        ExpressionParser parser = new SpelExpressionParser();
        String name1 = parser.parseExpression("name?:'Unknown'").getValue(new Inventor(), String.class);
        System.out.println(name1);  // 'Unknown'
        EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
        String name2 = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String.class);
        System.out.println(name2);  // Nikola Tesla
        tesla.setName(null);
        name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String.class);
        System.out.println(name);  // Elvis Presley
    }
}

4.3.15. Safe Navigation Operator

package org.example.spel.language;

import org.example.spel.po.Inventor;
import org.example.spel.po.PlaceOfBirth;
import org.junit.jupiter.api.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;

/**
 * Create by zjg on 2024/4/23
 */
public class SafeNavigationOperator {
    @Test
    public void test1()  {
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
        tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
        String city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String.class);
        System.out.println(city);  // Smiljan
        tesla.setPlaceOfBirth(null);
        city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String.class);
        System.out.println(city);  // null - does not throw NullPointerException!!!
    }
}

4.3.16. Collection Selection

package org.example.spel.language;

import org.example.spel.po.Inventor;
import org.example.spel.po.Society;
import org.junit.jupiter.api.Test;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Create by zjg on 2024/4/23
 */
public class CollectionSelection {
    @Test
    public void test1()  {
        ExpressionParser parser = new SpelExpressionParser();
        Society societyContext=new Society();
        Inventor inventor1=new Inventor();
        inventor1.setName("inventor1");
        inventor1.setNationality("Serbian");
        societyContext.addMembers(inventor1);
        Inventor inventor2=new Inventor();
        inventor2.setName("inventor2");
        inventor2.setNationality("China");
        societyContext.addMembers(inventor2);
        Inventor inventor3=new Inventor();
        inventor3.setName("inventor3");
        inventor3.setNationality("Serbian");
        societyContext.addMembers(inventor3);
        List<Inventor> list = (List<Inventor>) parser.parseExpression("members.?[nationality == 'Serbian']").getValue(societyContext);
        System.out.println(list);//[Inventor{name='inventor1', nationality='Serbian', inventions=null, birthdate=null, placeOfBirth=null}, Inventor{name='inventor3', nationality='Serbian', inventions=null, birthdate=null, placeOfBirth=null}]
        Inventor inventor = (Inventor) parser.parseExpression("members.^[nationality == 'Serbian']").getValue(societyContext);
        System.out.println(inventor);//Inventor{name='inventor1', nationality='Serbian', inventions=null, birthdate=null, placeOfBirth=null}

        Society society=new Society();
        society.addOfficers("001",25);
        society.addOfficers("002",30);
        society.addOfficers("003",22);
        Map newMap = (Map) parser.parseExpression("officers.?[value<27]").getValue(society);
        System.out.println(newMap);//{001=25, 003=22}
        newMap = parser.parseExpression("officers.$[value<27]").getValue(society,Map.class);
        System.out.println(newMap);//{003=22}
    }
}

4.3.17. Collection Projection

package org.example.spel.language;

import org.example.spel.po.Inventor;
import org.example.spel.po.PlaceOfBirth;
import org.example.spel.po.Society;
import org.junit.jupiter.api.Test;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import java.util.List;

/**
 * Create by zjg on 2024/4/23
 */
public class CollectionProjection {
    @Test
    public void test1()  {
        ExpressionParser parser = new SpelExpressionParser();
        Society societyContext=new Society();
        Inventor inventor1=new Inventor();
        inventor1.setName("inventor1");
        PlaceOfBirth placeOfBirth1 = new PlaceOfBirth("Smiljan");
        inventor1.setPlaceOfBirth(placeOfBirth1);
        societyContext.addMembers(inventor1);
        Inventor inventor2=new Inventor();
        inventor2.setName("inventor2");
        PlaceOfBirth placeOfBirth2 = new PlaceOfBirth("Idvor");
        inventor2.setPlaceOfBirth(placeOfBirth2);
        societyContext.addMembers(inventor2);
        // returns ['Smiljan', 'Idvor' ]
        List placesOfBirth = (List)parser.parseExpression("members.![placeOfBirth.city]").getValue(societyContext);
        System.out.println(placesOfBirth);
    }
}

4.3.18. Expression templating

package org.example.spel.language;

import org.junit.jupiter.api.Test;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * Create by zjg on 2024/4/23
 */
public class ExpressionTemplating {
    @Test
    public void test1()  {
        ExpressionParser parser = new SpelExpressionParser();
        String randomPhrase = parser.parseExpression(
                "random number is #{T(java.lang.Math).random()}",
                new TemplateParserContext()).getValue(String.class);
        // evaluates to "random number is 0.7038186818312008"
        System.out.println(randomPhrase);
    }
}

4.3.19. Expression Templating Extend(扩展)

模板表达式的使用,此处模拟我们有一个法院传单的模板,需要根据传单实体将数据动态渲染到模板上,spel非常适合做这类操作,下面让我们跟随案例学习下吧。

package org.example.spel.po;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Create by zjg on 2024/4/22
 */
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
public class Summons {
    private int id;
    private String defendantName;
    private String defendantGende;
    private int defendantAge;
    private String defendantUnit;
    private String caseNature;
    private String plaintiffName;
    private Date hearingDate;
    private String hearingVenue;
    private String courtName;
    private String courtAddress;
    private String contactPhone;
    private Date summonsDate;
    public String format(Date date,String pattern) {
        return new SimpleDateFormat(pattern).format(date);
    }
}

package org.example.spel.language;

import org.example.spel.po.Summons;
import org.junit.jupiter.api.Test;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import java.time.ZonedDateTime;
import java.util.Date;

/**
 * Create by zjg on 2024/4/23
 */
public class ExpressionTemplatingExtend {
    @Test
    public void test1()  {
        ExpressionParser parser = new SpelExpressionParser();
        String summonsMsg="法院传票\n" +
                "\n" +
                "案号:() 字第#{id}号\n" +
                "\n" +
                "被传唤人:#{defendantName}\n" +
                "性别:#{defendantGende}\n" +
                "年龄:#{defendantAge}\n" +
                "工作单位/住所:#{defendantUnit}\n" +
                "\n" +
                "案由:#{caseNature}\n" +
                "\n" +
                "本院受理的#{plaintiffName}诉#{defendantName}#{caseNature}一案,现定于#{format(hearingDate,'yyyy-MM-dd HH:mm:ss')}在#{hearingVenue}开庭审理。根据《中华人民共和国民事诉讼法》的相关规定,现向你发出传票,请你准时出庭参加诉讼。\n" +
                "\n" +
                "注意事项:\n" +
                "\n" +
                "被传唤人应准时到达应诉场所,不得无故缺席或迟到。\n" +
                "被传唤人应携带本传票及有效身份证件到庭,以便核对身份。\n" +
                "如被传唤人不能按时出庭,应在开庭前向本院申请延期审理或说明理由。无正当理由拒不出庭的,本院将依法缺席判决。\n" +
                "特此传唤!\n" +
                "\n" +
                "#{courtName}\n" +
                "#{courtAddress}\n" +
                "#{contactPhone}\n" +
                "#{format(summonsDate,'yyyy-MM-dd')}\n" +
                "\n" +
                "如有任何疑问,请及时与法院联系。";
        Summons summons = new Summons();
        summons.setId(100);
        summons.setDefendantName("张三");
        summons.setDefendantGende("男");
        summons.setDefendantAge(32);
        summons.setDefendantUnit("北京");
        summons.setCaseNature("商标侵权");
        summons.setPlaintiffName("李四");
        summons.setHearingDate(Date.from(ZonedDateTime.now().plusDays(7).withHour(10).withMinute(0).withSecond(0).toInstant()));
        summons.setHearingVenue("北京市东城区东交民巷27号");
        summons.setCourtName("中华人民共和国最高人民法院");
        summons.setCourtAddress("北京市东城区东交民巷27号");
        summons.setContactPhone("67550114");
        summons.setSummonsDate(new Date());
        String summon = parser.parseExpression(summonsMsg,new TemplateParserContext()).getValue(summons, String.class);
        System.out.println(summon);
    }
}


总结

回到顶部
学完基础版及进阶版,您对Spel表达式就已经学完了,剩下的就是多加练习,大成指日可待。

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值