需求分析
需求经过日志记载接口调用信息。便于后期调试排查。而且可能有许多接口都需求进行日志的记载。
接口被调用时日志打印格局如下:
log.info("=======Start=======");
// 打印恳求 URL
log.info("URL : {}",);
// 打印描绘信息
log.info("BusinessName : {}", );
// 打印 Http method
log.info("HTTP Method : {}", );
// 打印调用 controller 的全途径以及履行办法
log.info("Class Method : {}.{}", );
// 打印恳求的 IP
log.info("IP : {}",);
// 打印恳求入参
log.info("Request Args : {}",);
// 打印出参
log.info("Response : {}", );
// 完毕后换行
log.info("=======End=======" + System.lineSeparator());
思路分析
适当所以对原有的功用进行增强。而且是批量的增强,这个时候就十分适合用AOP来进行实现,例如对更新用户的接口进行日志记载,当用户调用这个接口的时候,对调用的信息进行记载
@PutMapping("/userInfo")
public ResponseResult updateUserInfo(@RequestBody User user){
return userService.updateUserInfo(user);
}
代码实现
界说自界说注解@SystemLog
创立接口
在annotation
包下创立SystemLog
@Retention(RetentionPolicy.RUNTIME)
表明在运行是收效
@Target(ElementType.METHOD)
效果类型是办法
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SystemLog {
String businessName();
}
界说切面类LogAspect
@Pointcut注解
,它主要界说切入点,用来符号一个办法以及在何处触发断点。它能够界说切入点表达式,符号一个办法,以及指定何时履行某个动作。
@Around注解
能够用来在调用一个详细办法前和调用后来完成一些详细的任务。比如在在调用pt()
办法前调用printLog()
办法。
@Aspect //该注解声明这个类为一个切面类
@Component
@Slf4j
public class LogAspect {
@Pointcut("@annotation(com.whj.annotation.SystemLog)")
public void pt() {
}
@Around("pt()")
public Object printLog(ProceedingJoinPoint joinPoint) throws Throwable{
Object ret;
try {
handleBefore(joinPoint);
// 回来履行的成果
ret = joinPoint.proceed();
handleAfter(ret);
} finally {
// 完毕后换行
log.info("=======End=======" + System.lineSeparator());
}
return ret;
}
private void handleAfter(Object ret) {
// 打印出参
log.info("Response : {}", JSON.toJSON(ret));
}
private void handleBefore(ProceedingJoinPoint joinPoint) {
// 向下转行 获取被增强办法的URL
ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
//获取被增强办法的注解目标
SystemLog systemLog = getSystemLog(joinPoint);
log.info("=======Start=======");
// 打印恳求 URL
log.info("URL : {}",request.getRequestURL());
// 打印描绘信息
log.info("BusinessName : {}", systemLog.businessName());
// 打印 Http method
log.info("HTTP Method : {}", request.getMethod());
// 打印调用 controller 的全途径以及履行办法
log.info("Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(),joinPoint.getSignature().getName());
// 打印恳求的 IP
log.info("IP : {}",request.getRemoteHost());
// 打印恳求入参
log.info("Request Args : {}", JSON.toJSON(joinPoint.getArgs()));
}
private SystemLog getSystemLog(ProceedingJoinPoint joinPoint) {
//将增强办法的全体作为一个目标封装成methodSignature
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
// 获取办法上的注解
SystemLog systemLog = methodSignature.getMethod().getAnnotation(SystemLog.class);
return systemLog;
}
}
在需求记载日志的办法加上注解
@PutMapping("/userInfo")
@SystemLog(businessName="更新用户信息")
public ResponseResult updateUserInfo(@RequestBody User user){
return userService.updateUserInfo(user);
}
运行成果