简介

• Spring MVC 通过 HandlerExceptionResolver 处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常。

• SpringMVC 提供的 HandlerExceptionResolver 的实现类

SpringMVC 异常处理_其他

HandlerExceptionResolver

• DispatcherServlet 默认装配的 HandlerExceptionResolver :

– 没有使用 配置:

SpringMVC 异常处理_其他_02

– 使用了<mvc:annotation-driven/> 配置:

SpringMVC 异常处理_html_03

ExceptionHandlerExceptionResolver

• 主要处理 Handler 中用 @ExceptionHandler 注解定义的 方法。

• @ExceptionHandler 注解定义的方法优先级问题:例如发 生的是NullPointerException,但是声明的异常有 RuntimeException 和 Exception,此候会根据异常的最近 继承关系找到继承深度最浅的那个 @ExceptionHandler 注解方法,即标记了 RuntimeException 的方法

• ExceptionHandlerMethodResolver 内部若找不 到@ExceptionHandler 注解的话,会找 @ControllerAdvice 中的@ExceptionHandler 注解方法

注意事项:

1、在@ExceptionHandler方法的入参中可以加入Exception类型的参数,该参数即对应发生的异常对象。

2、@ExceptionHandler 方法的入参中不能传入Map,若希望把异常信息传导页面上,需要使用ModelAndView作为返回值。

3、@ExceptionHandler方法标记的异常有优先级

4、 @ControllerAdvice注解如果当前Handler中找不到@ExceptionHandler方法来解决当前方法出现的异常,则将去@ControllerAdvice注解标记的类中查找@ExceptionHandler标记的方法来处理异常。

例如(当id = 0时,将出现异常)

index.jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%--
  Created by IntelliJ IDEA.
  User: 23369
  Date: 3/31/2019
  Time: 3:03 PM
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>$Title$</title>
</head>
<body>
<a href="testExceptionHandlerExceptionResolver?id=10">TestExceptionHandlerExceptionResolver</a>
</body>
</html>

error.jsp

<%--
  Created by IntelliJ IDEA.
  User: 23369
  Date: 4/4/2019
  Time: 7:50 PM
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
errorPage

<br>

错误信息是:${requestScope.exception}
</body>
</html>

TestException.class

(不使用ModelAndView)

package com.hello2;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class TestException {

    @ExceptionHandler({ArithmeticException.class})
    public String handlerArithmeticException(Exception exception){

        System.out.println("异常" + exception);

        return "error";
    }

    @RequestMapping("testExceptionHandlerExceptionResolver")
    public String testExceptionHandlerExceptionResolver(@RequestParam("id") Integer id ){

        System.out.println(10/id);

        return "success";
    }
}

(使用ModelAndView)

package com.hello2;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller
public class TestException {

    @ExceptionHandler({ArithmeticException.class})
    public ModelAndView handlerArithmeticException(Exception exception){

        System.out.println("异常" + exception);

        ModelAndView modelAndView = new ModelAndView("error");

       modelAndView.addObject("exception",exception);

        return modelAndView;
    }

    @RequestMapping("testExceptionHandlerExceptionResolver")
    public String testExceptionHandlerExceptionResolver(@RequestParam("id") Integer id ){

        System.out.println(10/id);

        return "success";
    }
}

使用 @ControllerAdvice注解

package com.hello2;


import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class HandlerException {

    @ExceptionHandler({ArithmeticException.class})
    public ModelAndView handlerArithmeticException(Exception exception){

        ModelAndView modelAndView = new ModelAndView("error");
        modelAndView.addObject("exception",exception);
        return modelAndView;
    }
}

ResponseStatusExceptionResolver

• 在异常及异常父类中找到 @ResponseStatus 注解,然后使用这个注解的属性进行处理。

• 定义一个 @ResponseStatus 注解修饰的异常类

• 若在处理器方法中抛出了上述异常: 若ExceptionHandlerExceptionResolver 不解析述异常。由于 触发的异常 UnauthorizedException 带有@ResponseStatus 注解。因此会被ResponseStatusExceptionResolver 解析到。最后响应HttpStatus.UNAUTHORIZED 代码给客户 端。HttpStatus.UNAUTHORIZED 代表响应码401,无权限。 关于其他的响应码请参考 HttpStatus 枚举类型源码。

•该注解常用的属性

—value:代表当前页面的响应码

—reason:输出出错的原因

注意:该注解可以作用于方法上。

例如(当上方index.jsp 页面中的id序号为10时,抛出异常)

TestRuntimeException.class(需要继承RuntimeException类)

package com.hello2;


import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "ID序号不正确")
public class TestRuntimeException extends RuntimeException {

    private static final long serialVersionUID = 1L;
}

TestException .class

package com.hello2;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;

@Controller
public class TestException {

  
    //@ResponseStatus(value = HttpStatus.FORBIDDEN.NOT_FOUND,reason = "ID序号不正确")
    @RequestMapping("testResponseStatusExceptionResolver")
    public String testResponseStatusExceptionResolver(@RequestParam("id") Integer id){

        if( id == 10){
            throw new TestRuntimeException();
        }else {
            System.out.println("成功");
        }

        return "success";
    }
}

DefaultHandlerExceptionResolver

• 对一些特殊的异常进行处理,比 如NoSuchRequestHandlingMethodException、HttpReques tMethodNotSupportedException、HttpMediaTypeNotSuppo rtedException、HttpMediaTypeNotAcceptableException 等。

SimpleMappingExceptionResolver

• 如果希望对所有异常进行统一处理,可以使用 SimpleMappingExceptionResolver,它将异常类名映射为 视图名,即发生异常时使用对应的视图报告异常