SpringBoot下使用AOP做日志

AOP实现接口执行时间的计算:

  • SpringBoot项目导入spring-boot-starter-aop依赖
  • 编写切面类
    • 类上加@Aspect注解,表明这是一个切面类
    • 类上加@Component,把切面交给Spring管理(我们要切的Controller/Service都是Spring容器的,切面要对它们起作用,就必须同样进入容器)
    • 类内部配置切点表达式,比如@Pointcut("execution(* com.bravo.demo.controller.*.*(..))") 表示对com.bravo.demo.controller包下所有方法进行增强
    • 类内部编写增强逻辑,通常使用@Before、@Around声明这是一个增强,不同的注解增强的方式不同,比如@Before前置增强、@Around环绕增强

1、导入AOP整合SpringBoot依赖

 <!--SpringBoot整合Aop依赖-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>

2、编写切面类:com.zhixi.config.aop.ApiTimeLogAspect

import lombok.extern.slf4j.Slf4j;
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;

/**
 * @ClassName ApiTimeLogAspect
 * @Author zhangzhixi
 * @Description
 * @Date 2022-4-15 10:42
 * @Version 1.0
 */
@Slf4j
/*第一步:声明这是一个切面类*/
@Aspect
@Component
public class ApiTimeLogAspect {

    /**
     * 第二步:定义切点表达式,明确要对那些方法起作用(比如,只对com.bravo.demo.controller包的方法计算接口耗时)
     */
    @Pointcut("execution(* com.zhixi.controller.*.*(..))")
    public void controllerPointcut() {
    }

    /**
     * 第三步:1.通过引用切点表达式,明确这个增强的应用规则。 2.编写增强逻辑
     *
     * @param proceedingJoinPoint 执行目标方法的参数
     * @return 返回目标方法的执行结果
     * @throws Throwable proceedingJoinPoint.proceed()方法抛出的异常
     */
    @Around(value = "controllerPointcut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        // 记录接口执行前的时间戳
        long startTime = System.currentTimeMillis();
        // 实际执行目标方法,类似动态代理的invoke()执行目标方法
        Object result = proceedingJoinPoint.proceed();
        // 计算接口耗时
        log.info("------------ 耗时: {} ms ------------", System.currentTimeMillis() - startTime);
        // 只做增强不做改变,还是要把接口原本的结果返回
        return result;
    }
}

3、启动项目访问接口即可

AOP获取请求的浏览器信息

1、依赖

<dependencies>
    <!--Lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <!--fastjson依赖-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.73</version>
    </dependency>
    <!--获取浏览器信息-->
    <dependency>
        <groupId>eu.bitwalker</groupId>
        <artifactId>UserAgentUtils</artifactId>
        <version>1.21</version>
    </dependency>
    <!--SpringBoot整合Aop依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <!--SpringBoot-Web依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

2、工具类(对上一版进行了优化)

package com.zhixi.util;

import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import eu.bitwalker.useragentutils.Version;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class IpAndAddrUtil {
    private static final String UNKNOWN = "unknown";
    private static final String[] PROXY_HEADERS = {"x-forwarded-for", "Proxy-Client-IP", "WL-Proxy-Client-IP"};

    /**
     * 获取发起请求的IP地址
     */
    public static String getIp(HttpServletRequest request) {
        String ip = null;
        for (String header : PROXY_HEADERS) {
            ip = request.getHeader(header);
            if (ip != null && ip.length() != 0 && !UNKNOWN.equalsIgnoreCase(ip)) {
                break;
            }
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if ("127.0.0.1".equals(ip)) {
                try {
                    ip = InetAddress.getLocalHost().getHostAddress();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
            }
        }
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        return ip;
    }

    /**
     * 获取发起请求的浏览器名称
     */
    public static String getBrowserName(HttpServletRequest request) {
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        Browser browser = userAgent.getBrowser();
        return browser.getName();
    }

    /**
     * 获取发起请求的浏览器版本号
     */
    public static String getBrowserVersion(HttpServletRequest request) {
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        Browser browser = userAgent.getBrowser();
        Version version = browser.getVersion(request.getHeader("User-Agent"));
        return version == null ? null : version.getVersion();
    }

    /**
     * 获取发起请求的操作系统名称
     */
    public static String getOsName(HttpServletRequest request) {
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        OperatingSystem os = userAgent.getOperatingSystem();
        return os.getName();
    }
}

3、AOP:前置通知

package com.zhixi.aop;

import com.alibaba.fastjson.JSONObject;
import com.zhixi.util.IpAndAddrUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
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 javax.servlet.http.HttpServletRequest;

@Aspect
@Component
@Slf4j
public class LogBrowserAspect {

    @Pointcut("execution(* com.zhixi.controller.*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        /*获取请求IP*/
        String requestIp = IpAndAddrUtil.getIp(request);
        /*获取发起请求的浏览器版本号*/
        String browserVersion = IpAndAddrUtil.getBrowserVersion(request);
        /*获取发起请求的操作系统名称*/
        String osName = IpAndAddrUtil.getOsName(request);
        /*获取发起请求的浏览器名称*/
        String browserName = IpAndAddrUtil.getBrowserName(request);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("requestURL", request.getRequestURL());
        jsonObject.put("ip", requestIp);
        jsonObject.put("browserVersion", browserVersion);
        jsonObject.put("osName", osName);
        jsonObject.put("browserName", browserName);
        jsonObject.forEach((k, v) -> {
            log.info(k + ":" + v);
        });
    }
}

4、测试  

posted @ 2022-04-15 19:02  Java小白的搬砖路  阅读(365)  评论(0编辑  收藏  举报