Spring中SpEL表達式的使用全解
一、概述
1、什么是SpEL
SpEL(Spring Expression Language)是Spring框架中用于表達式語言的一種方式。它類似于其他編程語言中的表達式語言,用于在運行時計算值或執(zhí)行特定任務(wù)。
SpEL提供了一種簡單且強大的方式來訪問和操作對象的屬性、調(diào)用對象的方法,以及實現(xiàn)運算、條件判斷等操作。它可以被用于XML和注解配置中,可以用于許多Spring框架中的特性,如依賴注入、AOP、配置文件等。
SpEL表達式可以在字符串中進行定義,使用特殊的語法和符號來表示特定的操作。例如,可以使用${expression}來表示一個SpEL表達式,其中expression是具體的SpEL語句。
SpEL支持各種操作和函數(shù),包括算術(shù)運算、邏輯運算、條件判斷、正則表達式匹配、集合操作等。它還支持訪問上下文中的變量和參數(shù),以及調(diào)用對象的方法。
2、SpEL能做什么
SpEL表達式具有廣泛的功能,以下是一些SpEL表達式可以做的事情:
- 訪問對象屬性:SpEL表達式可以通過對象引用來訪問對象的屬性,例如
${object.property}。 - 調(diào)用方法:SpEL表達式可以調(diào)用對象的方法,例如
${object.method()}。 - 進行算術(shù)運算:SpEL表達式支持各種算術(shù)運算符,如加法、減法、乘法和除法。
- 進行邏輯運算:SpEL表達式支持邏輯運算符,如與、或、非等。
- 進行條件判斷:SpEL表達式可以進行條件判斷,例如通過if語句判斷條件,并執(zhí)行相應(yīng)的操作。
- 訪問集合元素和屬性:SpEL表達式可以通過索引或鍵來訪問集合中的元素或?qū)ο蟮膶傩浴?/li>
- 執(zhí)行正則表達式匹配:SpEL表達式可以執(zhí)行正則表達式匹配,并返回匹配結(jié)果。
- 訪問上下文變量和參數(shù):SpEL表達式可以訪問上下文中的變量和方法參數(shù)。
- 進行類型轉(zhuǎn)換:SpEL表達式可以進行類型轉(zhuǎn)換操作,將一個對象轉(zhuǎn)換為另一種類型。
- 支持特殊操作符:SpEL表達式支持一些特殊的操作符,如Elvis操作符(
?:)、安全導航操作符(?.)等。
總的來說,SpEL表達式可以用于在運行時計算值、執(zhí)行任務(wù)和操作對象,提供了靈活且強大的表達能力,廣泛應(yīng)用于Spring框架中的各種功能和配置中。
二、SpEL表達式使用
0、用到的類
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;
}
}
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 Map getOfficers() {
return officers;
}
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;
}
}
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;
}
}
1、文字表達式
支持的文字表達式類型有字符串、數(shù)值(int、real、hex)、布爾和null。字符串由單引號分隔。若要將單引號本身放在字符串中,請使用兩個單引號字符。
通常來說,不會單純的定義一個簡單的文字表達式,而是通過方法調(diào)用等等復雜的操作,來完成一個功能:
// 定義Parser,可以定義全局的parser
ExpressionParser parser = new SpelExpressionParser();
// 獲取字符串 "Hello World"
String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();
// double類型 6.0221415E23
double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();
// int類型 2147483647
int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();
// true
boolean trueValue = (Boolean) parser.parseExpression("true").getValue();
// null
Object nullValue = parser.parseExpression("null").getValue();
2、屬性, 數(shù)組, List, Map,和 索引
(1)屬性操作
注意!屬性名的第一個字母不區(qū)分大小寫。
// 定義Parser,可以定義全局的parser
ExpressionParser parser = new SpelExpressionParser();
// 注意!屬性名的第一個字母不區(qū)分大小寫。 birthdate.year等效于Birthdate.Year
// 取出Inventor 中,birthdate屬性的year屬性
Inventor zhangsan = new Inventor("zhangsan", new Date(), "China");
// 定義StandardEvaluationContext ,傳入一個操作對象
StandardEvaluationContext zhangsanContext = new StandardEvaluationContext(zhangsan);
int year = (Integer) parser.parseExpression("birthdate.year + 1900").getValue(zhangsanContext);
System.out.println(year); // 2023
//取出Inventor的placeOfBirth的city屬性
PlaceOfBirth placeOfBirth = new PlaceOfBirth("長沙", "中國");
zhangsan.setPlaceOfBirth(placeOfBirth);
String city = (String) parser.parseExpression("placeOfBirth.City").getValue(zhangsanContext);
System.out.println(city); // 長沙
(2)數(shù)組和List
數(shù)組和List的內(nèi)容是通過使用方括號符號獲得的。
// 定義Parser,可以定義全局的parser
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// 省略數(shù)據(jù)初始化
// 取出tesla對象的inventions 第四個數(shù)據(jù)
String invention = parser.parseExpression("inventions[3]").getValue(
context, tesla, String.class);
// 取出ieee對象的第一個Member的name屬性
String name = parser.parseExpression("Members[0].Name").getValue(
context, ieee, String.class);
// 取出ieee對象的第一個Member中的第七個Inventions
String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(
context, ieee, String.class);
(3)Map
Map操作是通過key來獲取的
// 取出societyContext的Officers中的key為president的值
Inventor pupin = parser.parseExpression("Officers['president']").getValue(
societyContext, Inventor.class);
String city = parser.parseExpression("Officers['president'].PlaceOfBirth.City").getValue(
societyContext, String.class);
// Officers中key為advisors的值取第一個
parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(
societyContext, "Croatia");
3、內(nèi)嵌List
可以使用{}符號在表達式中直接表示List。{}本身意味著一個空列表。
// 定義Parser,可以定義全局的parser
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// [1, 2, 3, 4]
List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);
System.out.println(numbers);
// 嵌套: [[a, b], [x, y]]
List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);
System.out.println(listOfLists);
4、內(nèi)嵌Map
使用{key:value}符號在表達式中表示Map。{:}意味著空Map。
// 定義Parser,可以定義全局的parser
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// {name=Nikola, dob=10-July-1856}
Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context);
System.out.println(inventorInfo);
// 嵌套:{name={first=Nikola, last=Tesla}, dob={day=10, month=July, year=1856}}
Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context);
System.out.println(mapOfMaps);
// List與Map可以嵌套使用,互相結(jié)合。
// 嵌套:[{name={first=Nikola, last=Tesla}}, {dob={day=10, month=July, year=1856}}]
List listOfMaps = (List) parser.parseExpression("{{name:{first:'Nikola',last:'Tesla'}},{dob:{day:10,month:'July',year:1856}}}").getValue(context);
System.out.println(listOfMaps);
5、構(gòu)建數(shù)組
多維數(shù)組不提供初始化方式。
// 定義Parser,可以定義全局的parser
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context);
// 數(shù)組并初始化
int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context);
// 多維數(shù)組
int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);
6、調(diào)用類的方法
ExpressionParser parser = new SpelExpressionParser();
// 調(diào)用substring方法
String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);
// 調(diào)用societyContext中對象的isMember方法,并傳值。
StandardEvaluationContext societyContext = new StandardEvaluationContext(society);
boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
societyContext, Boolean.class);
7、SpEL操作符
(1)標準運算符
使用標準運算符表示法支持關(guān)系運算符(等于、不等于、小于、小于或等于、大于和大于或等于)。
null不被視為任何東西(即不為零)。因此,任何其他值總是大于null (X > null總是為真),并且沒有任何其他值小于零(X < null總是為假)。
ExpressionParser parser = newSpelExpressionParser();
// evaluates to true
boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);
// evaluates to false
boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);
// evaluates to true
boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
(2)instanceof 和 正則表達式的匹配操作符
使用基本類型時要小心,因為它們會立即被裝箱為包裝器類型,所以1 instanceof T(int)會計算為false,而1 instanceof T(Integer)會計算為true。
// evaluates to false
boolean falseValue = parser.parseExpression(
"'xyz' instanceof T(Integer)").getValue(Boolean.class);
// evaluates to true
boolean trueValue = parser.parseExpression(
"'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
//evaluates to false
boolean falseValue = parser.parseExpression(
"'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
(3)操作符的英文等價標識
每個符號操作符也可以被指定為純字母的等價物。這避免了所使用的符號對于嵌入表達式的文檔類型具有特殊含義的問題(例如在XML文檔中)。所有文本操作符都不區(qū)分大小寫。對應(yīng)的文本是:
lt (<)
gt (>)
le (<=)
ge (>=)
eq (==)
ne (!=)
div (/)
mod (%)
not (!)
(4)邏輯運算符
SpEL支持以下邏輯運算符:and、or、not
// 結(jié)果: false
boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);
// 調(diào)用方法并根據(jù)方法返回值判斷
String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
// -- OR --
boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.class);
// 調(diào)用方法并根據(jù)方法返回值判斷
String expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
// -- NOT --
// 取反
boolean falseValue = parser.parseExpression("!true").getValue(Boolean.class);
// -- AND and NOT --
String expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
(5)數(shù)學運算符
可以對數(shù)字和字符串使用加法運算符。只能對數(shù)字使用減法、乘法和除法運算符。
也可以使用模數(shù)(%)和指數(shù)冪(^)運算符。
強制執(zhí)行標準運算符優(yōu)先級。
// 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
// 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 one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class); // 1
// Operator precedence
int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21
(6)賦值運算符
若要給對象設(shè)置屬性,請使用賦值運算符(=)。這通常在對setValue的調(diào)用中完成,但也可以在對getValue的調(diào)用中完成。
// 定義Parser,可以定義全局的parser
ExpressionParser parser = new SpelExpressionParser();
Inventor inventor = new Inventor();
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
parser.parseExpression("Name").setValue(context, inventor, "Aleksandar Seovic");
System.out.println(inventor.getName()); // Aleksandar Seovic
// 或者這樣賦值
String aleks = parser.parseExpression(
"Name = 'Aleksandar Seovic2'").getValue(context, inventor, String.class);
System.out.println(inventor.getName()); // Aleksandar Seovic2
8、獲取類的類型
可以使用特殊的T運算符來指定java.lang.Class的實例(類型)。靜態(tài)方法也是通過使用這個操作符來調(diào)用的。
StandardEvaluationContext使用TypeLocator來查找類型,StandardTypeLocator(可以替換)是基于對java.lang包的理解而構(gòu)建的。所以java.lang中類型的T()引用不需要使用全限定名,但是其他包中的類,必須使用全限定名。
ExpressionParser parser = new SpelExpressionParser();
Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);
Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);
boolean trueValue = parser.parseExpression(
"T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR")
.getValue(Boolean.class);
9、調(diào)用類構(gòu)造器
使用new運算符調(diào)用構(gòu)造函數(shù)。除了基本類型(int、float等)和String之外,所有類型都應(yīng)該使用完全限定的類名。
Inventor einstein = p.parseExpression(
"new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
.getValue(Inventor.class);
//創(chuàng)建一個新的Inventor,并且添加到members的list中
p.parseExpression(
"Members.add(new org.spring.samples.spel.inventor.Inventor(
'Albert Einstein', 'German'))").getValue(societyContext);
10、SpEL變量
(1)基本使用
可以使用#variableName語法在表達式中引用變量。通過在EvaluationContext實現(xiàn)上使用setVariable方法來設(shè)置變量
ExpressionParser parser = new SpelExpressionParser();
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
context.setVariable("newName", "Mike Tesla"); // 設(shè)置變量
// 獲取變量newName,并將其賦值給name屬性
parser.parseExpression("Name = #newName").getValue(context, tesla);
System.out.println(tesla.getName()); // "Mike Tesla"
(2)#this 和 #root變量
#this變量引用當前的評估對象(根據(jù)該評估對象解析非限定引用)。
#root變量總是被定義并引用根上下文對象。雖然#this可能會隨著表達式的組成部分的計算而變化,但是#root總是指根。
// 創(chuàng)建一個Integer數(shù)組
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.forReadWriteDataBinding().build();
context.setVariable("primes", primes);
// numbers > 10 的 list
// evaluates to [11, 13, 17]
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
"#primes.?[#this>10]").getValue(context);
System.out.println(primesGreaterThanTen);
11、調(diào)用類靜態(tài)方法
// 方法定義的方式
Method method = ...;
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
context.setVariable("myFunction", method);
// 準備一個要調(diào)用的目標方法
public 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();
}
}
// 調(diào)用目標靜態(tài)方法
public static void main(String[] args) throws NoSuchMethodException {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// 獲取要調(diào)用的方法
context.setVariable("reverseString",
StringUtils.class.getDeclaredMethod("reverseString", String.class));
// 調(diào)用
String helloWorldReversed = parser.parseExpression(
"#reverseString('hello')").getValue(context, String.class);
}
12、Bean引用
如果已經(jīng)用bean解析器配置了評估上下文,則可以使用@符號從表達式中查找bean。
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());
// 將調(diào)用MyBeanResolver 的 resolve(context,"something")
Object bean = parser.parseExpression("@something").getValue(context);
// 注意!MyBeanResolver 可以使用系統(tǒng)自帶的BeanFactoryResolver,寫成:
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
// BeanFactoryResolver的resolve方法,就是通過Bean的名稱來獲取Bean:
@Override
public Object resolve(EvaluationContext context, String beanName) throws AccessException {
try {
return this.beanFactory.getBean(beanName);
}
catch (BeansException ex) {
throw new AccessException("Could not resolve bean reference against BeanFactory", ex);
}
}
要訪問工廠bean本身,應(yīng)該在bean名稱前加上&符號:
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());
// 將調(diào)用MyBeanResolver 的 resolve(context,"something")
Object bean = parser.parseExpression("&foo").getValue(context);
13、三元運算符(If-Then-Else)
// 使用示例
String falseString = parser.parseExpression(
"false ? 'trueExp' : 'falseExp'").getValue(String.class);
// name屬性設(shè)置值
parser.parseExpression("Name").setValue(societyContext, "IEEE");
// 設(shè)置變量
societyContext.setVariable("queryName", "Nikola Tesla");
// 三元運算符
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, String.class);
// queryResultString = "Nikola Tesla is a member of the IEEE Society"
14、Elvis操作符
Elvis運算符是三元運算符語法的縮寫,用于Groovy語言中。使用三元運算符語法時,通常需要將一個變量重復兩次,如下例所示:
String name = "Elvis Presley"; String displayName = (name != null ? name : "Unknown");
可以使用Elvis運算符(因與Elvis的發(fā)型相似而得名)優(yōu)化。以下示例顯示了如何使用Elvis運算符:
ExpressionParser parser = new SpelExpressionParser();
String name = parser.parseExpression("name?:'Unknown'").getValue(String.class);
System.out.println(name); // 'Unknown'
更復雜的實例:
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class);
System.out.println(name); // Nikola Tesla
tesla.setName(null);
name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class);
System.out.println(name); // Elvis Presley
15、安全導航操作員
安全導航操作符用于避免NullPointerException,來自Groovy語言。通常,當引用一個對象時,可能需要在訪問該對象的方法或?qū)傩灾膀炞C它不為null。為了避免這種情況,安全導航運算符返回null,而不是引發(fā)異常。以下示例顯示了如何使用安全導航運算符:
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!!!
16、集合選擇
// 語法.?[selectionExpression]
List<Inventor> list = (List<Inventor>) parser.parseExpression(
"Members.?[Nationality == 'Serbian']").getValue(societyContext);
// 返回value小于27的值
Map newMap = parser.parseExpression("map.?[value<27]").getValue();
除了返回所有選定的元素之外,還可以只檢索第一個或最后一個值。要獲得匹配選擇的第一個條目,語法是。.^[selectionExpression].要獲得最后一個匹配的選擇,語法是。.$[選擇表達式]。
17、集合投影
// 語法:.![projectionExpression]
// returns ['Smiljan', 'Idvor' ]
List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]");
18、表達式模板
// 通常使用#{}作為模板,與字符串拼接起來
String randomPhrase = parser.parseExpression(
"random number is #{T(java.lang.Math).random()}",
new TemplateParserContext()).getValue(String.class);
// evaluates to "random number is 0.7038186818312008"
// TemplateParserContext 的定義
public class TemplateParserContext implements ParserContext {
public String getExpressionPrefix() {
return "#{";
}
public String getExpressionSuffix() {
return "}";
}
public boolean isTemplate() {
return true;
}
}
參考資料
到此這篇關(guān)于Spring中SpEL表達式的使用全解的文章就介紹到這了,更多相關(guān)Spring SpEL表達式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Spring中@Value使用詳解及SPEL表達式
- 詳解Spring中Spel表達式和el表達式的區(qū)別
- SpringDataElasticsearch與SpEL表達式實現(xiàn)ES動態(tài)索引
- Spring AOP如何在注解上使用SPEL表達式注入對象
- spring之SpEL表達式詳解
- 使用Springboot自定義注解,支持SPEL表達式
- 基于spring?@Cacheable?注解的spel表達式解析執(zhí)行邏輯
- Spring?Cache抽象-使用SpEL表達式解析
- Spring實戰(zhàn)之Bean定義中的SpEL表達式語言支持操作示例
- Spring組件開發(fā)模式支持SPEL表達式
- Spring spel表達式使用方法示例
相關(guān)文章
Springboot WebFlux集成Spring Security實現(xiàn)JWT認證的示例
這篇文章主要介紹了Springboot WebFlux集成Spring Security實現(xiàn)JWT認證的示例,幫助大家更好的理解和學習使用springboot框架,感興趣的朋友可以了解下2021-04-04
java mybatis框架實現(xiàn)多表關(guān)系查詢功能
這篇文章主要介紹了java mybatis框架實現(xiàn)多表關(guān)系查詢,基于Maven框架的整體設(shè)計 —— 一多一的關(guān)系,文中通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-10-10
MyBatisPlus使用${ew.customSqlSegment}別名問題解決
在使用MyBatisPlus進行連表查詢時,可能遇到因${ew.customSqlSegment}無法加別名的問題,本文就來介紹一下如何解決,感興趣的可以了解一下2024-10-10
Java通過反射機制動態(tài)設(shè)置對象屬性值的方法
下面小編就為大家?guī)硪黄狫ava通過反射機制動態(tài)設(shè)置對象屬性值的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-07-07

