业务场景:
开给c端的接口需要鉴权,这里入参的格式种类繁多,但是最终需要的是拿到一个id,当然只有封装入参VO的人才知道哪个字段对应id。所以需要实现的功能就是在切面上由对应的方法传入不同的VO里命名不一样的 “id”。
注意点:
如果是固定字段直接在注解上给固定值就好,这里针对那种需要从入参VO对象进行取值的情况。
编码:
首先定义一个注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface KBVerify {
String id() default “";
}
tips:这里同时定义了一个字段,用于后续传参。
同时需要定一个advice类,来对切面进行增强
@Slf4j
@Aspect
@Component
public class KBVerifyAdvice {
@Autowired
private XXXXService xxxxService;
/**
* 权限校验
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("@annotation(com.ddmc.knowledge.config.KBVerify)")
public Object doCheckKBAccess(ProceedingJoinPoint pjp) throws Throwable {
Method objMethod = ((MethodSignature) pjp.getSignature()).getMethod();
String[] parameterNames = ((MethodSignature) pjp.getSignature()).getParameterNames();
Object[] args = pjp.getArgs();
KBVerify kbVerify = objMethod.getDeclaredAnnotation(KBVerify.class);
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression(kbVerify.baseId());
StandardEvaluationContext ctx = new StandardEvaluationContext();
for (int i = 0; i < parameterNames.length; i++) {
ctx.setVariable(parameterNames[i], args[i]);
}
String id = expression.getValue(ctx).toString();
//TODO 拿到id就可以进行对应的校验了,该报错报错
// xxxxService.getById();
return pjp.proceed();
}
}
调用端:
/**
* c端接口
*
* @param searchReqVO
*/
@KBVerify(id = “#reqVO.appCode")
public SearchPageInfoResVO queryList(RequestVO reqVO) {
//…业务代码
}
注意这里的spel表达式要跟入参的参数名相同。
这样就可以在注解里动态读取到对应的入参啦。