SpringMVC全局异常处理

SpringMVC全局异常处理

SpringMVC全局异常处理方式一般分为两大种:

  1. 使用 HandlerExceptionResolver 接口
  2. @ExceptionHandler
  3. @ResponseStatus

一、使用 HandlerExceptionResolver 接口

HandlerExceptionResolver 是org.springframework.web.servlet下的一个接口,可以解析在处理程序映射或执行期间抛出的异常,通常情况下会返回一个error views ,error views类似于JSP错误页面,但可以与任何类型的异常一起使用。


使用这个接口只需要实现resolveException方法(以下是API文档简单翻译了一下): 这是API文档

具体示例(方法内可根据自己需求编写代码):

public class HandlerExceptionResolverDemo implements HandlerExceptionResolver {
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        if(e instanceof IOException){
            return new ModelAndView("ioexp");
        }else if(e instanceof SQLException){
            return new ModelAndView("sqlexp");
        }
        return null;
    }

也可以直接使用官方的实现类SimpleMappingExceptionResolver,当然无论是自己实现还是直接调用官方的都必须在spring的配置文件内配置(或者加注解)目的是为了能让spring管理:

<!-- 自己编写的简单异常处理器 -->
<bean class="com.expection.demo.HandlerExceptionResolverDemo "/>

<!--or下面的,自定义和官方提供的不冲突可同时使用-->

<!-- springmvc提供的简单异常处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
     <!-- 定义默认的异常处理页面 -->
    <property name="defaultErrorView" value="/WEB-INF/jsp/error.jsp"/>
    <!-- 定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为exception --> 
    <property name="exceptionAttribute" value="ex"/>
    <!-- 定义需要特殊处理的异常,这是重要点 --> 
    <property name="exceptionMappings">
        <props>
            <prop key="com.exception.demo.SuperExceptionResolver">/WEB-INF/jsp/custom_error.jsp</prop>
        </props>
        <!-- 还可以定义其他的自定义异常 -->
    </property>
</bean>

从配置文件可以看出可以配置特殊处理的异常,也就是说可以自定义特殊异常类。


接下来可以自定义一些出异常的方法来测试一下
测试

启动tomcat输入路径后就会发现页面跳转到了error.jsp。

从上面的过程可知,使用SimpleMappingExceptionResolver进行异常处理,具有集成简单、有良好的扩展性(可以任意增加自定义的异常和异常显示页面)、对已有代码没有入侵性等优点,但该方法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的情况不适用。


二、@ExceptionHandler
API源码:

@Target(value=METHOD)
 @Retention(value=RUNTIME)
 @Documented
public @interface ExceptionHandler{
	java.lang.Class<? extends java.lang.Throwable>[]	
}

详解请见API文档(英文的)简单翻译一下(英语大神建议英文API):

用于处理特定处理程序类和/或处理程序方法中的异常的注释。在Servlet和Portlet环境之间提供一致的样式,语义适应具体环境。

使用此注释注释的处理程序方法允许具有非常灵活的签名。它们可以按任意顺序具有以下类型的参数:

  • 异常参数:声明为一般异常或更具体的异常。如果注释本身不通过它缩小异常类型,这也可以作为映射提示value()。
    请求和/或响应对象。您可以选择任何特定的请求/响应类型,例如 ServletRequest/ HttpServletRequest 或PortletRequest/ ActionRequest/ RenderRequest。
  • 会话对象: HttpSession或者PortletSession。此类型的参数将强制存在相应的会话。因此,这样的论证永远不会null。 请注意,会话访问可能不是线程安全的,特别是在Servlet环境中:"synchronizeOnSession"如果允许多个请求同时访问会话,请考虑将标志切换 为“true”。
  • WebRequest或 NativeWebRequest。允许通用请求参数访问以及请求/会话属性访问,而不与本机Servlet / Portlet API绑定。
  • Locale对于当前请求区域设置
  • InputStream/ Reader用于访问请求的内容。
  • OutputStream/ Writer用于生成响应的内容。
  • Model作为从处理程序方法返回模型映射的替代方法。

处理程序方法支持以下返回类型:

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

翻译的惨不忍睹,强烈建议看API文档
用法:在方法上加 @ExceptionHandler(value={}) ,value可以写一个或多个异常类码,如 @ExceptionHandler(value={IOException.class,SQLException.class}) ,若不写则默认所有异常。
示例:


@RequestMapping("/errorTest")
public class ErrorController {

    @RequestMapping("/demo")
    @ExceptionHandler(value={IOException.class,SQLException.class})
    public void demo() {
        //-------------方法内容-----------------
    }

}

注意:

如果单使用@ExceptionHandler,只能在当前Controller中处理异常,因此往往都会配合@ControllerAdvice使用,就可以摆脱那个限制了。这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。 也就是说,@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。

当然无论单独使用@ExceptionHandler还是使用@controlleradvice + @ ExceptionHandler 配合都必须确保处理类能被sping捕获到

优缺点:

  • 优点:将 Controller 层的异常和数据校验的异常进行统一处理,减少模板代码,减少编码量,提升扩展性和可维护性。
  • 缺点:只能处理 Controller 层未捕获(往外抛)的异常,对于 Interceptor(拦截器)层的异常,Spring 框架层的异常,就无能为力了。

三、好像还有第三种@ResponseStatus???
@ResponseStatus(value= ,reason=" ")
它有两个属性,value属性是http状态码,比如404,500等。reason是错误信息

示例:

//页面出现404后就会有一个友好的提示了
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "页面走丢了")
public class demoExceptionResolver extends RuntimeException {
	//HttpStatus.NOT_FOUN-->404
    //---------------------------------
}

来在API的警告:
警告:在异常类上使用此批注时,或者在设置reason此批注的属性时,HttpServletResponse.sendError将使用该方法。

因此HttpServletResponse.sendError,响应被认为是完整的,不应再写入。此外,Servlet容器通常会编写HTML错误页面,因此使用reason不适合的REST API。对于这种情况,最好使用a ResponseEntity作为返回类型并避免@ResponseStatus完全使用。

写的有点错略,有机会分别解释一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值