• spring aop 配置(controller层 配置包名)


    今天在 PLAY项目里面, 要配置一个aop,拦截controller的所有请求,把入参都记录下来。

    步骤1:引入aop的依赖:

             <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>

    步骤2:添加aop配置的类:

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import first.zxz.tools.StringUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import org.springframework.web.multipart.MultipartFile;
    import simple.proj.zxz.play.pojo.entity.LogEntity;
    import simple.proj.zxz.play.pojo.vo.FieldVO;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    import java.util.Collection;
    import java.util.Date;
    
    /**
     * 控制器层的aop
     *
     * @author zhangxz
     * 2019/11/6
     */
    
    
    @Aspect
    @Component
    @Slf4j
    public class ControllerAop {
    
        //get方法类型
        private static final String METHOD_TYPE_GET = "GET";
    
        //controller层的aop配置
    
        //配置注解
        //@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.GetMapping)")
    
        //配置指定包下的类,不包含子包
        //@Pointcut("execution(* simple.proj.zxz.play.controller.acg.*.*(..))")
    
        //配置指定包下的类,包含所有子包的类
        @Pointcut("execution(* simple.proj.zxz.play.controller..*.*(..))")
        public void controllerAspect() {
        }
    
    
        /**
         * 切面方法,在方法执行期间,记录方法的入参,返回结果,执行时长等信息
         *
         * @param joinPoint 切面数据
         * @return java.lang.Object
         * @author Zxz
         * @date 2019/11/7 11:46
         **/
        @Around(value = "controllerAspect()")
        public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    
            long startTime = System.currentTimeMillis();
    
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    
            LogEntity logEntity = new LogEntity();
    
            logEntity.setCreateTime(new FieldVO<>(new Date()));
            logEntity.setReqData(getReqDataStr(joinPoint));
            logEntity.setRemoteIp(getIp(request));
    
            logEntity.setReqApi(request.getRequestURL().toString());
            logEntity.setReqType(request.getMethod());
    
            logEntity.setReqMethod(joinPoint.getSignature().toShortString());
    
            try {
                Object proceed = joinPoint.proceed();
    
                long endTime = System.currentTimeMillis();
                logEntity.setMethodHandleMilliseconds(endTime - startTime);
    
                if (!isIdempotentMethod(request.getMethod())) {
                    logEntity.setResult(proceed.toString());
                }
    
                log.info("controller request data: " + JSON.toJSONString(logEntity, true));
    
                return proceed;
            } catch (Throwable throwable) {
    
                long endTime = System.currentTimeMillis();
                logEntity.setMethodHandleMilliseconds(endTime - startTime);
    
                logEntity.setErrorMsg(throwable.getMessage());
                log.info("controller request data: " + JSON.toJSONString(logEntity, true));
    
                throw throwable;
            }
    
    
        }
    
        /**
         * 判断方法类型是否为幂等性的方法
         * 只有类型为GET的方法,才是幂等性的。
         *
         * @param methodType 方法类型
         * @return boolean
         * @author Zxz
         * @date 2019/11/7 11:43
         **/
        private boolean isIdempotentMethod(String methodType) {
            if (StringUtil.isEmptyAndBlank(methodType)) {
                return false;
            }
            return methodType.trim().toUpperCase().equals(METHOD_TYPE_GET);
        }
    
        /**
         * 获取请求的ip地址
         *
         * @param request 请求
         * @return java.lang.String
         * @author Zxz
         * @date 2019/11/7 11:39
         **/
        private static String getIp(HttpServletRequest request) {
            if (request == null)
                return null;
            String ip = request.getHeader("X-Forwarded-For");
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
    
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
    
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
    
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
    
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
    
            if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
                try {
                    ip = InetAddress.getLocalHost().getHostAddress();
                } catch (UnknownHostException e) {
                    log.error(e.getLocalizedMessage(), e);
                }
            }
            return ip;
        }
    
        /**
         * 获取请求参数,构造成字符串
         *
         * @param joinPoint 数据
         * @return java.lang.String
         * @author Zxz
         * @date 2019/11/6 17:37
         **/
        private String getReqDataStr(JoinPoint joinPoint) {
            StringBuilder result = new StringBuilder();
            if (joinPoint.getArgs() == null || joinPoint.getArgs().length <= 0) {
                return result.toString();
            }
            for (Object arg : joinPoint.getArgs()) {
                if (isInputString(arg)) {
                    String jsonString = JSON.toJSONString(arg,
    //                        SerializerFeature.NotWriteDefaultValue,
                            SerializerFeature.DisableCircularReferenceDetect,
                            SerializerFeature.WriteClassName);
                    result.append(jsonString).append(",");
                }
            }
    
            //去除最后一个逗号
            if (result.length() > 0) {
                result.deleteCharAt(result.length() - 1);
            }
            return result.toString();
        }
    
        /**
         * 判断对象是否是用户输入的数据
         *
         * @param arg 对象
         * @return boolean
         * @author Zxz
         * @date 2019/11/6 17:40
         **/
        private boolean isInputString(Object arg) {
            return !(arg instanceof HttpServletRequest)
                    && !(arg instanceof HttpServletResponse)
                    && !(containsMultipartFile(arg));
        }
    
        /**
         * 判断是否包含MultipartFile类型数据
         *
         * @param object 数据
         * @return boolean
         * @author Zxz
         * @date 2019/11/6 17:37
         **/
        private boolean containsMultipartFile(Object object) {
            if (object instanceof MultipartFile) {
                return true;
            }
            if (object instanceof Collection) {
                Collection list = (Collection) object;
                for (Object o : list) {
                    if (o instanceof MultipartFile) {
                        return true;
                    }
                }
            }
            return false;
        }
    
    }

    以上两步完成之后,项目运行过程中,每次有请求到达Controller层的接口时,都会去记录该请求的具体情况:客户端ip,请求数据,请求类型,请求方法名,请求执行总时间,请求返回结果,错误信息等。

  • 相关阅读:
    统计学习方法 学习笔记(八):k 近邻法
    统计学习方法 学习笔记(七):拉格朗日对偶性
    统计学习方法 学习笔记(六):序列最小最优化算法SMO
    统计学习方法 学习笔记(五):支持向量机(下)
    统计学习方法 学习笔记(四):支持向量机(中)
    统计学习方法 学习笔记(三):支持向量机(上)
    统计学习方法 学习笔记(二):感知机
    CUDA npp运动检测模块性能测试
    CUDA H624解码性能测试
    利用GPU改善程序性能的一点心得
  • 原文地址:https://www.cnblogs.com/zhangxuezhi/p/11812020.html
Copyright © 2020-2023  润新知