1. 定义注解
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CheckAuth {
/**
* 使用SpEL表达式标识需要需要检查的房间id
*/
String roomId();
/**
* SpEL表达式标识需要被检查的用户userId
*/
String userId();
}
2. 解析SpEL表达式的工具方法
public class SpelExpressionUtil {
private static final ExpressionParser parser = new SpelExpressionParser();
private static final LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
public static <T> T parseSpel(Method targetMethod, Object[] args, String spel, Class<T> paramType) {
EvaluationContext context = new StandardEvaluationContext();
String[] params = discoverer.getParameterNames(targetMethod);
for (int len = 0; len < params.length; len++) {
context.setVariable(params[len], args[len]);
}
Expression expression = parser.parseExpression(spel);
return expression.getValue(context, paramType);
}
}
3. 编写切面
@Slf4j
@Component
@Aspect
public class CheckResourceAuthProcessor {
@Before(value = "@annotation(com.xxx.yyy.aspect.CheckAuth) && @annotation(c)")
public void check(JoinPoint joinPoint, CheckAuth c) {
// 获取方法参数值
Object[] arguments = joinPoint.getArgs();
// 获取method
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 获取spel表达式
String roomIdSpEL = c.roomId();
String userIdSpEL = c.userId();
// 根据spel表达式获取真正的入参中 需要检查的变量
Long roomId = SpelExpressionUtil.parseSpel(method, arguments, roomIdSpEL, Long.class);
String userId = SpelExpressionUtil.parseSpel(method, arguments, userIdSpEL, String.class);
///...对用户操作是否有权限进行校验
}
}
4. 使用注解
@CheckAuth(roomId = "#req.roomId", userId = "#operator")
public void doSomething(KickOutReq req, String operator) {
///...其他业务逻辑
}
5. IDEA配置
在IDEA中Spring自带的SpEL表达式显示是有提示的
类似于这种
但是我们自定义的是没有提示的
我们可以加一下IDEA的提示
光标放到SpEL表达式上, Alt+Enter
,弹出, 选择 Inject language
查询spel
, 选择
这下我们的IDEA就能够把这个字符串当做SpEL正常的显示了
6. @Language(“SpEL”)
IDEA的配置只能配置自己电脑, 如果你经常换电脑, 那么这个spel的语法由无法正确显示了
如果团队中所有人都使用IDEA进行开发, 这里提供一个方法, 让团队中的所有人都能自动以spel的方式查看
添加依赖
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId> <version>13.0</version>
<scope>provided</scope>
</dependency>
使用@Language 注解
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CheckResourceAuth {
/**
* 使用SpEL表达式标识需要需要检查的房间id
*/
@Language("SpEL")
String roomId();
/**
* SpEL表达式标识需要被检查的用户userId
*/
@Language("SpEL")
String userId();
}
这时候idea不需要做任何配置, 自动就能正常显示spel语法了