@ControllerAdvice @ExceptionHandler 全局处理 Controller 层异常
2018-03-26 13:02
337 查看
前言
通过@ControllerAdvice。我们可以将对于控制器的全局配置放置在同一个位置,注解了@ControllerAdvice的类的方法可以使用@ExceptionHandler,@InitBinder,@ModelAttribute注解到方法上,这对所有注解了@RequestMapping的控制器内的方法有效。@ExceptionHandler:用于全局处理控制器里面的异常。
@InitBinder:用来设置WebDataBinder,WebDataBinder用来自动绑定前台请求参数到Model中。
@ModelAttribute:@ModelAttribute本来的作用是绑定键值对到Model里,此处是让全局的@RequestMapping都能获得在此处设置的键值对。
对于与数据库相关的 Spring MVC 项目,我们通常会把 事务 配置在 Service层,当数据库操作失败时让 Service 层抛出运行时异常,Spring 事物管理器就会进行回滚。
如此一来,我们的 Controller 层就不得不进行 try-catch Service 层的异常,否则会返回一些不友好的错误信息到客户端。但是,Controller 层每个方法体都写一些模板化的 try-catch 的代码,很难看也难维护,特别是还需要对 Service 层的不同异常进行不同处理的时候。例如以下 Controller 方法代码(非常难看且冗余):
/** * 手动处理 Service 层异常和数据校验异常的示例 * @param dog * @param errors * @return */ @PostMapping(value = "") AppResponse add(@Validated(Add.class) @RequestBody Dog dog, Errors errors){ AppResponse resp = new AppResponse(); try { // 数据校验 BSUtil.controllerValidate(errors); // 执行业务 Dog newDog = dogService.save(dog); // 返回数据 resp.setData(newDog); }catch (BusinessException e){ LOGGER.error(e.getMessage(), e); resp.setFail(e.getMessage()); }catch (Exception e){ LOGGER.error(e.getMessage(), e); resp.setFail("操作失败!"); } return resp; }
本文讲解使用 @ControllerAdvice + @ExceptionHandler 进行全局的 Controller 层异常处理,只要设计得当,就再也不用在 Controller 层进行 try-catch 了!而且,@Validated 校验器注解的异常,也可以一起处理,无需手动判断绑定校验结果 BindingResult/Errors 了!
优缺点
优点:将 Controller 层的异常和数据校验的异常进行统一处理,减少模板代码,减少编码量,提升扩展性和可维护性。缺点:只能处理 Controller 层未捕获(往外抛)的异常,对于 Interceptor(拦截器)层的异常,Spring 框架层的异常,就无能为力了。
基本使用示例
@ControllerAdvice 注解定义全局异常处理类
@ControllerAdvice public class GlobalExceptionHandler { }
请确保此 GlobalExceptionHandler 类能被扫描到并装载进 Spring 容器中。
@ExceptionHandler 注解声明异常处理方法
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) @ResponseBody String handleException(){ return "Exception Deal!"; } }
方法 handleException() 就会处理所有 Controller 层抛出的 Exception 及其子类的异常,这是最基本的用法了。
被 @ExceptionHandler 注解的方法的参数列表里,还可以声明很多种类型的参数,其原型如下
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ExceptionHandler { /** * Exceptions handled by the annotated method. If empty, will default to any * exceptions listed i 4000 n the method argument list. */ Class<? extends Throwable>[] value() default {}; }
如果 @ExceptionHandler 注解中未声明要处理的异常类型,则默认为参数列表中的异常类型。所以上面的写法,还可以写成这样:
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler() @ResponseBody String handleException(Exception e){ return "Exception Deal! " + e.getMessage(); } }
参数对象就是 Controller 层抛出的异常对象!
常见的例子
/** * Created by kinginblue on 2017/4/10. * @ControllerAdvice + @ExceptionHandler 实现全局的 Controller 层的异常处理 */ @ControllerAdvice public class GlobalExceptionHandler { private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 处理所有不可知的异常 * @param e * @return */ @ExceptionHandler(Exception.class) @ResponseBody AppResponse handleException(Exception e){ LOGGER.error(e.getMessage(), e); AppResponse response = new AppResponse(); response.setFail("操作失败!"); return response; } /** * 处理所有业务异常 * @param e * @return */ @ExceptionHandler(BusinessException.class) @ResponseBody AppResponse handleBusinessException(BusinessException e){ LOGGER.error(e.getMessage(), e); AppResponse response = new AppResponse(); response.setFail(e.getMessage()); return response; } }
参考:https://blog.csdn.net/kinginblue/article/details/70186586
相关文章推荐
- @ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常
- 使用@ControllerAdvice及@ExceptionHandler(value = Exception.class)全局异常处理
- Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获
- Spring Boot @ControllerAdvice 处理全局异常,返回固定格式Json
- springMVC-异常的全局处理 @ControllerAdvice , @ExceptionHandler(Exception.class)
- Spring Boot @ControllerAdvice 处理全局异常,返回固定格式Json
- @ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常
- 《Springboot极简教程》系统异常全局统一处理:@ControllerAdvice plus @ExceptionHandler
- @ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常
- springmvc全局异常处理,自定义异常处理 只处理一类异常
- Spring MVC的Controller统一异常处理:HandlerExceptionResolver
- 使用@RestController,@ExceptionHandler和@Valid,把检验和异常处理从主要业务逻辑里面抽离出来
- SpringMVC 全局异常处理代码
- 异常处理 --- B/S下页面的全局异常处理并发送到信箱
- Spring MVC 全局异常处理-RESTAPI接口返回统一JSON格式-自定义异常处理--404异常捕捉
- Spring MVC 全局异常处理&文件上传
- SpringBoot学习——全局异常处理设置(返回JSON)
- @ControllerAdvice 拦截异常并统一处理(转载)
- struts-config.xml中配置全局异常处理:global-exceptions元素
- web网页全局异常处理