SpringMVC异常处理

本文最后更新于:1 年前

在我们的应用系统运行的过程中,可能由于运行环境、用户操作、资源不足等各方面的原因导致系统出现异常(HTTP状态异常、Exception);如果系统出现了异常,这些异常将会通过浏览器呈现给用户,而这种异常的显示是没有必要,因此我们可以在服务器进行特定的处理——当系统出现异常之后,呈现给用户一个统一的、可读的的异常提示页面。

SpringMVC异常处理思路

系统中异常包括两类:预期异常运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生。

系统的 Dao、Service、Controller 出现都通过 throws Exception 向上抛出,最后由 SpringMVC 前端控制器交由异常处理器进行异常处理,如下图:

SpringMVC异常处理的几种方式

  • 使用 Spring MVC注解 @ExceptionHandler 自定义异常处理器
  • 使用 Spring MVC 提供的简单异常处理器 SimpleMappingExceptionResolver
  • 实现 Spring 的异常处理接口 HandlerExceptionResolver 自定义自己的异常处理器

使用 @ExceptionHandler 自定义异常处理器

  1. 使用 @ControllerAdvice 注解声明全局异常处理类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @ControllerAdvice
    public class MyExceptionHandler {

    //声明该方法是异常处理器
    @ExceptionHandler(ClassCastException.class)
    public String nullHandler(){
    return "/err1.jsp";
    }

    @ExceptionHandler(MyException.class)
    public String formatHandler(){
    return "/err2.jsp";
    }

    }
  2. 创建错误视图页面

    1
    2
    3
    4
    5
    err1.jsp

    <body>
    <h1>类型转换异常</h1>
    </body>
    1
    2
    3
    4
    5
    err2.jsp

    <body>
    <h1>自定义异常</h1>
    </body>
  3. 控制器产生异常

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class DemoServiceImpl implements DemoService {

    @Override
    public void show1() {
    System.out.println("抛出类型转换异常....");
    Object str = "zhangsan";
    Integer num = (Integer)str;
    }

    @Override
    public void show5() throws MyException {
    System.out.println("自定义异常....");
    throw new MyException();
    }
    }
  4. 测试

简单异常处理器 SimpleMappingExceptionResolver

SpringMVC 已经定义好了该类型转换器,在使用时可以根据项目情况在 spring-servlet.xml 中进行相应异常与视图的映射配置。

默认错误视图 defaultErrorView

  1. 创建通用错误视图页面 error.jsp
1
2
3
<body>
<h1>类型转换异常</h1>
</body>
  1. 配置异常处理器 defaultErrorView

    1
    2
    3
    4
    <!--配置异常处理器-->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="defaultErrorView" value="error"/> //默认错误视图
    </bean>
  2. 控制器产生异常

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class DemoServiceImpl implements DemoService {

    @Override
    public void show1() {
    System.out.println("抛出类型转换异常....");
    Object str = "zhangsan";
    Integer num = (Integer)str;
    }
    }
  3. 测试

异常映射 exceptionMappings

  1. 配置异常处理器 exceptionMappings
1
2
3
4
5
6
7
8
9
<!--配置异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings" > //异常映射
<map>
<entry key="java.lang.ClassCastException" value="error1"/> //类型转换异常
<entry key="cc.gaojie.exception.MyException" value="error2"/> //自定义异常
</map>
</property>
</bean>
  1. 创建错误视图页面

    1
    2
    3
    4
    5
    error1.jsp

    <body>
    <h1>类型转换异常</h1>
    </body>
    1
    2
    3
    4
    5
    error2.jsp

    <body>
    <h1>自定义异常</h1>
    </body>
  2. 控制器产生异常

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class DemoServiceImpl implements DemoService {

    @Override
    public void show1() {
    System.out.println("抛出类型转换异常....");
    Object str = "zhangsan";
    Integer num = (Integer)str;
    }

    @Override
    public void show5() throws MyException {
    System.out.println("自定义异常....");
    throw new MyException();
    }
    }
  3. 测试

实现异常处理接口 HandlerExceptionResolver自定义异常处理类

创建异常处理器类实现 HandlerExceptionResolver
配置异常处理器
编写异常页面
测试异常跳转

1. 创建异常处理器类实现 HandlerExceptionResolver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MyExceptionResolver implements HandlerExceptionResolver {

/**
* 参数Exception:报异常的异常对象
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @return modelAndView 要跳转的错误视图的信息
*/
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView modelAndView = new ModelAndView();

if (e instanceof MyException){
modelAndView.addObject("info","自定义异常");
} else if (e instanceof ClassCastException){
modelAndView.addObject("info","类型转换异常");
}

modelAndView.setViewName("error");
return modelAndView;
}
}

2. 配置异常处理器

1
2
3
4
spring-mvc.xml

<!--自定义异常处理器-->
<bean class="cc.gaojie.resolver.MyExceptionResolver"/>

3. 编写异常页面

1
2
3
4
5
6
error.jsp

<body>
<h1>通用的错误提示页面</h1>
<h1>${info}</h1>
</body>

4. 测试异常跳转


其他异常处理方式

HTTP异常状态统一处理

以 HTTP Status 404 为例。

  1. 创建一个用于进行异常提示的页面:404.jsp

    1
    2
    3
    4
    <body>
    <center><h1>404 Not Found</h1></center>
    <center><h1>页面找不到</h1></center>
    </body>
  2. 在web.xml中进行配置:

    1
    2
    3
    4
    <error-page>
    <error-code>404</error-code>
    <location>/404.jsp</location>
    </error-page>

基于Servlet-api代码异常统一处理

  1. 创建异常提示页面:err.jsp

  2. 在web.xml中进行配置

    1
    2
    3
    4
    <error-page>
    <exception-type>java.lang.ClassCastException</exception-type>
    <location>/error1.jsp</location>
    </error-page>