该专栏配套的开源项目easy-admin已开源:https://gitee.com/lakernote/easy-admin
背景
系统上线之后,需要记录哪些用户,哪些IP,终端是什么,请求体,响应体,耗时等进行记录,可以用于安全防控,用户行为分析,系统优化等。
实现
1.自定义注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Metrics {
}
可自行扩展属性,例如加模块名称
2.自定义AOP拦截器
自定义AOP拦截器拦截在方法和类上注解了@Metrics
的实例,进行切面操作。
@Aspect
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MetricsAspect {
@Pointcut("@annotation(Metrics) || @within(Metrics)")
public void withAnnotationMetrics() {
}
@Around("withAnnotationMetrics()")
public Object metrics(ProceedingJoinPoint pjp) throws Throwable {
MethodSignature signature = (MethodSignature) pjp.getSignature();
String name = signature.toShortString();
Object returnValue;
Instant start = Instant.now();
ExtLog logBean = new ExtLog();
logBean.setIp(HttpServletRequestUtil.getRemoteAddress());
logBean.setUri(HttpServletRequestUtil.getRequestURI());
logBean.setUserId(StpUtil.isLogin() ? StpUtil.getLoginIdAsLong() : null);
logBean.setClient(HttpServletRequestUtil.getRequestUserAgent());
logBean.setRequest(objectMapper.writeValueAsString(pjp.getArgs()));
logBean.setMethod(name);
logBean.setStatus(true);
try {
returnValue = pjp.proceed();
} catch (Exception ex) {
logBean.setCost((int) Duration.between(start, Instant.now()).toMillis());
logBean.setCreateTime(LocalDateTime.now());
logBean.setStatus(false);
extLogService.save(logBean);
log.error(name, ex);
throw ex;
}
String response = objectMapper.writeValueAsString(returnValue);
logBean.setCost((int) Duration.between(start, Instant.now()).toMillis());
logBean.setCreateTime(LocalDateTime.now());
if (StrUtil.isNotBlank(response) && response.length() <= 500) {
logBean.setResponse(response);
}
extLogService.save(logBean);
return returnValue;
}
}
该专栏配套的开源项目easy-admin已开源:https://gitee.com/lakernote/easy-admin