• springboot整合aop实现网站访问日志记录


    目的:

    统一日志输出格式,统计访问网站的ip.

    思路:

    1、针对不同的调用场景定义不同的注解,目前想的是接口层和服务层。

    2、我设想的接口层和服务层的区别在于:

      (1)接口层可以打印客户端IP,而服务层不需要

      (2)接口层的异常需要统一处理并返回,而服务层的异常只需要向上抛出即可

    3、就像Spring中的@Controller、@Service、@Repository注解那样,虽然作用是一样的,但是不同的注解用在不同的地方显得很清晰,层次感一下就出来了

    4、AOP去拦截特定注解的方法调用

    5、为了简化使用者的操作,采用Spring Boot自动配置

    如果要直接用@Aspect注解的话,要在spring的配置文件中加入

    <aop:aspectj-autoproxy />

    那么我们这里要不要在程序的主类中增加@EnableAspectJAutoProxy来启用呢?实际并不需要

    好的也就是说,只要引入SpringAOP相关的jar包依赖,我们就可以开始相关的Aspet的编程了。有时候拦截器也是可以实现的,但是如果我们采用的是post请求,如果使用拦截器就需要从报文中读取数据,

    其实就是io流,只能获取一次,所以在controller中无法获取数据,所以拦截器的方法是不可行的.

    首先需要引入依赖:

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-log4j</artifactId>
            </dependency>
    
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>

    controller中:

    package com.cxy.shibernate.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /***
     * @ClassName: HelloController
     * @Description:
     * @Auther: cxy
     * @Date: 2019/5/19:18:06
     * @version : V1.0
     */
    @Controller
    public class HelloController {
        @RequestMapping(value = "/hello", method = RequestMethod.GET)
        @ResponseBody
        public String hello(@RequestParam String name) {
            return "Hello " + name;
        }
    
    }

    工具类:

    package com.cxy.shibernate.controller;
    
    /***
     * @ClassName: HttpContextUtils
     * @Description:
     * @Auther: cxy
     * @Date: 2019/5/19:18:17
     * @version : V1.0
     */
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    
    public class HttpContextUtils {
    
        public static HttpServletRequest getHttpServletRequest() {
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            return servletRequestAttributes.getRequest();
        }
    //获取ip
        public static String getIpAddress() {
            HttpServletRequest request = getHttpServletRequest();
            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 != null && 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;
                    }
                }
            }
            return ip;
        }
    }

    切面:

    package com.cxy.shibernate.controller;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.Arrays;
    
    
    /***
     * @ClassName: WebLogAspect
     * @Description:
     * @Auther: cxy
     * @Date: 2019/5/19:18:08
     * @version : V1.0
     */
    @Aspect
    @Order(5)
    @Component
    public class WebLogAspect {
        private final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
    
        ThreadLocal<Long> startTime = new ThreadLocal<>();
        /**
       第一个*表示返回任何类型,com.cxy.shibernate.controller下任何类,任何方法,任何参数
         也可以加入参数限定例如com.cxy.shibernate.controller.*.*(..)&&args(name,..)
    
         下面那中表示方法也是对的,表示com.cxy.shibernate.下面任何子包下任何方法,任何参数
        **/
        @Pointcut("execution(public * com.cxy.shibernate..*.*(..))")
        public void webLog(){}
    
        @Before("webLog()")
        public void doBefore(JoinPoint joinPoint) throws Throwable {
            startTime.set(System.currentTimeMillis());
    
            // 接收到请求,记录请求内容
    
            HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
            String ipAddress = HttpContextUtils.getIpAddress();
    
            // 记录下请求内容
            logger.info("URL : " + request.getRequestURL().toString());
            logger.info("HTTP_METHOD : " + request.getMethod());
            logger.info("IP : " + request.getRemoteAddr());
            logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
            logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
            logger.info("ip:"+ipAddress);
    
        }
    
        @AfterReturning(returning = "ret", pointcut = "webLog()")
        public void doAfterReturning(Object ret) throws Throwable {
            // 处理完请求,返回内容
            logger.info("RESPONSE : " + ret);
            logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
        }
    
    
    
    }

    启动类:

    package com.cxy.shibernate;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class ShibernateApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ShibernateApplication.class, args);
        }
    
    }

    在application.yml不需要配置任何东西

    启动项目:

     

    当然可以配置文件输出的级别,制定输出的文件夹

  • 相关阅读:
    python读取二进制文件写入到txt
    python格式化输出
    字符编码
    python--随时记录
    python-web服务器
    openssh移植
    select、poll、epoll
    (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解
    heartbeat与keepalived的区别
    salt 常用命令整理
  • 原文地址:https://www.cnblogs.com/xiufengchen/p/10891027.html
Copyright © 2020-2023  润新知