Spring异常处理@ExceptionHandler

最近学习Spring时,认识到Spring异常处理的强大。之前处理工程异常,代码中最常见的就是try-catch-finally,有时一个try,多个catch,覆盖了核心业务逻辑:

1 try{
2     ..........
3 }catch(Exception1 e){
4     ..........
5 }catch(Exception2 e){
6     ...........
7 }catch(Exception3 e){
8     ...........
9 }

Spring能够较好的处理这种问题,核心如下,文章主要关注前两个:

  • @ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度
  • @ControllerAdvice:异常集中处理,更好的使业务逻辑与异常处理剥离开
  • @ResponseStatus:可以将某种异常映射为HTTP状态码

@ExceptionHandler

源码如下:

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

该注解作用对象为方法,并且在运行时有效,value()可以指定异常类。由该注解注释的方法可以具有灵活的输入参数(详细参见Spring API):

  • 异常参数:包括一般的异常或特定的异常(即自定义异常),如果注解没有指定异常类,会默认进行映射。
  • 请求或响应对象 (Servlet API or Portlet API): 你可以选择不同的类型,如ServletRequest/HttpServletRequest或PortleRequest/ActionRequest/RenderRequest
  • Session对象(Servlet API or Portlet API): HttpSession或PortletSession。
  • WebRequest或NativeWebRequest
  • Locale
  • InputStream/Reader
  • OutputStream/Writer
  • Model

方法返回值可以为:

  • ModelAndView对象
  • Model对象
  • Map对象
  • View对象
  • String对象
  • 还有@ResponseBody、HttpEntity<?>或ResponseEntity<?>,以及void

@ControllerAdvice

源码如下:

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

该注解作用对象为TYPE,包括类、接口和枚举等,在运行时有效,并且可以通过Spring扫描为bean组件。其可以包含由@ExceptionHandler、@InitBinder 和@ModelAttribute标注的方法,可以处理多个Controller类,这样所有控制器的异常可以在一个地方进行处理。

实例

异常类:

 1 public class CustomGenericException extends RuntimeException{
 2     private static final long serialVersionUID = 1L;
 3
 4     private String errCode;
 5     private String errMsg;
 6
 7     public String getErrCode() {
 8         return errCode;
 9     }
10
11     public void setErrCode(String errCode) {
12         this.errCode = errCode;
13     }
14
15     public String getErrMsg() {
16         return errMsg;
17     }
18
19     public void setErrMsg(String errMsg) {
20         this.errMsg = errMsg;
21     }
22
23     public CustomGenericException(String errCode, String errMsg) {
24         this.errCode = errCode;
25         this.errMsg = errMsg;
26     }
27 }

控制器:

 1 @Controller
 2 @RequestMapping("/exception")
 3 public class ExceptionController {
 4
 5     @RequestMapping(value = "/{type}", method = RequestMethod.GET)
 6     public ModelAndView getPages(@PathVariable(value = "type") String type) throws Exception{
 7         if ("error".equals(type)) {
 8             // 由handleCustomException处理
 9             throw new CustomGenericException("E888", "This is custom message");
10         } else if ("io-error".equals(type)) {
11             // 由handleAllException处理
12             throw new IOException();
13         } else {
14             return new ModelAndView("index").addObject("msg", type);
15         }
16     }
17 }

异常处理类:

 1 @ControllerAdvice
 2 public class ExceptionsHandler {
 3
 4     @ExceptionHandler(CustomGenericException.class)//可以直接写@ExceptionHandler,不指明异常类,会自动映射
 5     public ModelAndView customGenericExceptionHnadler(CustomGenericException exception){ //还可以声明接收其他任意参数
 6         ModelAndView modelAndView = new ModelAndView("generic_error");
 7         modelAndView.addObject("errCode",exception.getErrCode());
 8         modelAndView.addObject("errMsg",exception.getErrMsg());
 9         return modelAndView;
10     }
11
12     @ExceptionHandler(Exception.class)//可以直接写@EceptionHandler,IOExeption继承于Exception
13     public ModelAndView allExceptionHandler(Exception exception){
14         ModelAndView modelAndView = new ModelAndView("generic_error");
15         modelAndView.addObject("errMsg", "this is Exception.class");
16         return modelAndView;
17     }
18 }

JSP页面:

正常页面index.jsp:

 1 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 2 <html>
 3 <body>
 4 <h2>Spring MVC @ExceptionHandler Example</h2>
 5
 6 <c:if test="${not empty msg}">
 7     <h2>${msg}</h2>
 8 </c:if>
 9
10 </body>
11 </html>

异常处理页面generic_error.jsp

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>

<c:if test="${not empty errCode}">
    <h1>${errCode} : System Errors</h1>
</c:if>

<c:if test="${empty errCode}">
    <h1>System Errors</h1>
</c:if>

