SpEL + AOP实现注解的动态赋值.

首先,我们需要有个自定义注解,它有两个参数:key 表示 SpEL 表达式;userType 表示权限

参数。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ResponseSensitiveOverride {

/**
 * SPEL 表达式
 *
 * @return
 */
String key() default "";

/**
 * 1:主账号、2:子账号
 */
int userType() default 1;

}
然后,把这个注解放在路由地址上,key 写入获取权限参数的 SpEL 表达式:

@ResponseSensitiveOverride(key = "#driverPageParam.getUserType()")
@RequestMapping(value = "/queryPage", method = RequestMethod.POST)
public ResponseData<PageVo<AdminDriverVo>> queryPage(@RequestBody 

AdminDriverPageParam driverPageParam) {
return driverService.queryPageAdmin(driverPageParam);
}
回到顶部
二、SpEl + AOP 注解赋值
现在 SpEL 表达式是有了,怎么把 SpEL 表达式的结果赋值给注解的 userType 参数呢?这就

需要用 Spring AOP 、Java 反射 和 动态代理 的知识。

@Aspect
@Component
public class SensitiveAspect {

private SpelExpressionParser spelParser = new SpelExpressionParser();

/**
 * 返回通知
 */    
@AfterReturning("@annotation

(com.yungu.swift.base.model.annotation.ResponseSensitiveOverride) && @annotation

(sensitiveOverride)")
public void doAfter(JoinPoint joinPoint, ResponseSensitiveOverride

sensitiveOverride) throws Exception {
//获取方法的参数名和参数值
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature

();
List paramNameList = Arrays.asList

(methodSignature.getParameterNames());
List paramList = Arrays.asList(joinPoint.getArgs());

    //将方法的参数名和参数值一一对应的放入上下文中
    EvaluationContext ctx = new StandardEvaluationContext();
    for (int i = 0; i < paramNameList.size(); i++) {
        ctx.setVariable(paramNameList.get(i), paramList.get(i));
    }

    // 解析SpEL表达式获取结果
    String value = spelParser.parseExpression(sensitiveOverride.key

()).getValue(ctx).toString();
//获取 sensitiveOverride 这个代理实例所持有的 InvocationHandler
InvocationHandler invocationHandler = Proxy.getInvocationHandler

(sensitiveOverride);
// 获取 invocationHandler 的 memberValues 字段
Field hField = invocationHandler.getClass().getDeclaredField

(“memberValues”);
// 因为这个字段是 private final 修饰,所以要打开权限
hField.setAccessible(true);
// 获取 memberValues
Map memberValues = (Map) hField.get(invocationHandler);
// 修改 value 属性值
memberValues.put(“userType”, Integer.parseInt(value));

}

}
通过这种方式,我们就实现了为注解动态赋值。

回到顶部
三、ResponseBodyAdvice 处理数据
现在要做的事情就是在 ResponseBody 数据返回前,对数据进行拦截,然后读取注解上的权限

参数,从而对数据进行处理,这里使用的是 SpringMVC 的 ResponseBodyAdvice 来实现:

@Slf4j
@RestControllerAdvice
@Order(-1)
public class ResponseBodyAdvice implements

org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice {

private static final ThreadLocal<Integer> threadLocal = new 

ThreadLocal() {
@Override
protected Integer initialValue() {
return SysUserDto.USER_TYPE_PRIMARY;
}
};

@Override
public boolean supports(MethodParameter returnType, Class converterType) {
    if (returnType.hasMethodAnnotation(ResponseSensitiveOverride.class)) {
        ResponseSensitiveOverride sensitiveOverride = 

returnType.getMethodAnnotation(ResponseSensitiveOverride.class);
threadLocal.set(sensitiveOverride.userType());
return true;
}
return false;
}

@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, 

MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest

request, ServerHttpResponse response) {
if (body != null && SysUserDto.USER_TYPE_SUB.equals(threadLocal.get())) {
// 业务处理
}
return body;
}
}
亚马逊测评 www.yisuping.com

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值