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依赖

csharp;gutter:true; org.springframework.boot spring-boot-starter-aop</p> <pre><code> > 2、编写切面类:com.zhixi.config.aop.ApiTimeLogAspect ;gutter:true;
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、启动项目访问接口即可

SpringBoot下使用AOP做日志

AOP获取请求的浏览器信息

1、依赖

csharp;gutter:true; org.projectlombok lombok</p> <pre><code> com.alibaba fastjson 1.2.73 eu.bitwalker UserAgentUtils 1.21 org.springframework.boot spring-boot-starter-aop org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test </code></pre> <pre><code> > 2、工具类(对上一版进行了优化) ;gutter:true;
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:前置通知

csharp;gutter:true; package com.zhixi.aop;</p> <p>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;</p> <p>import javax.servlet.http.HttpServletRequest;</p> <p>@Aspect @Component @Slf4j public class LogBrowserAspect {</p> <pre><code>@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); }); } </code></pre> <p>}

4、测试

SpringBoot下使用AOP做日志

Original: https://www.cnblogs.com/zhangzhixi/p/16150607.html
Author: Java小白的搬砖路
Title: SpringBoot下使用AOP做日志

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/612329/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Java的值传递

    1. 形参和实参 实参(实际参数) :用于传递给函数/方法的参数,必须有确定的值。 形参(形式参数) :用于定义函数/方法,接收实参,不需要有确定的值 2. 值传递和引用传递 值传…

    数据库 2023年6月14日
    072
  • 使用Java刷评论为平台引流的经历

    场景:需要在一网站中批量评论留言。分析接口:列表接口获取idList,返回的是json数据直接用FastJson转就可以,如果返回的是HTML片段,则需要使用Jsoup进行提取,值…

    数据库 2023年6月14日
    0108
  • PostgreSQL 和 MySQL 在用途、好处、特性和特点上的异同

    PostgreSQL 和 MySQL 在用途、好处、特性和特点上的异同。 PostgreSQL 和 MySQL 是将数据组织成表的关系数据库。这些表可以根据每个表共有的数据链接或关…

    数据库 2023年5月24日
    095
  • 常见的位操作及其应用

    概述 与、或、异或、取反或者移位运算这几种基本的位操作想必诸位读者并不陌生,如果我们能在某些合适场景下使用位运算,有些时候可以大大提高算法的效率。但由于本身位运算太过灵活,甚至某些…

    数据库 2023年6月11日
    078
  • MySQL之group by分组查询

    有如下数据: 一个简单的分组查询案例 [En] A simple case of grouping query 按照部门编号deptno分组,统计每个部门的平均工资。 select…

    数据库 2023年5月24日
    0104
  • mysql约束

    一、表约束 PK主键约束(索引)唯一约束 非空 默认值 在关系数据库,一个表中,只能有一个主键(Primary Key),有些数据库没有pk,系统报出错误。 在myql数据库,建立…

    数据库 2023年6月9日
    083
  • Ceph创建一个新集群 报错: File “/usr/bin/ceph-deploy”, line 18, in……….

    [root@ceph-node1 ceph]# ceph-deploy new node1 Traceback (most recent call last): File &quo…

    数据库 2023年6月14日
    082
  • 2022-8-18 第六组 JDBC

    JDBC 1. 概念:Java DataBase Connectivity Java 数据库连接, Java语言操作数据库 JDBC本质:其实是官方(sun公司)定义的一套操作所有…

    数据库 2023年6月14日
    082
  • Go语言常见的并发模式

    Go语言常见的并发模式 并发不是并行 并发关注的是程序的设计层面,并发的程序也可以顺序执行,在多核CPU上才可能真正同时的运行,并行关注的是程序的运行层面,如GPU中对图像处理都会…

    数据库 2023年6月16日
    074
  • springboot~Cache注解缓存在代码中的获取

    对于springboot中基于方法的缓存Caching来说,我们直接以声明的方式添加,删除这些缓存,而它们在redis这种持久化产品中,通过 value::key的方法组成一个re…

    数据库 2023年6月6日
    094
  • Question03-查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩

    * SELECT stu.SID, stu.Sname, CAST(AVG(sc.score) AS DECIMAL(18,2)) avg_score FROM Student s…

    数据库 2023年6月16日
    067
  • 从源码分析 XtraBackup 的备份原理

    MySQL物理备份工具,常用的有两个:MySQL Enterprise Backup 和 XtraBackup。 前者常用于MySQL企业版,后者常用于MySQL社区版、Perco…

    数据库 2023年6月11日
    0124
  • Selenium 4 有哪些不一样?

    转载请注明出处❤️ 作者:测试蔡坨坨 原文链接:caituotuo.top/d59b986c.html 你好,我是测试蔡坨坨。 众所周知,Selenium在2021年10月13号发…

    数据库 2023年6月11日
    085
  • MySQL优化之索引解析

    索引的本质 MySQL索引或者说其他关系型数据库的索引的本质就只有一句话, 以空间换时间。 索引的作用 索引关系型数据库为了 加速对表中行数据检索的( 磁盘存储的) 数据结构 索引…

    数据库 2023年5月24日
    089
  • VSCode快捷键

    基础编辑 作用 WINDOWS 剪切行 Ctrl + X 复制行 Ctrl + C 向上/向下移动行 Alt + ↑↓ 向上/向下复制行 Shift + Alt + ↑↓ 删除行 …

    数据库 2023年6月6日
    0142
  • bat 脚本启用及禁用网卡

    启用网卡 需要以管理员身份运行bat脚本 netsh interface set interface "Npcap Loopback Adapter" enab…

    数据库 2023年6月9日
    0124
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球