Spring Expression Language (SpEL) 是强大的表达式语言,支持查询、操作运行时对象图,以及解析逻辑、算术表达式。SpEL可以独立使用,无论你是否使用Spring框架。
本文尝试通过多个示例使用SpEL,探索其强大能力。
引入依赖:
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);
}
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);
}
这里直接解决字符串及数字文本。
/**
* 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方法。
/**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);
}
表达式可以直接使用对象的属性与方法。我们看到方法与属性使用一样,只是多了调用括号。
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));
}
表达式不仅需要引用对象,而且可能需要引用多个不同类型的对象。我们可以把所有使用的对象都加入至上下文中。使用键值对的方式加入并引用。
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);
}
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();
}
}
本文通过示例介绍了SpEl中多种应用场景。读者可以利用这些功能实现更加灵活的功能应用。