<c:if test="${not empty errMsg}">
    <h2>${errMsg}</h2>
</c:if>

</body>
</html>

测试运行如下:

正常情况:

CustomGenericException异常情况:

IOException异常情况:

总结

  • @ExceptionHandler和@ControllerAdvice能够集中异常,使异常处理与业务逻辑分离
  • 本文重点理解两种注解方式的使用

参考:

时间: 2024-10-12 12:14:21

Spring异常处理@ExceptionHandler的相关文章

Unit06: Spring对JDBC的 整合支持 、 Spring+JDBC Template、Spring异常处理

Unit06: Spring对JDBC的 整合支持 . Spring+JDBC Template .Spring异常处理 1. springmvc提供的异常处理机制 我们可以将异常抛给spring框架,让spring来帮我们处理异常. (1)使用简单异常处理器 step1. 配置简单异常处理器. step2. 添加对应的异常处理页面. 注:该方式只适合处理简单异常的处理,如果要对异常做复杂处理,比如 记录日志等,则不合适了. (2)使用@ExceptionHandler注解 step1. 在处理

spring异常处理

http://cgs1999.iteye.com/blog/1547197 1 描述 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的.不可预知的异常需要处理.每个过程都单独处理异常,系统的代码耦合度高,工作量大且不好统一,维护的工作量也很大. 那么,能不能将所有类型的异常处理从各处理过程解耦出来,这样既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护?答案是肯定的.下面将介绍使用Spring MVC统

深入理解Spring异常处理

1.前言2.相信我们每个人在SpringMVC开发中,都遇到这样的问题:当我们的代码正常运行时,返回的数据是我们预期格式,比如json或xml形式,但是一旦出现了异常(比如:NPE或者数组越界等等),返回的内容确实服务端的异常堆栈信息,从而导致返回的数据不能使客户端正常解析: 很显然,这些并不是我们希望的结果.我们知道,一个较为常见的系统,会涉及控制层,服务(业务)层.缓存层.存储层以及接口调用等,其中每一个环节都不可避免的会遇到各种不可预知的异常需要处理.如果每个步骤都单独try..catch

Spring的@ExceptionHandler和@ControllerAdvice统一处理异常

之前敲代码的时候,避免不了各种try..catch, 如果业务复杂一点, 就会发现全都是try…catch try{ ..........}catch(Exception1 e){ ..........}catch(Exception2 e){ ...........}catch(Exception3 e){ ...........} 这样其实代码既不简洁好看 ,我们敲着也烦, 一般我们可能想到用拦截器去处理, 但是既然现在Spring这么火,AOP大家也不陌生, 那么Spring一定为我们想好

Spring 注解 @ExceptionHandler

Spring 注解学习手札(一) 构建简略Web使用 Spring 注解学习手札(二) 操控层整理 Spring 注解学习手札(三) 表单页面处置 Spring 注解学习手札(四) 持久层分析 Spring 注解学习手札(五) 事务层事务处置 Spring 注解学习手札(六) 测验 Spring 注解学习手札(七) 补遗--@ResponseBody,@RequestBody,@PathVariable Spring 注解学习手札(八) 补遗--@ExceptionHandler 直接上代码:

spring 新版本 ExceptionHandler 了解

Spring注解ExceptionHandler ,今天看新公司的项目发现的这个注解(以前公司用的版本低啊很多新特性都没有遇到过),用@RequestBody,@ResponseBody,可解决json绑定.但是每次遇到RuntimeException,需要给出一个默认返回JSON这一点比较繁琐. SimpleMappingExceptionResolver这个拦截器也可以实现,不过貌似是一般的用法. 用了ExceptionHandler注解,可以轻松解决这个问题 很简单,代码不再贴了

Spring MVC 异常处理 - ExceptionHandler

通过HandlerExceptionResolver 处理程序异常,包括Handler映射, 数据绑定, 以及目标方法执行时的发生的异常 实现类如下 /** * 1. 在 @ExceptionHandler 方法的入参中可以加入 Exception 类型的参数, 该参数即对应发生的异常对象 * 2. @ExceptionHandler 方法的入参中不能传入 Map. 若希望把异常信息传导页面上, 需要使用 ModelAndView 作为返回值 * 3. @ExceptionHandler 方法标

统一异常处理@ExceptionHandler

异常处理功能中用到的注解是:@ExceptionHandler(异常类型.class). 这个注解的功能是:自动捕获controller层出现的指定类型异常,并对该异常进行相应的异常处理. 比如我要在controller层中处理InsertMessageException类型异常,我就可以在controller层的类中定义以下方法: @ExceptionHandler(InsertMessageException.class) public ModelAndView HandlerInsertM

Spring --- 异常处理机制

1.定义全局异常处理器,为全局的异常,如出现将调用 error.JSP <!-- 定义异常处理器 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- 如果Controller抛出Except