java使用AOP切面获取请求日志并记录

简介: java使用AOP切面获取请求日志并记录


3.AOP切面如下

package com.tjair.tjapi.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tjair.common.log.TjapiLogVo;
import com.tjair.common.util.IPUtil;
import com.tjair.tjapi.feign.LogFeignService;
import com.tjair.tjapi.util.HttpHelper;
import io.swagger.annotations.ApiOperation;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.Objects;
/**
• @description 拦截所有控制器的返回,记录响应报文
• @author unhejing
• @date 2021-03-17 上午11:52:26
*/
@Aspect
@Configuration
@Slf4j
public class LogAspect {
@Autowired
private LogFeignService logFeignService;
public LogAspect() {
}
@Pointcut(“execution(public * com.tjair.tjapi.controller..(…))”)
public void pointCutMethod() {
}
// 声明环绕通知
@Around(“pointCutMethod()”)
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
Long startTime = System.currentTimeMillis();
ApiOperation apiOperation = ((MethodSignature)pjp.getSignature()).getMethod().getAnnotation(ApiOperation.class);
// 获取request对象
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletRequest request = sra.getRequest();
Object ret = pjp.proceed();
Long endTime = System.currentTimeMillis();
TjapiLogVo tjapiLogVo = getTjapiLogVo(request,Objects.nonNull(apiOperation) ? apiOperation.value() : “”,endTime-startTime,JSON.toJSONString(ret));
// 添加日志
addLog(tjapiLogVo);
log.info(“响应数据耗时{}:响应数据{}”,endTime-startTime,JSON.toJSONString(ret));
return ret;
}
public void addLog(TjapiLogVo tjapiLogVo) {
log.info(“添加日志:{}”,JSON.toJSONString(tjapiLogVo));
Long startTime = System.currentTimeMillis();
logFeignService.addTjapiLog(tjapiLogVo);
Long endtime = System.currentTimeMillis();
log.info(“添加日志耗时:{}”,endtime-startTime);
}
private TjapiLogVo getTjapiLogVo(HttpServletRequest request,String apiName,Long time,String response) throws IOException {
TjapiLogVo tjapiLogVo = new TjapiLogVo();
String jsonBody = HttpHelper.getBodyString(request);
log.info(“请求参数:{}”,jsonBody);
JSONObject reqObj = Objects.nonNull(JSON.parseObject(jsonBody)) ? JSON.parseObject(jsonBody) : new JSONObject();
JSONObject resObj = Objects.nonNull(JSON.parseObject(response)) ? JSON.parseObject(response) : new JSONObject();
//设置请求参数
tjapiLogVo.setParams(jsonBody);
tjapiLogVo.setPartnerid(Objects.nonNull(reqObj.getString(“partnerId”)) ? reqObj.getString(“partnerId”) : “-1”);
// 设置IP地址
tjapiLogVo.setIp(IPUtil.getIpAddr(request));
// 设置位置
tjapiLogVo.setLocation(IPUtil.getCityInfo(tjapiLogVo.getIp()));
//设置请求方法,GET,POST…
tjapiLogVo.setMethod(request.getMethod());
//设置请求路径
tjapiLogVo.setUrl(request.getRequestURI());
// 设置请求方法名称
tjapiLogVo.setApiName(apiName);
// 设置创建时间
tjapiLogVo.setCreateTime(new Date());
// 设置请求状态
Integer code = Objects.nonNull(resObj.getInteger(“code”)) ? resObj.getInteger(“code”) : 1;
tjapiLogVo.setStatus(code);
// 设置接口消耗时间
tjapiLogVo.setTime(time.intValue());
// 设置响应内容
tjapiLogVo.setResponse(response);
return tjapiLogVo;
}
}

4.测试接口

package com.tjair.tjapi.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tjair.common.service.RedisUtils;
import com.tjair.common.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
• @author jingyujie
• @create 2021-03-16 下午2:39
**/
@RestController
@RequestMapping(“/test”)
@Api(tags = “测试API控制器”)
public class TestController {
@Autowired
private RedisUtils redisUtils;
@PostMapping(“/apiTest”)
@ApiOperation(“接口测试”)
public Result apiTest(@RequestBody JSONObject obj){
return Result.returnSuccess(“接口已联通,请求入参:”+ JSON.toJSONString(obj));
}
}

