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、测试