说明 **本文是通过springboot注解的方式集成aop切面,让验证模块可以在项目中更灵活的配置。**注解的方式集成aop切面在实际使用中只需要将注解标注在需要执行aop逻辑的方法上即可实现调用。使用起来方便快捷,原始配置aop切面一般都会标注为某个package包下方的所有类中的方法,而实际业务中可能并不是这样的,注解的方式就是为了应对这种情况,能更灵活的控制aop切面。
本文项目地址https://github.com/gwy572294624/springboot_aspect_verify
通过注解实现aop切面
- 使用到的jar包
- 配置注解
- 配置切面类,切入配置好的注解
- 验证
- 注解扩展
- 怎么取呢
使用到的jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
配置注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TokenVerify {
String value() default "";
}
@Target 用来标注注解可以被用在哪些地方,该注解中的参数是可以放多个,我们是用他来进行签名验证,只使用到了方法,当然也可以加个ElementType.TYPE
可以将注解放在类上,标注当前类中的所有方法都会执行(但是测试过程中直接标注在类上并不会触发下面的方法都执行aop处理逻辑!!!!)。所以aop集成注解的形式应该只支持注解标注方法上。
@Retention 该注解是标注的生命周期,定义的注解那一般情况下肯定是运行时一直用的,所以一般都会选择RUNTIME。
1、RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
2、RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
3、RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
@Documented 指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值。
配置切面类,切入配置好的注解
@Aspect
@Component
@Slf4j
public class TokenAspect {
@Pointcut("@annotation(com.aspect.config.TokenVerify)")
public void tokenAspect() {
}
@Around("tokenAspect()")
public Object beforePointcut(ProceedingJoinPoint joinPoint) throws Throwable {
log.info(" 切面类 ---!");
try{
//获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
String data = request.getHeader("Authorization");
if (ObjectUtils.isEmpty(data)){
return JSON.toJSONString("token - null");
}
//业务逻辑通过token查询验证
//-------
//验证完成后调用 触发aop前置的方法 并返回处理完成的结果
Object result = joinPoint.proceed();
return result;
}catch (Exception e){
e.printStackTrace();
return JSON.toJSONString("签名不合法");
}
}
}
验证
@RestController
@RequestMapping(value ="/test/aop/verify")
public class TestController {
@TokenVerify
@RequestMapping("/methodOne")
public String methodOne(){
System.out.println("新增用户 ----- ");
return "新增成功";
}
@RequestMapping("/methodTwo")
public String methodTwo(){
System.out.println("删除用户 ----- ");
return "删除成功";
}
}
请求http://127.0.0.1:8080/test/aop/verify/methodOne 拦截
请求http://127.0.0.1:8080/test/aop/verify/methodTwo成功
@RestController
@TokenVerify
@RequestMapping(value ="/testtwo/aop/verify")
public class TestTwoController {
@RequestMapping("/methodOne")
public String methodOne(){
System.out.println("新增用户 ----- ");
return "新增成功";
}
@RequestMapping("/methodTwo")
public String methodTwo(){
System.out.println("删除用户 ----- ");
return "删除成功";
}
}
请求http://127.0.0.1:8080/testtwo/aop/verify/methodOne 成功
请求http://127.0.0.1:8080/testtwo/aop/verify/methodTwo成功
注解扩展
//当然部分业务逻辑可能涉及到每个注解所对应到方法有其他附加值,每个方法有不相同 例如 我们现在需要通过aop加入系统操作日志,每个方法操作的信息不一样,有新增有修改,这样的话我们可以使用注解的value标注,
例
@TokenVerify("我在methodOne上")
@RequestMapping("/methodOne")
public String methodOne(){
System.out.println("新增用户 ----- ");
return "新增成功";
}
怎么取呢
//切面类中加入
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
TokenVerify tokenVerify = signature.getMethod().getDeclaredAnnotation(TokenVerify.class);
String value = tokenVerify.value();
System.out.println("==注解@TokenVerify的value==" + value);
//完整代码展示
@Around("tokenAspect()")
public Object beforePointcut(ProceedingJoinPoint joinPoint) throws Throwable {
log.info(" 切面类 ---!");
try{
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
TokenVerify tokenVerify = signature.getMethod().getDeclaredAnnotation(TokenVerify.class);
String value = tokenVerify.value();
System.out.println("==注解@TokenVerify的value==" + value);
//获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
String data = request.getHeader("Authorization");
if (ObjectUtils.isEmpty(data)){
return JSON.toJSONString("token - null");
}
//业务逻辑通过token查询验证
//-------
//验证完成后调用触发aop前置的方法 并返回处理完成的结果
Object result = joinPoint.proceed();
return result;
}catch (Exception e){
e.printStackTrace();
return JSON.toJSONString("签名不合法");
}
}
以上,希望本文可以帮到你。