目前接触的这个项目中,需要在自己每个方法的前后打印日志,感觉这些都是通用的东西可以抽取出来。后来参照了公司的另外一个项目,结合这段时间对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()可以指定异常类。由该注解注释的方法可以具有灵活的输入参数。