- 介绍
最近自己在做项目时,因为要使用到日志记录功能,故翻阅之前自己的学习文章,从新理解并加以总结后加入自己的项目中,对此相关的一些技术知识点做一些分享。
- 环境
java:11
maven:3.8.1
springboot:2.6.6
注意:如若不熟悉AOP以及注解如何使用请先通过下文了解先。
- 添加依赖
<!-- 添加所需依赖 -->
<dependencies>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!--aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
- 自定义日志注解
LogAnnotation.java
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
// 设置所需参数以及默认值
String module() default "";
String operate() default "";
}
- 自定义日志切面类
LogAspect.java
@Component
@Aspect
@Slf4j
public class LogAspect {
/**
* 切点
* 注意:这里的路径最好写全路径 不写全有时会有错误
*
* 参数说明:
* 使用@annotation时,所修饰的方法或是接口都会被拦截。
* 使用execution时,指定你要切入的一个地方。
*/
//@Pointcut("@annotation(LogAnnotation)")
@Pointcut("@annotation(com.hetongxue.aop.log.LogAnnotation)")
public void pointcut() {
}
/**
* 通知
* 注意:对应上面得切点方法名称
*/
@Around("pointcut()")
public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
// 记录开始时长
long beginTime = System.currentTimeMillis();
// 执行方法
Object result = joinPoint.proceed();
// 执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
// 记录日志
recordLog(joinPoint, time);
return result;
}
/**
* 记录日志
*/
private void recordLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
log.info("===============================日志开始===============================");
log.info("日志模块:{}", logAnnotation.module());
log.info("日志操作:{}", logAnnotation.operate());
log.info("请求方法:{}", joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()");
log.info("请求参数:{}", JSON.toJSONString(joinPoint.getArgs()[0]));
log.info("请求时长:{} ms", time);
log.info("请求IP:{}", getRequestIp());
log.info("===============================日志结束===============================");
}
/**
* 获取请求IP地址
*/
private String getRequestIp() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
assert requestAttributes != null;
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
assert request != null;
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
- 使用
TestController.java
测试
@RestController
public class TestController {
@GetMapping("/test")
@LogAnnotation(module = "测试", operate = "测试使用")
public String test(@RequestParam String name) {
return Result.Success().setMessage("你好," + name + "!");
}
}
- 日志结果
2022-07-05 20:53:11.689 INFO 15548 --- [nio-8080-exec-1] com.hetongxue.aop.log.LogAspect : 日志模块:测试
2022-07-05 20:53:11.689 INFO 15548 --- [nio-8080-exec-1] com.hetongxue.aop.log.LogAspect : 日志操作:测试使用
2022-07-05 20:53:11.689 INFO 15548 --- [nio-8080-exec-1] com.hetongxue.aop.log.LogAspect : 请求方法:com.hetongxue.system.controller.TestController.test()
2022-07-05 20:53:11.703 INFO 15548 --- [nio-8080-exec-1] com.hetongxue.aop.log.LogAspect : 请求参数:["何同学"]
2022-07-05 20:53:11.703 INFO 15548 --- [nio-8080-exec-1] com.hetongxue.aop.log.LogAspect : 请求时长:3 ms
2022-07-05 20:53:11.703 INFO 15548 --- [nio-8080-exec-1] com.hetongxue.aop.log.LogAspect : 请求IP:127.0.0.1