问题:
- 想要打印每次请求的入参,返回值,响应时间,异常日志,如果给每个方法挨个添加打印日志非常麻烦
解决方案:
- 使用切面的方式将所有的Controller每个方法加入切入点
- 使用环绕通知的方式可以在切入点执行前后执行切面,符合我们的需求在方法执行前后打印相关日志
- 忽略@LogIgnore注解的方法
Controller层日志切面
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* Controller层日志切面
*/
@Aspect
@Component
@Slf4j
public class ControllerLogAspect {
/**
* 切入点: 所有Controller类的public方法,忽略@LogIgnore注解的方法
*/
@Pointcut("execution(public * com.applets.manager.api..*Controller.*(..))&&!@annotation(com.applets.manager.api.aspect.LogIgnore)")
public void controllerLogPointcut() {
}
@Around("controllerLogPointcut()")
public Object aroundMethod(ProceedingJoinPoint point) throws Throwable {
long time = System.currentTimeMillis();
Signature signature = point.getSignature();
try {
log.info(">>> Begin execute {}, args: {}", signature, point.getArgs());
Object object = point.proceed();
log.info("<<< End execute {} in {} ms, return: {}", signature, System.currentTimeMillis() - time, JSON.toJSONString(object));
return object;
} catch (Throwable e) {
log.warn(">>> Execute {} has occurred exception: ", signature, e);
throw e;
}
}
}
忽略日志切面
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 忽略日志切面
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface LogIgnore {
}