公司功能重做,有一些老的接口需要弃用,但是旧版本的APP调用就会报错,所以需要对这些接口处理,返回版本过低提示,于是乎写了一个注解,调用这个接口的都会返回版本过低。
写完之后闲来无事,想到最近系统压力过大,有些接口需要增加耗时计算,想写一个注解,自定义打印日志,说干就干。
定义注解名称
参考网上查的资源,进行注解的自定义,level用来判断都需要打印哪些日志
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface WebLog {
String value() default "";
Level[] level() default {};
enum Level{
URL,// 请求路径
METHOD,//请求方法
ARGS,//请求参数
RESPONSE,//返回数据
}
}
实现注解切面
有了注解名称,对注解切面进行实现,可以通过输入参数判断用户都需要打印哪些参数,特此记录,干完收工。
@Aspect
@Component
//@Profile({"dev","test"})
public class WebLogAspect {
private static final Logger log = Logger.getLogger(WebLogAspect.class);
@Pointcut("@annotation(com.cpit.icp.appserver.annotation.WebLog)")
public void webLog(){}
private String PREFIX = "";
private List<WebLog.Level> LEVEL = new ArrayList<>();
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Exception {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
WebLog aspectValue = getAspectValue(joinPoint);
PREFIX = aspectValue.value();
LEVEL = Arrays.asList(aspectValue.level());
if(LEVEL.contains(WebLog.Level.URL)){
log.info(PREFIX + " URL: "+request.getRequestURL().toString());
}
if(LEVEL.contains(WebLog.Level.METHOD)){
log.info(PREFIX + " METHOD: " + request.getMethod());
}
if(LEVEL.contains(WebLog.Level.ARGS)){
log.info("ARGS: " + new Gson().toJson(joinPoint.getArgs()));
}
}
@Around("webLog()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
// 打印出参
if(LEVEL.contains(WebLog.Level.RESPONSE)){
log.info(PREFIX + " RESPONSE :"+ new Gson().toJson(result));
}
// 执行耗时
log.info(PREFIX + " [耗时计算]: " + (System.currentTimeMillis() - startTime) + " ms");
return result;
}
public WebLog getAspectValue(JoinPoint joinPoint)
throws Exception {
Class<?> targetCls=joinPoint.getTarget().getClass();
Signature signature=joinPoint.getSignature();
MethodSignature ms= (MethodSignature)signature;
Method targetMethod=targetCls.getDeclaredMethod(ms.getName(),ms.getParameterTypes());
return targetMethod.getAnnotation(WebLog.class);
}
}
附使用方法:
@WebLog(value = "获取所有充电站",level = {WebLog.Level.URL, WebLog.Level.METHOD, WebLog.Level.RESPONSE})
另一种实现
来更新一波,通过实验,还有一种方法,不进行切点的定义,直接在Before上使用注解,这样免去上面用各种反射取得注解中参数的麻烦
@Aspect
@Component
//@Profile({"dev","test"})
public class WebLogAspect {
private static final Logger log = Logger.getLogger(WebLogAspect.class);
@Before("@annotation(webLog)")
public void doBefore(JoinPoint joinPoint,WebLog webLog) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
String PREFIX = webLog.value();
List<WebLog.Level> LEVEL = Arrays.asList(webLog.level());
if(LEVEL.contains(WebLog.Level.URL)){
log.info(PREFIX + " URL: "+request.getRequestURL().toString());
}
if(LEVEL.contains(WebLog.Level.METHOD)){
log.info(PREFIX + " METHOD: " + request.getMethod());
}
if(LEVEL.contains(WebLog.Level.ARGS)){
log.info("ARGS: " + new Gson().toJson(joinPoint.getArgs()));
}
}
@Around("@annotation(webLog)")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint,WebLog webLog) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
String PREFIX = webLog.value();
List<WebLog.Level> LEVEL = Arrays.asList(webLog.level());
// 打印出参
if(LEVEL.contains(WebLog.Level.RESPONSE)){
log.info(PREFIX + " RESPONSE :"+ new Gson().toJson(result));
}
// 执行耗时
log.info(PREFIX + " [耗时计算]: " + (System.currentTimeMillis() - startTime) + " ms");
return result;
}
}
区别在于将注解对象放在入参中,直接取用即可。