Spring AOP 记录日志和全局异常处理

薛定谔的汪

目前接触的这个项目中,需要在自己每个方法的前后打印日志,感觉这些都是通用的东西可以抽取出来。后来参照了公司的另外一个项目,结合这段时间对Spring的学习,整理出可以通用的日志和异常处理类,以供参考。

记录日志:

注解LoggerManage:

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoggerManage {
//描述
public String description();
}

日志的管理类LoggerAdvice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Service;
@Aspect
@Service
public class LoggerAdvice {

private Logger logger = Logger.getLogger(this.getClass());

@Before("within(com.yakai.aop..*) && @annotation(loggerManage)")
public void addBeforeLogger(JoinPoint joinPoint, LoggerManage loggerManage) {
logger.info("执行 " + loggerManage.description() + " 开始");
logger.info(joinPoint.getSignature().toString());
logger.info(parseParames(joinPoint.getArgs()));
}

@AfterReturning("within(com.yakai.aop..*) && @annotation(loggerManage)")
public void addAfterReturningLogger(JoinPoint joinPoint, LoggerManage loggerManage) {
logger.info("执行 " + loggerManage.description() + " 结束");
}

@AfterThrowing(pointcut = "within(com.yakai.aop..*) && @annotation(loggerManage)", throwing = "ex")
public void addAfterThrowingLogger(JoinPoint joinPoint, LoggerManage loggerManage, Exception ex) {
logger.error("执行 " + loggerManage.description() + " 异常", ex);
}

private String parseParames(Object[] parames) {
if (null == parames || parames.length <= 0) {
return "";
}
StringBuffer param = new StringBuffer("传入参数[{}] ");
for (Object obj : parames) {
param.append(ToStringBuilder.reflectionToString(obj)).append(" ");
}
return param.toString();
}

}

使用:

只需要在方法上加上注解即可

1
2
@LoggerManage(description="更新用户信息")
public void updateUse(User user){...}

SpringMVC定义全局异常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.apache.log4j.Logger;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;


@ControllerAdvice
public class GlobalExceptionHandler {

protected Logger logger = Logger.getLogger(this.getClass());
@ExceptionHandler(value = Exception.class)
public ModelAndView defaultErrorHandler(Exception e, HttpServletRequest request) throws Exception {
logger.info("请求地址:" + request.getRequestURL());
ModelAndView mv = new ModelAndView();
logger.error("异常信息:",e);
mv.setViewName("error");
return mv;
}
}

@ControllerAdvice注解:

其源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
@AliasFor("basePackages")
String[] value() default {};

@AliasFor("value")
String[] basePackages() default {};

Class<?>[] basePackageClasses() default {};

Class<?>[] assignableTypes() default {};

Class<? extends Annotation>[] annotations() default {};
}

@controllerAdvice最为实用的一个场景就是将所有@ExceptionHandler方法收集到一个类中,这样所有的异常都能在一个地方进行一致处理。

@ControllerAdvice默认所有控制的抛出的异常都会在这个类进行处理 ,异常集中处理,更好的使业务逻辑与异常处理剥离开

@ControllerAdvice(annotations = {PCInfoController .class}) 配置你需要拦截的控制器,

@ControllerAdvice(basePackages = “com.demo”) 配置你需要路径下的控制器

@ExceptionHandler注解:

其源码:

1
2
3
4
5
6
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
Class<? extends Throwable>[] value() default {};
}

@ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度,该注解作用对象为方法,并且在运行时有效,value()可以指定异常类。由该注解注释的方法可以具有灵活的输入参数。

  • Title: Spring AOP 记录日志和全局异常处理
  • Author: 薛定谔的汪
  • Created at : 2017-10-24 17:45:20
  • Updated at : 2023-11-17 19:37:37
  • Link: https://www.zhengyk.cn/2017/10/24/spring/AopLog-Exeption/
  • License: This work is licensed under CC BY-NC-SA 4.0.