zoukankan      html  css  js  c++  java
  • spring boot使用自定义注解+AOP实现对Controller层指定方法的日志记录

    1.创建一个spring boot项目,导入maven依赖:

    	<dependencies>
    		<dependency>
    			<groupId>com.google.code.gson</groupId>
    			<artifactId>gson</artifactId>
    			<version>2.8.6</version>
    		</dependency>
            <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>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    

    2.自定义RecordLog注解:

    import java.lang.annotation.*;
    
    @Target(ElementType.METHOD) // 此注解适用于方法上
    @Retention(RetentionPolicy.RUNTIME) // 此注解不仅被保存到class文件中,jvm加载class文件之后依然存在
    @Documented
    /**
     * 用于标识方法需要记录日志
     */
    public @interface RecordLog {
        /**
         * 方法描述
         *
         * @return
         */
        String desc() default "";
    }
    

    3.定义一个IP工具类获取访问的ip地址:

    import javax.servlet.http.HttpServletRequest;
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    /**
     * @ClassName: IPUtil
     * @Description:获取ip地址工具类
     * @author: jinghx
     * @date: 2020/5/26 16:28
     */
    public class IPUtil {
        private IPUtil() {
        }
    
        /**
         * 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址;
         *
         * @param request
         * @return
         */
        public final static String getIpAddress(HttpServletRequest request) throws UnknownHostException {
            // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址
            String ip = request.getHeader("X-Forwarded-For");
    
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                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();
                }
            } else if (ip.length() > 15) {
                String[] ips = ip.split(",");
                for (int index = 0; index < ips.length; index++) {
                    String strIp = (String) ips[index];
                    if (!("unknown".equalsIgnoreCase(strIp))) {
                        ip = strIp;
                        break;
                    }
                }
            }
            if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
                // 根据网卡取本机配置的IP
                ip = getLocalIp();
            }
            return ip;
        }
    
        /**
         * 获取本机IP
         */
        public static String getLocalIp() throws UnknownHostException {
            InetAddress inetAddress = InetAddress.getLocalHost();
            String ip = inetAddress.getHostAddress().toString();//获得本机Ip
            return ip;
        }
    }
    

    4.编码实现切面类:

    /**
     * @ClassName: LogAspect
     * @Description: 日志切面
     * @author: jinghx
     * @date: 2020/5/26 15:42
     */
    @Aspect // 标识这是一个切面类
    @Component // 把切面类加入到IOC容器中
    public class LogAspect {
    
        private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
        /**
         * 切入点表达式
         */
        public static final String exp = "@annotation(com.learn.annotation.RecordLog)"; // "execution(* com.learn.controller..*(..))";
    
        /**
         * 定义切入点
         */
        @Pointcut(exp)
        public void logAspect() {
        }
    
        /**
         * 切面方法(环绕通知)
         *
         * @param joinPoint
         * @return
         * @throws Exception
         */
        @Around("logAspect()")
        public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
            long startTime = System.currentTimeMillis(); // 开始时间
            Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            // 获取方法描述
            String methodDesc = methodSignature.getMethod().getAnnotation(RecordLog.class).desc();
            // 获取Request对象
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
    
            log.info("-----------开始访问方法:" + LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "-------------");
            // 方法描述
            log.info("方法描述:{}", methodDesc);
            // 请求url
            log.info("请求url:{}", request.getRequestURL().toString());
            // 请求类型
            log.info("请求类型:{}", request.getMethod());
            // 请求方法
            log.info("请求方法:{}.{}", signature.getDeclaringTypeName(), methodSignature.getName());
            // 请求IP
            log.info("请求IP:{}", IPUtil.getIpAddress(request));
            // 请求参数
            log.info("请求参数:{}", new Gson().toJson(joinPoint.getArgs()));
    
            Object result = joinPoint.proceed();
    
            // 请求耗时
            log.info("请求耗时:{}ms", System.currentTimeMillis() - startTime);
            // 请求返回
            log.info("请求返回:{}", new Gson().toJson(result));
            log.info("------------------请求结束-----------------------");
            return result;
        }
    
    }
    

    5.编写一个Controller类进行测试:

    /**
     * @ClassName: UserController
     * @Description: 用户Controller
     * @author: jinghx
     * @date: 2020/5/26 15:38
     */
    @RestController
    public class UserController {
    
        @GetMapping("/hello")
        @RecordLog(desc = "这个一个用于问好的方法")
        public String sayHello(String name) {
            return "hello," + name + "!";
        }
    
    }
    

    最终项目结构:
    在这里插入图片描述
    启动项目,在浏览器中输入:http://localhost:8080/hello?name=德玛西亚

    日志输出:
    在这里插入图片描述

    一颗安安静静的小韭菜。文中如果有什么错误,欢迎指出。
  • 相关阅读:
    makefile ifeq ($(LANG),) 判断操作系统
    MIPS 指令集速查
    ps ef|grep mh* 命令
    ulimit c unlimited 命令
    kill 9 2402 命令
    chmod R 777 命令
    计算机网络总结
    source 命令
    ./ 命令
    reboot f 命令
  • 原文地址:https://www.cnblogs.com/c-Ajing/p/13448341.html
Copyright © 2011-2022 走看看