文章目录
- 前言
- 准备
- 4.3. Language Reference
- 4.3.1. Literal Expressions
- 4.3.2. Properties, Arrays, Lists, Maps, and Indexers
- 4.3.3. Inline Lists
- 4.3.4. Inline Maps
- 4.3.5. Array Construction
- 4.3.6. Methods
- 4.3.7. Operators
- 4.3.8. Types
- 4.3.9. Constructors
- 4.3.10. Variables
- 4.3.11. Functions
- 4.3.12. Bean References
- 4.3.13. Ternary Operator (If-Then-Else)
- 4.3.14. The Elvis Operator
- 4.3.15. Safe Navigation Operator
- 4.3.16. Collection Selection
- 4.3.17. Collection Projection
- 4.3.18. Expression templating
- 4.3.19. Expression Templating Extend(扩展)
- 总结
前言
书接上回,这次主要讲述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表达式就已经学完了,剩下的就是多加练习,大成指日可待。