手撕SpringMVC异常

1.异常处理简介
SpringMVC通过HandlerExceptionResolver处理程序的异常,包括Handler映射、数据绑定以及处理器方法执行时发生的异常。
HandlerExceptionResolver(接口) 源码注释:
* Interface to be implemented by objects that can resolve exceptions thrown during
* handler mapping or execution, in the typical case to error views. Implementors are
* typically registered as beans in the application context.
SpringMVC提供的HandlerExceptionResolver的实现类
②DispatcherServlet默认装配,以及开发常用装配
没有使用<mvc:annotation-drivern/>配置,则装配了以下三种异常解析器:
AnnotationMehtodHandlerExceptionResolver (源码中显示已经过时)
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
使用了<mvc:annotation-drivern/>配置:
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
2.ExceptionHandlerExceptionResolver
Talk is cheap! show me your code!
主要处理 Handler 中用 @ExceptionHandler 注解定义的方法。
	//这个也是能够处理运行时发生的异常,但是和ArithmeticException相比较,没有ArithmeticException近
	@ExceptionHandler(Exception.class)
    public String getEx(){
        return "error";
    }    

	//处理任何符合ArithmeticException的异常,一旦运行过程中又出现该类型异常,便会转到此处执行
	@ExceptionHandler(ArithmeticException.class)
    public String getEx(){
        return "error";
    }
    
    @RequestMapping(value = "exceptionTest")
    public String exceptionTest(){
        int i = 10/0;
        //如果代码正常执行,那么就会返回a.jsp  ,但是还是出现了异常
        return "a"; 
    }
@ExceptionHandler注解定义的方法优先级问题:例如发生的是ArithmeticException,但是声明的异常有 RuntimeException 和 Exception,
此候会根据异常的最近 继承关系找到继承深度最浅的那个@ExceptionHandler 注解方法,即标记了 RuntimeException 的方法 
此时还有一种情况,如果用户自定义了一个类,并使用@ControllerrAdvice注解,同时其内部定义了许多@ExceptionHandler注解方法,如下:
@ControllerAdvice
public class MyHandlerException {
    @ExceptionHandler(ArithmeticException.class)
    public String testEx(){
        return "error";
    }
}
此时规则如下:ExceptionHandlerMethodResolver 内部若找不到@ExceptionHandler 注解的话,会找 @ControllerAdvice 中的@ExceptionHandler 注解方法

3.ResponseStatusExceptionResolver
直接上代码理解:
①自定义一个异常,并采用@ResponseStatus注解修饰异常类
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public class MyException extends RuntimeException {

    static final long serialVersionUID = -7034897190745766939L;

    public MyException() {
    }

    public MyException(String message) {
        super(message);
    }
    public MyException(String message, Throwable cause) {
        super(message, cause);
    }
    public MyException(Throwable cause) {
        super(cause);
    }
    public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

////////////// 测试代码
    @RequestMapping(value = "exceptionTest")
    public String exceptionTest(){
        try {
            int i = 10/0;
        } catch (Exception e) {
            throw new MyException();
        }
        return "a";
    }
若在处理器方法中抛出了上述异常:
若ExceptionHandlerExceptionResolver 不解析述异常。由于触发的异常 UnauthorizedException 带有@ResponseStatus 注解。因此会被ResponseStatusExceptionResolver 解析到。最后响应HttpStatus.UNAUTHORIZED 代码给客户端。HttpStatus.UNAUTHORIZED 代表响应码401,无权限。 关于其他的响应码请参考 HttpStatus 枚举类型源码
实际出现异常然后如下图:
4.DefaultHandlerExceptionResolver
对一些特殊的异常进行处理,比如NoSuchRequestHandlingMethodException、HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException 等

5.SimpleMappingExceptionResolver(这个异常处理器没有自动注册,需要手动配置)
如果希望对所有异常进行统一处理,可以使用 SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常
    <bean id="simpleMappingExceptionResolver"
          class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.ArithmeticException">error</prop>
            </props>
        </property>
    </bean>
当发生ArithmeticException时就可以转到error页面,当然这个配置是properties类型,因此可以配置多个各种类型的异常以及异常对应的界面。
注意:当代码中也配置了异常处理方法,无论远近只要能处理,那么代码处理异常优先级高于配置文件,直接使用代码中的方式处理




posted @ 2020-12-09 19:26  大洋游侠1  阅读(60)  评论(0编辑  收藏  举报