使用Spring Expression Language (SpEL)解析表達式
Spring Expression Language (SpEL) 是強大的表達式語言,支援查詢、操作運作時對象圖,以及解析邏輯、算術表達式。SpEL可以獨立使用,無論你是否使用Spring架構。
本文嘗試通過多個示例使用SpEL,探索其強大能力。
1. 環境準備
引入依賴:
compile group: 'org.springframework', name: 'spring-expression', version: '5.2.4.RELEASE'
讀者可以選擇最新版本或合适的版本。當然也可以下載下傳相應jar檔案。在調用下面的函數之前,按如下方式初始化一個類級屬性SpelExpression解析器:
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class ElMain {
private ExpressionParser parser;
ElMain(){
parser = new SpelExpressionParser();
}
public static void main(String[] args) {
ElMain elHelper = new ElMain();
elHelper.evaluateLiteralExpresssions();
}
private static void print(Object message){
System.out.println(message);
}
2. SpEL示例應用
2.1. 解析直接文本
private void evaluateLiteralExpresssions() {
Expression exp = parser.parseExpression("'Hello World'");
String message = (String) exp.getValue();
print(message);
exp = parser.parseExpression("6");
Integer value = exp.getValue(Integer.class);
print(value*2);
}
這裡直接解決字元串及數字文本。
2.2. 直接文本上調用方法
/**
* A function that tests method invocation on literals
*/
private void methodInvocationOnLiterals() {
Expression exp = parser.parseExpression("'Hello World'.concat('!')");
String message = (String) exp.getValue();
println(message);
exp = parser.parseExpression("'Hello World'.length()");
Integer size = exp.getValue(Integer.class);
println(size);
exp = parser.parseExpression("'Hello World'.split(' ')[0]");
message = (String)exp.getValue();
println(message);
}
示例展示了在字元串上直接調用Java String類的public方法。
2.3. 通路對象屬性和方法
/**A function that tests accessing properties of objects**/
private void accessingObjectProperties() {
User user = new User("John", "Doe", true, "[email protected]",30);
Expression exp = parser.parseExpression("firstName");
println((String)exp.getValue(user));
exp = parser.parseExpression("isAdmin()==false");
boolean isAdmin = exp.getValue(user, Boolean.class);
println(isAdmin);
exp = parser.parseExpression("email.split('@')[0]");
String emailId = exp.getValue(user, String.class);
println(emailId);
exp = parser.parseExpression("age");
Integer age = exp.getValue(user, Integer.class);
println(age);
}
表達式可以直接使用對象的屬性與方法。我們看到方法與屬性使用一樣,隻是多了調用括号。
2.4. 執行各種操作(比較、邏輯、算術)
SpEl支援下面幾種操作:
關系比較操作:==, !=, <, <=, >, >=
邏輯操作: and, or, not
算術操作: +, -, /, *, %, ^
private void operators() {
User user = new User("John", "Doe", true,"[email protected]", 30);
Expression exp = parser.parseExpression("age > 18");
println(exp.getValue(user,Boolean.class));
exp = parser.parseExpression("age < 18 and isAdmin()");
println(exp.getValue(user,Boolean.class));
}
2.5. 使用多個對象和變量
表達式不僅需要引用對象,而且可能需要引用多個不同類型的對象。我們可以把所有使用的對象都加入至上下文中。使用鍵值對的方式加入并引用。
private void variables() {
User user = new User("John", "Doe", true, "[email protected]",30);
Application app = new Application("Facebook", false);
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("user", user);
context.setVariable("app", app);
Expression exp = parser.parseExpression("#user.isAdmin() and #app.isActive()");
Boolean result = exp.getValue(context,Boolean.class);
println(result);
}
2.6. 調用自定義函數
SpEl也可以調用自定義的函數,使用者可以擴充業務邏輯。下面首先定義一個函數:、
public class StringHelper {
public static boolean isValid(String url){
return true;
}
}
下面在SpEl中調用isValid方法:
private void customFunctions() {
try {
StandardEvaluationContext context = new StandardEvaluationContext();
context.registerFunction("isURLValid",
StringHelper.class.getDeclaredMethod("isValid", new Class[] { String.class }));
String expression = "#isURLValid('http://google.com')";
Boolean isValid = parser.parseExpression(expression).getValue(context, Boolean.class);
println(isValid);
} catch (Exception e) {
e.printStackTrace();
}
}
3. 總結
本文通過示例介紹了SpEl中多種應用場景。讀者可以利用這些功能實作更加靈活的功能應用。