springboot+@Aspect+@Log实现切面日志打印
程序员文章站
2022-05-07 19:01:32
在接口开发过程中,我们经常需要打印入参出参的log,来定位问题,比如:logger.info("xx接口返回结果{}", JSON.toJSONString(result));有时我们想要知道调用的ip地址,调用方法名等信息,那么这样一行代码就不能满足我们的要求。基于springboot项目,我们可以使用@Aspect注解声明一个日志切面,在此切面中完成统一的返回日志打印或异常日志打印,下面详细介绍:首先我们自定义一个注解Log,注解中可以定义一些属性,比如title接口注释/** * 自定义...
在接口开发过程中,我们经常需要打印入参出参的log,来定位问题,比如:
logger.info("xx接口返回结果{}", JSON.toJSONString(result));
有时我们想要知道调用的ip地址,调用方法名等信息,那么这样一行代码就不能满足我们的要求。
基于springboot项目,我们可以使用@Aspect
注解声明一个日志切面,在此切面中完成统一的返回日志打印或异常日志打印,下面详细介绍:
1.首先我们自定义一个注解Log,注解中可以定义一些属性,比如title接口注释
/**
* 自定义操作日志记录注解
*
* @author china
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/**
* 接口注释
*/
String title() default "";
}
2.在接口中使用@Log的注解来开启,注意注解只能作用在方法上
@Log(title = "切面测试接口")
@GetMapping()
public String hello() {
for (int i = 0; i < 10; i++) {
String traceId = UUID.randomUUID().toString();
log.info("请求打印traceId:" + traceId);
}
return "日志切面接口测试成功";
}
3.接下来我们开始介绍@Aspect注解,首先介绍下相关注解
@Aspect:作用是把当前类标识为一个切面供容器读取
@Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice
@After: final增强,不管是抛出异常或者正常退出都会执行
下面贴出LogAspect代码,方法logPointCut定义了一个切点,注解@PointCut中@annotation(),括号中表示上述我们定义的@Log注解的位置,当然我们也可以使用切点表达式execution(),方法doAfterReturning和doAfterThrowing是正常返回和异常返回执行的方法。
/**
* 系统日志切面
*/
@Aspect
@Component
public class LogAspect {
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
/**
* 这里我们使用注解的形式
* 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
* 切点表达式: execution(...)
*/
@Pointcut("@annotation(com.demo.framework.aspectj.lang.annotation.Log)")
public void logPointCut() {
}
/**
* 处理完请求后执行
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
saveLog(joinPoint, null, jsonResult);
}
/**
* 拦截异常操作
*
* @param joinPoint 切点
* @param e 异常
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
saveLog(joinPoint, e, null);
}
}
4.方法saveLog为业务逻辑方法,主要是解释如何获取需要打印的内容,如下:
/**
* 保存日志
*/
private void saveLog(JoinPoint joinPoint, final Exception e, Object jsonResult) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 请求的地址
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
LogBO sysLogBO = new LogBO();
sysLogBO.setIp(ip);
sysLogBO.setResult(JSON.toJSONString(jsonResult));
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sysLogBO.setCreateDate(dateFormat.format(new Date()));
Log sysLog = method.getAnnotation(Log.class);
if (sysLog != null) {
//注解上的描述
sysLogBO.setRemark(sysLog.title());
}
//请求的 类名、方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLogBO.setClassName(className);
sysLogBO.setMethodName(methodName);
//请求的参数
Object[] args = joinPoint.getArgs();
try {
List<String> list = new ArrayList<String>();
for (Object o : args) {
list.add(JSON.toJSONString(o));
}
sysLogBO.setParams(list.toString());
} catch (Exception ex) {
// 记录本地异常日志
log.error("异常信息:{}", ex.getMessage());
}
log.info("ip地址:{},创建时间:{},调用方法名:{},参数:{},返回值:{}",
sysLogBO.getIp(), sysLogBO.getCreateDate(), sysLogBO.getMethodName(), sysLogBO.getParams(), sysLogBO.getResult());
}
5.至此,代码部分结束,主要是介绍了使用@Aspect定义日志切面,最后贴出测试结果:
参考文章:https://blog.csdn.net/zhuzhezhuzhe1
本文地址:https://blog.csdn.net/weixin_38117908/article/details/107283999
推荐阅读
-
FFmpeg调用c语言SDK实现日志的打印
-
springboot+@Aspect+@Log实现切面日志打印
-
springboot配置aop切面日志打印过程解析
-
SpringBoot2.0 基础案例(02):配置Log4j2,实现不同环境日志打印
-
利用spring 框架的AOP来实现日志打印
-
打印HTTP request body和response body实现日志跟踪
-
Spring Boot如何通过自定义注解实现日志打印详解
-
java最简单实现Log打印和生成日志文件
-
Spring Boot 中使用自定义注解,AOP 切面打印出入参日志及Dubbo链路追踪透传traceId
-
log4j打印日志文件 如何实现相对路径到 项目工程下