5.请求结果如下

备注说明:

1.LogFeignService是添加日志的service

2.IPUtil是获取IP和地址信息相关的工具类

3.HttpHelper是解析request中的请求参数的工具类

4.ApiOperation是获取接口的注解上面的接口描述

5.partnerId是我请求参数里面必传的用户编码

6.code是响应参数里面的状态码,用于判断接口是否请求成功

末尾附上工具类:

IPUtil.java

类中的/ip2region.db这个是一个地址库,可直接百度下载即可。

package com.tjair.common.util;
import org.apache.commons.io.FileUtils;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.lionsoul.ip2region.Util;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.lang.reflect.Method;
/**
• ip操作相关工具类
• @author jingyujie
• @create 2020-06-24 下午2:11
**/
public class IPUtil {
public static String getCityInfo(String ip){
try {
//db
String dbPath = IPUtil.class.getResource(“/ip2region.db”).getPath();
System.out.println(“路径:”+dbPath);
File file = new File(dbPath);
if (file.exists() == false) {
System.out.println(“Error: Invalid ip2region.db file”);
String tmpDir = System.getProperties().getProperty(“java.io.tmpdir”);
dbPath = tmpDir + “ip.db”;
System.out.println(dbPath);
file = new File(dbPath);
FileUtils.copyInputStreamToFile(IPUtil.class.getClassLoader().getResourceAsStream(“classpath:ip2region.db”), file);
}
//查询算法
int algorithm = DbSearcher.BTREE_ALGORITHM; //B-tree
//DbSearcher.BINARY_ALGORITHM //Binary
//DbSearcher.MEMORY_ALGORITYM //Memory
DbSearcher searcher = null;
try {
DbConfig config = new DbConfig();
searcher = new DbSearcher(config, dbPath);


相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
相关文章
|
10月前
|
SQL druid Oracle
【YashanDB知识库】yasdb jdbc驱动集成druid连接池,业务(java)日志中有token IDENTIFIER start异常
客户Java日志中出现异常,影响Druid的merge SQL功能(将SQL字面量替换为绑定变量以统计性能),但不影响正常业务流程。原因是Druid在merge SQL时传入null作为dbType,导致无法解析递归查询中的`start`关键字。
|
11月前
|
XML JSON Java
Java中Log级别和解析
日志级别定义了日志信息的重要程度,从低到高依次为:TRACE(详细调试)、DEBUG(开发调试)、INFO(一般信息)、WARN(潜在问题)、ERROR(错误信息)和FATAL(严重错误)。开发人员可根据需要设置不同的日志级别,以控制日志输出量,避免影响性能或干扰问题排查。日志框架如Log4j 2由Logger、Appender和Layout组成,通过配置文件指定日志级别、输出目标和格式。
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
978 8
|
Java Maven
java项目中jar启动执行日志报错:no main manifest attribute, in /www/wwwroot/snow-server/z-server.jar-jar打包的大小明显小于正常大小如何解决
在Java项目中,启动jar包时遇到“no main manifest attribute”错误,且打包大小明显偏小。常见原因包括:1) Maven配置中跳过主程序打包;2) 缺少Manifest文件或Main-Class属性。解决方案如下:
2927 8
java项目中jar启动执行日志报错:no main manifest attribute, in /www/wwwroot/snow-server/z-server.jar-jar打包的大小明显小于正常大小如何解决
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
482 0
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
332 1
|
人工智能 Oracle Java
解决 Java 打印日志吞异常堆栈的问题
前几天有同学找我查一个空指针问题,Java 打印日志时,异常堆栈信息被吞了,导致定位不到出问题的地方。
353 2
|
Java
Java的aop是如何实现的?原理是什么?
Java的aop是如何实现的?原理是什么?
173 4
|
3月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
243 1
|
3月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
257 1