springboot-自定义注解实现入参出参打印日志
原理:自定义注解+AOP切面
第1步,新建springboot项目
项目中必须有web依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
第2步,自定义注解
自定义一个WebLog注解,后面会用到controller的方法上
import java.lang.annotation.*;
/**
* 打印方法入参和出参的注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface WebLog {
/**
* 日志描述信息
*
* @return
*/
String description() default "";
}
第3步,为注解配置切面
- 使用@WebLog作为切点,这样所有配置了该注解的方法,都能被切面切到。
- 使用前置通知doBefore打印入参信息;
- 使用环绕通知doAround打印出参信息;
import cn.demo.annotation.WebLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
@Aspect
@Component
@Slf4j
public class WebLogAspect {
/**
* 换行符
*/
private static final String LINE_SEPARATOR = System.lineSeparator();
/**
* 以自定义 @WebLog 注解为切点
*/
@Pointcut("@annotation(cn.demo.annotation.WebLog)")
public void webLog() {
}
/**
* 在切点之前织入
*
* @param joinPoint
* @throws Throwable
*/
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 开始打印请求日志
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 获取 @WebLog 注解的描述信息
String methodDescription = getAspectLogDescription(joinPoint);
// 打印请求相关参数
log.info("========================================== Start ==========================================");
// 打印请求 url
log.info("URL : {}", request.getRequestURL().toString());
// 打印描述信息
log.info("Description : {}", methodDescription);
// 打印 Http method
log.info("HTTP Method : {}", request.getMethod());
// 打印调用 controller 的全路径以及执行方法
log.info("Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
// 打印请求的 IP
log.info("IP : {}", request.getRemoteAddr());
// 打印请求入参
log.info("Request Args : {}", joinPoint.getArgs());
}
/**
* 在切点之后织入
*
* @throws Throwable
*/
@After("webLog()")
public void doAfter() throws Throwable {
// 接口结束后换行,方便分割查看
log.info("=========================================== End ===========================================" + LINE_SEPARATOR);
}
/**
* 环绕
*
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("webLog()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
// 打印出参
log.info("Response Args : {}", result);
// 还可以打印执行耗时
//log.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
return result;
}
/**
* 获取切面注解的描述-正确方式
*
* @param joinPoint 切点
* @return 描述信息
* @throws Exception
*/
public String getAspectLogDescription(JoinPoint joinPoint)
throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = null;
if (!(signature instanceof MethodSignature)) {
throw new IllegalArgumentException("该注解只能用于方法");
}
methodSignature = (MethodSignature) signature;
Method currentMethod = joinPoint.getTarget().getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
return currentMethod.getAnnotation(WebLog.class).description();
}
}
第4步,将自定义注解@WebLog加到方法上
@WebLog(description = "底库查询")
@PostMapping("/query")
public Result<List<Face>> query(@Validated @RequestBody AlbumQueryParam param, BindingResult bindingResult) throws BindException {
this.validate(bindingResult);
// 省略逻辑代码
return null;
}
第5步,看打印效果
[INFO ] 2021-01-03 12:54:17.877 [http-nio-8001-exec-1] 服务名称:cw-tool-engine-api [cn.demo.aspect.WebLogAspect:48] - ========================================== Start ==========================================
[INFO ] 2021-01-03 12:54:17.879 [http-nio-8001-exec-1] 服务名称:cw-tool-engine-api [cn.demo.aspect.WebLogAspect:50] - URL : http://localhost:8001/api/album/query
[INFO ] 2021-01-03 12:54:17.879 [http-nio-8001-exec-1] 服务名称:cw-tool-engine-api [cn.demo.aspect.WebLogAspect:52] - Description : 底库查询
[INFO ] 2021-01-03 12:54:17.880 [http-nio-8001-exec-1] 服务名称:cw-tool-engine-api [cn.demo.aspect.WebLogAspect:54] - HTTP Method : POST
[INFO ] 2021-01-03 12:54:17.881 [http-nio-8001-exec-1] 服务名称:cw-tool-engine-api [cn.demo.aspect.WebLogAspect:56] - Class Method : cn.demo.controller.AlbumController.query
[INFO ] 2021-01-03 12:54:17.881 [http-nio-8001-exec-1] 服务名称:cw-tool-engine-api [cn.demo.aspect.WebLogAspect:58] - IP : 0:0:0:0:0:0:0:1
[INFO ] 2021-01-03 12:54:17.882 [http-nio-8001-exec-1] 服务名称:cw-tool-engine-api [cn.demo.aspect.WebLogAspect:60] - Request Args : AlbumQueryParam(similarity=80.0, albumID=CCL01, topN=10, level=0, feature=7hL3ARQGEu818P797QoS//og9u/sAgX68+8PE/7x/uflEiP0JO/zDfj3+fb85hAJ/eUcCN8TBBcM+gcUCQH+8QIjDQUU8vn9APTn/gMTGBH1BPv45xH5HAT3BQniBO77BgL5AOIRCgDtCgTv/dwO+e8AEP4JA/H5Df398Rn+DgsNCwsB//sPAvby7gv48w8GFyjrEgYaAe328gXxBvbuCvb+BQMRCwkjFgH9/wsA/iD9ARb65AER3gsBD/oAAhXqBP/4EvoRIff78gMWA+v6/hcA6AMC9gP//g0H9/QH/yH0Fg778//78RQk/QkABfn9CgnzGAn5EQ389QUeFP4YCRH8CvT5BwoA4vXs7/4JFvYF++n7ARj8Bv/9D/f6IRIQ/vwEBhnzBfsP9AH9BwELEgP3CPD1//v59w4K/hj5+/f2C/HwCQzsCgLw9BDnBBL+BfkS+vUJBRDtCfL0/PYLD/4GEtsCD/H9/u78BPnz++31AQQJ/u3vBvP9AAz89+vpJlX/wa21hjLTz1eH+pYDn+f9T/HYOrgy98Vn7hURGrQXduMkw2SLJI5H3iCo+hEwaAUvFEPEL6zT1DI20pbbjw==, faceID=CCL0101)
[INFO ] 2021-01-03 12:54:17.902 [http-nio-8001-exec-1] 服务名称:cw-tool-engine-api [cn.demo.aspect.WebLogAspect:86] - Response Args : Result(code=200, message=success, result=[Face(deviceID=null, faceID=CCL0101, similarity=100.0, captureTime=null)], duration=5282)
[INFO ] 2021-01-03 12:54:17.903 [http-nio-8001-exec-1] 服务名称:cw-tool-engine-api [cn.demo.aspect.WebLogAspect:71] - =========================================== End ===========================================

1157

被折叠的 条评论
为什么被折叠?



