• 利用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

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

  • 相关阅读:
    Siege 3.0 正式版发布,压力测试工具
    Pomm 1.1.2 发布,专为 PG 设计的 ORM 框架
    Whonix 0.5.6 发布,匿名通用操作系统
    国内开源 java cms,Jspxcms 2.0 发布
    EZNamespaceExtensions.Net v2013增加对上下文菜单、缩略图、图标、属性表的支持
    GNU Guile 2.0.9 发布,Scheme 实现
    jdao 1.0.4 发布 轻量级的orm工具包
    OpenSearchServer 1.4 RC4 发布
    Percona Server for MySQL 5.5.3030.2
    Samba 4.0.5 发布
  • 原文地址:https://www.cnblogs.com/dongl961230/p/13434937.html
Copyright © 2020-2023  润新知