• 利用AOP的方式自定义注解


    使用背景:

    公司的维护项目提出一个比较恶心的需求,添加针对系统的人员和部门,企业等不同维度进行考核(考核的标准大体是根据登录、使用系统内部按钮、审批流转等...)大体就是要通过活跃度,这一下懵逼了,这肯定要在不同的接口写业务逻辑了,根据token获取登录人的所属部门等信息,然后获取对应的业务信息;

    解决方法:利用AOP自定义注解的方法可以减少很大一部分工作。这里提供一个简单的测试方法,仅仅只起到提示的作用;

    一、首先需要在pom文件中集成aop的包

    这里如果你想找不同版本的pom依赖:

    https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>

    二、Controller层:利用AOP自定义注解的方式解决问题

    package com.dongl.controller;
    
    import com.dongl.utils.CheckManagement;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @author D-L
     * @Classname AnnotationController
     * @Version 1.0
     * @Description   使用AOP测试自定义注解 controller
     * @Date 2020/8/4
     */
    
    @RestController
    @RequestMapping("Annotation")
    public class AnnotationController {
    
        @CheckManagement("annotation-one")
        @GetMapping(value = "annotation")
        public Boolean Annotation (){
            System.out.println("interface start -----------------------------");
            return true;
        }
    }

    三、自定义注解

    package com.dongl.utils;
    
    import java.lang.annotation.*;
    /**
     * @author D-L
     * @Classname CheckManagement
     * @Version 1.0
     * @Description  自定义注解
     * @Date 2020/8/4
     */
    
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface CheckManagement {
        String value() default "";
    }

    四、切面类

    package com.dongl.utils;
    
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @author D-L
     * @Classname AnnotationController
     * @Version 1.0
     * @Description   使用AOP测试自定义注解 切面类
     * @Date 2020/8/4
     */
    
    @Aspect
    @Component
    public class CheckManagementAspect {
    
        /**
         * 切入点
         * 切入点为包路径下的:execution(public * org.ylc.note.aop.controller..*(..)):
         * com.dongl.controller包下任意类任意返回值的 public 的方法
         *
         * 切入点为注解的: @annotation(CheckManagement)
         * 存在 CheckManagement 注解的方法
         */
        @Pointcut("@annotation(com.dongl.utils.CheckManagement)")
        private void check() {
        }
    
        /**
         * 目标方法调用之前执行
         * 注意这里不能使用 ProceedingJoinPoint
         * @param joinPoint
         */
        @Before("check()")
        public void doBefore(JoinPoint joinPoint) {
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            CheckManagement visitPermission = method.getAnnotation(CheckManagement.class);
            String value = visitPermission.value();
            System.out.println("before--------------"+ value);
        }
    
        /**
         *  目标方法调用之后执行
         *  注意这里不能使用 ProceedingJoinPoint
         * @param joinPoint
         */
        @After("check()")
        public void doAfter(JoinPoint joinPoint) {
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            CheckManagement visitPermission = method.getAnnotation(CheckManagement.class);
            String value = visitPermission.value();
            //根据不同的value处理不同的业务
            if(value.equals("annotation-one")){
                System.out.println("after-处理方式1 :------------------");
            }else if (value.equals("annotation-two")){
                System.out.println("after-处理方式2 :------------------");
            }else if (value.equals("annotation-three")){
                System.out.println("after-处理方式3 :------------------");
            }
            System.out.println("after--------------"+ value);
        }
    
        /**
         * 环绕
         * @param proceedingJoinPoint
         * @return
         * @throws Throwable
         */
        @Around("check()")
        public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            System.out.println("around start --------------------------");
            long startTime = System.currentTimeMillis();
    
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
    
            Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();
            CheckManagement visitPermission = method.getAnnotation(CheckManagement.class);
            String value = visitPermission.value();
    
            Object result = proceedingJoinPoint.proceed();
            long endTime = System.currentTimeMillis();
            Map<String, Object> infomation = getInfomation(request, proceedingJoinPoint, startTime, endTime);
            System.out.println("around end --------------------------");
            return result;
        }
    
        /**
         * 处理执行结果
         * @param request 请求体
         * @param proceedingJoinPoint
         * @param startTime 开始时间
         * @param endTime 结束时间
         * @return
         */
        private Map<String ,Object> getInfomation(HttpServletRequest request ,ProceedingJoinPoint proceedingJoinPoint,  long startTime, long endTime){
            Map<String , Object> map = new HashMap<>();
            // 请求 url
            String url = request.getRequestURL().toString();
            map.put("url" , url);
            //  Http method
            String HttpMethod = request.getMethod();
            map.put("HttpMethod" , HttpMethod);
            // 调用 controller 的全路径以及执行方法
            String declaringTypeName = proceedingJoinPoint.getSignature().getDeclaringTypeName();
            map.put("declaringTypeName",declaringTypeName);
            // 调用方法
            String method = proceedingJoinPoint.getSignature().getName();
            map.put("method",method);
            // 执行耗时
            map.put("time",(endTime - startTime));
            return map;
        }
    }

    五、测试方法:使用postman调用具体的接口

     六、测试结果:

    around start --------------------------
    before--------------annotation-one
    interface start -----------------------------
    around end --------------------------
    after-处理方式1 :------------------
    after--------------annotation-one

     根据测试结果你也可以看出不同类型的方式执行的顺序;

  • 相关阅读:
    必须克服的10种不良阅读习惯
    如何提升你的影响力
    爱情在线:拥抱变化的男女爱情!
    时间与生命
    女子最钟爱的五种男人
    社交常用表达:把人家的名字给忘了怎么办?
    最常用英语口头禅[推荐]
    中秋节的来历
    学会欣赏自己
    转帖]白领:4大行业通往高薪之路
  • 原文地址:https://www.cnblogs.com/dongl961230/p/13434937.html
Copyright © 2020-2023  润新知