Spring MVC 全局异常处理

Spring MVC提供了3种全局异常处理方式

  1. 使用 Spring MVC 提供的简单异常处理器 SimpleMappingExceptionResolver
  2. 实现 Spring 的异常处理接口 HandleExceptionResolver 自定义异常处理器
  3. 使用 @ExceptionHandler 注解实现异常处理

简单异常处理器

需要在spring mvc 的配置文件中配置简单异常处理器,主要配置异常发生时调用的视图页面和异常变量名称。

定义自定义异常

参数异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.example.ssm.exception;

/**
* 自定义异常:参数异常
*/
public class ParamsException extends RuntimeException {
private Integer code = 300;
private String msg = "参数异常";

public ParamsException(){
super("参数异常");
}

public ParamsException(String msg){
super(msg);
this.msg = msg;
}

public ParamsException(Integer code){
super("参数异常");
this.code = code;
}

public ParamsException(Integer code, String msg){
super(msg);
this.code = code;
this.msg = msg;
}

public Integer getCode() {
return code;
}

public void setCode(Integer code) {
this.code = code;
}

public String getMsg() {
return msg;
}

public void setMsg(String msg) {
this.msg = msg;
}
}
业务异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.example.ssm.exception;

/**
* 自定义异常:业务异常
*/
public class BusinessException extends RuntimeException{
private Integer code = 400;
private String msg = "业务异常";

public BusinessException(){
super("业务异常");
}

public BusinessException(String msg){
super(msg);
this.msg = msg;
}

public BusinessException(Integer code){
super("业务异常");
this.code = code;
}

public BusinessException(Integer code, String msg){
super(msg);
this.code = code;
this.msg = msg;
}

public Integer getCode() {
return code;
}

public void setCode(Integer code) {
this.code = code;
}

public String getMsg() {
return msg;
}

public void setMsg(String msg) {
this.msg = msg;
}
}

设置SpringMvc 配置文件

servlet-context.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 简单异常处理 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 设置默认的异常处理页面 (error是一个视图名) -->
<property name="defaultErrorView" value="error"/>
<!-- 设置异常的变量名 -->
<property name="exceptionAttribute" value="ex" />
<!-- 设置自定义异常与页面的映射 -->
<property name="exceptionMappings">
<props>
<!-- 定义 自定义异常类 对应的 视图名称 -->
<prop key="com.example.ssm.exception.ParamsException">params_error</prop>
<prop key="com.example.ssm.exception.BusinessException">buss_error</prop>
</props>
</property>
</bean>

定义错误页面

error.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<%--
Created by IntelliJ IDEA.
User: haight
Date: 2022/4/9
Time: 4:00 PM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Error</title>
</head>
<body>
<h2>${ex}</h2>
</body>
</html>

实现异常处理接口(推荐)

实现 HandlerExceptionResolver 接口,不需要配置 spring mvc的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.example.ssm.exception;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* 全局异常处理
*/
@Component
public class GlobalExceptionRsolver implements HandlerExceptionResolver {
/**
* 异常处理方法
* @param request 请求对象
* @param response 响应对象
* @param handler 目标方法
* @param ex 异常对象
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 得到ModelAndView对象 并设置默认视图
ModelAndView modelAndView = new ModelAndView("error");
// 设置默认的异常消息
modelAndView.addObject("ex", "默认的异常消息...");

// 根据不同的异常,执行不同的处理
if(ex instanceof ParamsException){
ParamsException paramsException = (ParamsException) ex;
paramsException.setCode(300);
paramsException.setMsg("参数异常...");

// 设置异常视图
modelAndView.setViewName("params_error");
modelAndView.addObject("ex", paramsException);
}

// 根据不同的异常,执行不同的处理
if(ex instanceof BusinessException){
BusinessException businessException = (BusinessException) ex;
businessException.setCode(400);
businessException.setMsg("业务异常...");

// 设置异常视图
modelAndView.setViewName("buss_error");
modelAndView.addObject("ex", businessException);
}

return modelAndView;
}
}

使用异常注解

控制器基类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.ssm.controller;

import com.example.ssm.exception.BusinessException;
import com.example.ssm.exception.ParamsException;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class BaseController {
@ExceptionHandler
public String exceptionResolver(HttpServletRequest request, HttpServletResponse response, Exception e){
request.setAttribute("ex", "默认异常消息...");

if(e instanceof ParamsException){
return "params_error";
} else if(e instanceof BusinessException){
return "buss_error";
}
// 返回默认异常视图名称
return "error";
}
}

使用注解 @ExceptionHandler ,只需要将要异常处理的 Controller 类继承与 BaseController 即可,不需要配置 spring mvc 的配置文件。

1
public class UserController extends BaseController {}

未捕获异常处理

大多数服务器,可以通过设置 web.xml, 配置特定异常情况下的显示页面。

web.xml
1
2
3
4
5
6
7
8
9
10
11
12
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/500.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>