本帖最后由 大山哥哥 于 2021-7-13 11:22 编辑
今天我们来看一个SPEL表达式的使用案例,通过它来讲解几种常见的SPEL表达式语法。 在spring security注解@PreAuthorize中使用的SpEL表达式有一个较为复杂的写法:
[Java] 纯文本查看 复制代码 @PreAuthorize("hasRole('ROLE_USER') and 'admin' == authentication.principal.username") 其中的hasRole('ROLE_USER')和'admin' == authentication.principal.username分别采用的是SpEL表达式写法。
那么这些SpEL代表什么意思呢?又有那些常用的SpEL表达式写法呢?我们挑选几个例子来统一演示,同时也可以说明上述表达式分别代表什么意义。
我们先准备两个类,为下面的语法测试做准备:
[Java] 纯文本查看 复制代码 public class AppContextBean {
private String appName;
private AuthUser user;//用户对象
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public AuthUser getUser() {
return user;
}
public void setUser(AuthUser user) {
this.user = user;
}
}
public class AuthUser {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
下面,我们来使用SpEL的几个语法:
[Java] 纯文本查看 复制代码 /**
* 普通字符串
*/
@Test
public void string(){
ExpressionParser parse = new SpelExpressionParser();
Expression expression = parse.parseExpression("'你好SPEL'");
Object value = expression.getValue();
System.out.println(value);
}
[Java] 纯文本查看 复制代码 /**
* 对象属性调用
* 创建AppContextBean对象,该对象中有两个属性,分别是字符串类型的appName和AuthUser对象类型的user
*/
@Test
public void objectAttr(){
//构建AuthUser对象
AuthUser user = new AuthUser();
user.setUsername("宙斯");
//构建对象
AppContextBean appContext = new AppContextBean();
appContext.setAppName("SPEL应用");
appContext.setUser(user);
//使用SPEL表达式来读取对象中的属性值
ExpressionParser parse = new SpelExpressionParser();
EvaluationContext context=new StandardEvaluationContext(appContext);
//读取appContext对象中的用户名称 其中"user"读取的是AppContextBean这个对象的user属性对象,"user.username"读取的是user对象的username属性值
Expression expression = parse.parseExpression("user.username");
//设置获取值的上下文环境
Object value = expression.getValue(context);
System.out.println("当前AppContextBean中用户名为:" + value);
//执行结果如下:
// 当前AppContextBean中用户名为:宙斯
}
[Java] 纯文本查看 复制代码 /**
* 普通方法调用
* 演示调用AppContextBean中的getAppName方法
*/
@Test
public void invokeMethod(){
//构建AppContextBean对象
AppContextBean appContext = new AppContextBean();
appContext.setAppName("SPEL应用");
ExpressionParser parse = new SpelExpressionParser();
EvaluationContext context=new StandardEvaluationContext(appContext);
Expression expression = parse.parseExpression("getAppName()");
Object value = expression.getValue(context);
System.out.println(value);
//执行结果如下:
// SPEL应用
}
[Java] 纯文本查看 复制代码 /**
* 方法传参使用
* 获取某个入参对象的属性值
*/
@Test
public void variable(){
//构建解析器
ExpressionParser parse = new SpelExpressionParser();
//构建AuthUser对象
AuthUser user = new AuthUser();
user.setUsername("影魔");
//构建对象
AppContextBean appContextBean = new AppContextBean();
appContextBean.setAppName("SPEL应用");
appContextBean.setUser(user);
//设置解析环境
EvaluationContext context=new StandardEvaluationContext();
//设置变量(参数)
context.setVariable("appContext",appContextBean);
//!!注意,此处的"#appContext"的语法是 #变量名,即,获取上下文环境中变量名为appContext的值——appContextBean对象。
//"#appContext.appName"则是获取appContextBean对象的appName属性值
Expression appNameParse = parse.parseExpression("#appContext.appName");
//从上下文环境中得到该SPEL表达式运行的结果
Object appName = appNameParse.getValue(context);
//"#appContext.user.username"则是获取appContextBean对象user属性的username值
Expression usernameParse = parse.parseExpression("#appContext.user.username");
//从上下文环境中得到该SPEL表达式运行的结果
Object username = usernameParse.getValue(context);
System.out.println("当前APPNAME是:" + appName + ", 用户名是:" + username);
//执行结果如下:
// 当前APPNAME是:SPEL应用, 用户名是:影魔
}
[Java] 纯文本查看 复制代码 /**
* 判断
*/
@Test
public void cal(){
ExpressionParser parse = new SpelExpressionParser();
//判断2>1 返回boolean类型
Expression expression = parse.parseExpression("2 > 1");
Object value = expression.getValue();
System.out.println("判断2>1:" + value);
expression = parse.parseExpression("2 == 1");
value = expression.getValue();
System.out.println("判断2 == 1:" + value);
//执行结果如下:
// 判断2>1:true
// 判断2 == 1:false
}
[Java] 纯文本查看 复制代码 /**
* 多判断条件拼接
*/
@Test
public void calConcat(){
ExpressionParser parse = new SpelExpressionParser();
//2>1和2==1的判断结果“或”拼接 返回boolean类型
Expression expression = parse.parseExpression("2 > 1 or 2 == 1"); //其中or也可以使用||
Object value1 = expression.getValue();
System.out.println("2 > 1 or 2 == 1:" + value1);
//2>1和2==1的判断结果“与”拼接 返回boolean类型
expression = parse.parseExpression("2 > 1 and 2 == 1");//其中and也可以使用&&
Object value2 = expression.getValue();
System.out.println("2 > 1 and 2 == 1:" + value2);
//执行结果如下:
// 2 > 1 or 2 == 1:true
// 2 > 1 and 2 == 1:false
}
学习到这里,大家应该可以想得到 @PreAuthorize("hasRole('ROLE_USER') and 'admin' == authentication.principal.username") 中的SPEL表达式的作用了吧?我们通过一个截图来说明:
大家也可以思考一下下面的代码中的SPEL所表达的判断:
[Java] 纯文本查看 复制代码 //SPEL表达式如下:
// #userId == authentication.principal.username or hasRole('ROLE_ADMIN')
@PreAuthorize("#userName == authentication.principal.username or hasRole('ROLE_ADMIN')")
void changeUserPassword(@RequestParam("userName") String userName ){
//代码执行段
}
|