说明 **本文是通过springboot注解的方式集成aop切面,让验证模块可以在项目中更灵活的配置。**注解的方式集成aop切面在实际使用中只需要将注解标注在需要执行aop逻辑的方法上即可实现调用。使用起来方便快捷,原始配置aop切面一般都会标注为某个package包下方的所有类中的方法,而实际业务中可能并不是这样的,注解的方式就是为了应对这种情况,能更灵活的控制aop切面。

本文项目地址https://github.com/gwy572294624/springboot_aspect_verify

spring boot api验证签名 springboot 接口签名_java


通过注解实现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("签名不合法");
        }
    }

以上,希望本文可以帮到你。