相信大家在开发的时候面对controller层有打印日志的习惯,controller层无需过多代码,基本上包括入参日志打印,调用service层方法,打印返回值结果,便于后期定位问题,再有就是对controller进行try catch处理,而我作为一名很懒的开发者,基本上就是看着别人的代码复制粘贴一遍,入参和返回值的日志打印,往往复制的时候把别人的方法名,类名都复制,简直是无脑复制,在后期定位问题的时候也给自己挖坑,最主要的是为了减少冗余代码,实现健壮性代码的基本要求,这次来个大保健,哦,不对, 是来个小重构,使用aop+注解。
对于需要引入什么aop pom文件这里就不多废话,自行google,自定义一个注解,用于标注在controller方法上.
@Aspect
@Component
@Slf4j
@Profile({"dev", "test"})
public class WebLogAspect {
然后就是一个切面
/**
* 换行符
*/
private static final String LINE_SEPARATOR = System.lineSeparator();
/**
* 以自定义 @WebLog 注解为切点
*/
@Pointcut("@annotation(com.demo.anno.WebLog)")
public void test() {
}
/**
* 在切点之前织入
*
* @param joinPoint
* @throws Throwable
*/
@Before("test() && @annotation(webLog)")
public void doBefore(JoinPoint joinPoint, WebLog webLog) throws Throwable {
// 开始打印请求日志
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 获取 @WebLog 注解的描述信息
String methodDescription = getAspectLogDescription(joinPoint);
// 打印请求相关参数
log.info("==================================【{}】【{}】Start =================================", joinPoint.getTarget().getClass().getSimpleName(), joinPoint.getSignature().getName());
// 打印描述信息
log.info("Description : {}", methodDescription);
// 打印请求入参
log.info("【Request Args】 : {}", new repack.com.google.gson.Gson().toJson(joinPoint.getArgs()));
}
/**
* 在切点之后织入
*
* @throws Throwable
*/
@After("test()")
public void doAfter(JoinPoint joinPoint) throws Throwable {
// 接口结束后换行,方便分割查看
log.info("==================================【{}】【{}】 End =================================" + LINE_SEPARATOR, joinPoint.getTarget().getClass().getSimpleName(), joinPoint.getSignature().getName());
}
/**
* 环绕
*
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("test()")
public Result<Object> doAround(ProceedingJoinPoint proceedingJoinPoint) {
long startTime = System.currentTimeMillis();
Result result = null;
try {
result = (Result<Object>) proceedingJoinPoint.proceed();
log.info("【Response Args】 : {}", new Gson().toJson(result));
return result;
} catch (BizException e) {
result = new Result<>(ResultConstant.FAIL_CODE, ResultConstant.FAIL, e.getMessage());
log.info("The method 【{}】 occurs exception: {}", proceedingJoinPoint.getSignature().getName(), e);
} catch (Throwable throwable) {
result = new Result<>(ResultConstant.FAIL_CODE, ResultConstant.FAIL, throwable.getMessage());
log.info("The method 【{}】 occurs exception: {}", proceedingJoinPoint.getSignature().getName(), throwable);
}
// 打印出参
log.info("【Response Args】 : {}", new Gson().toJson(result));
// 执行耗时
log.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
return result;
}
/**
* 获取切面注解的描述
*
* @param joinPoint 切点
* @return 描述信息
* @throws Exception
*/
public String getAspectLogDescription(JoinPoint joinPoint)
throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
StringBuilder description = new StringBuilder("");
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description.append(method.getAnnotation(WebLog.class).desc());
break;
}
}
}
return description.toString();
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface WebLog {
String desc() default "";
}
然后再开始写一个切面
@Aspect
@Component
@Slf4j
@Profile({"dev", "test"})
public class WebLogAspect {
/**
* 换行符
*/
private static final String LINE_SEPARATOR = System.lineSeparator();
/**
* 以自定义 @WebLog 注解为切点
*/
@Pointcut("@annotation(com.demo.anno.WebLog)")
public void test() {
}
/**
* 在切点之前织入
*
* @param joinPoint
* @throws Throwable
*/
@Before("test() && @annotation(webLog)")
public void doBefore(JoinPoint joinPoint, WebLog webLog) throws Throwable {
// 开始打印请求日志
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 获取 @WebLog 注解的描述信息
String methodDescription = getAspectLogDescription(joinPoint);
// 打印请求相关参数
log.info("==================================【{}】【{}】Start =================================", joinPoint.getTarget().getClass().getSimpleName(), joinPoint.getSignature().getName());
// 打印描述信息
log.info("Description : {}", methodDescription);
// 打印请求入参
log.info("【Request Args】 : {}", new repack.com.google.gson.Gson().toJson(joinPoint.getArgs()));
}
/**
* 在切点之后织入
*
* @throws Throwable
*/
@After("test()")
public void doAfter(JoinPoint joinPoint) throws Throwable {
// 接口结束后换行,方便分割查看
log.info("==================================【{}】【{}】 End =================================" + LINE_SEPARATOR, joinPoint.getTarget().getClass().getSimpleName(), joinPoint.getSignature().getName());
}
/**
* 环绕
*
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("test()")
public Result<Object> doAround(ProceedingJoinPoint proceedingJoinPoint) {
long startTime = System.currentTimeMillis();
Result result = null;
try {
result = (Result<Object>) proceedingJoinPoint.proceed();
log.info("【Response Args】 : {}", new Gson().toJson(result));
return result;
} catch (BizException e) {
result = new Result<>(ResultConstant.FAIL_CODE, ResultConstant.FAIL, e.getMessage());
log.info("The method 【{}】 occurs exception: {}", proceedingJoinPoint.getSignature().getName(), e);
} catch (Throwable throwable) {
result = new Result<>(ResultConstant.FAIL_CODE, ResultConstant.FAIL, throwable.getMessage());
log.info("The method 【{}】 occurs exception: {}", proceedingJoinPoint.getSignature().getName(), throwable);
}
// 打印出参
log.info("【Response Args】 : {}", new Gson().toJson(result));
// 执行耗时
log.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
return result;
}
/**
* 获取切面注解的描述
*
* @param joinPoint 切点
* @return 描述信息
* @throws Exception
*/
public String getAspectLogDescription(JoinPoint joinPoint)
throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
StringBuilder description = new StringBuilder("");
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description.append(method.getAnnotation(WebLog.class).desc());
break;
}
}
}
return description.toString();
}
当然它山之石可以攻玉,感谢大神的文章借鉴,来源: