示例 @ExceptionHandler处理异常

示例 @ExceptionHandler处理异常

新建一个项目ExceptionHandlerTest,加入所需的jar文件,示例代码如下:

index.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>异常处理示例</title>
</head>
<body>
<a href="test">@ExceptionHandler处理异常</a>
<br>
<a href="login">UserController:使用从父类继承来的异常处理方法</a>
<br>
<a href="find">BookController:使用从父类继承来的异常处理方法</a>
<br>
</body>
</html>

index.jsp中有3个超链接,分别用于测试@ExceptionHandler异常处理和使用父级Controller异常处理。

TestController.java

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
package org.fkit.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class TestController
{
@GetMapping("/test")
public String test() throws Exception
{
// 模拟异常,调用本类中定义的异常处理方法
@SuppressWarnings("unused")
int i = 5 / 0;
return "success";
}
// 在异常抛出的时候,Controller会使用@ExceptionHandler注解的方法去处理异常
// value=Exception.class表示处理所有的Exception类型异常。
@ExceptionHandler(value = Exception.class)
public ModelAndView testErrorHandler(Exception e)
{
ModelAndView mav = new ModelAndView();
mav.setViewName("error");
mav.addObject("ex", e);
return mav;
}
}

TestControllertest()方法是index.jsp页面的超链接"@ExceptionHandler处理异常“的请求处理方法,模拟了一个除数不能为0的异常。
testErrorHandler()方法使用了@ExceptionHandler注解, value = Exception.class表示处理所有的Exception类型异常。TestController类抛出异常的时候,会使用@ExceptionHandler注解的方法去处理异常,而不会直接抛给浏览器testErrorHandler()方法将捕捉到的异常对象保存到ModelAndView当中,传递到JSP页面。

error.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试@ExceptionHandler注解</title>
</head>
<body>
<h3>异常处理页面</h3>
抛出异常信息:${requestScope.ex.message}
</body>
</html>

部署ExceptionHandlerTest这个Web应用,在浏览器中输入如下URL来测试应用:

1
http://localhost:8080/ExceptionHandlerTest/

单击"@ExceptionHandler处理异常“超链接,发送"test"请求,TestControllertest()方方法在处理请求抛出异常,异常会被同一类中的@ExceptionHandler注解修饰的testErrorHandler方法捕获,处理之后跳转到error.jsp页面。

更好一点的做法

基于Controller@ExceptionHandler注解方法在进行异常处理时,对于每个Controller都需要写@ExceptionHandler注解的异常处理方法,在实际开发当中这非常烦琐。可以写一个父类,在父类中完成@ExceptionHandler注解的异常处理方法,所有的Controller继承这个父类,则所有的Controller就都拥有了@ExceptionHandler注解的异常处理方法。

BaseExceptionController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package org.fkit.controller;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
public class BaseExceptionController
{
// 表示这是一个异常处理方法
// value = Exception.class表示处理的异常类型为Exception
// 也就是处理所有的异常
@ExceptionHandler(value = Exception.class)
public ModelAndView defaultErrorHandler(Exception e) throws Exception
{
ModelAndView mav = new ModelAndView();
// 设置模型数据
mav.addObject("ex", e);
// 设置视图
mav.setViewName("error");
return mav;
}
}

BaseController作为父类,定义了一个@ExceptionHandler注解修饰的方法。

UserController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package org.fkit.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController extends BaseExceptionController
{
@GetMapping("/login")
public String login(String username) throws Exception
{
if (username == null)
{
// 调用本类的异常处理方法
throw new NullPointerException("用户名不存在!");
}
return "success";
}
}

UserController继承BaseController,如果抛出异常,将使用父类的ExceptionHandler注解修饰的方法处理异常。

BookController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.fkit.controller;

import java.sql.SQLException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class BookController extends BaseExceptionController
{
@GetMapping("/find")
public String find() throws Exception
{
try
{
// 除零异常,调用继承得到的异常处理方法
@SuppressWarnings("unused")
int i = 5 / 0;
return "success";
} catch (Exception e)
{
throw new SQLException("查找图书信息失败!");
}
}
}

BookController继承BaseController,如果抛出异常,将使用父类的@ExceptionHandler注解修饰的方法处理异常.
再次部署Exception2Test这个Web应用,在浏览器中输入如下URL来测试应用,单击"UserController:父级Controller异常处理“超链接,发送login请求,异常处理之后跳转到error.jsp页面.浏览器显示内容如下:

1
2
异常处理页面
抛出异常信息:用户名不存在!

再次请求index.jsp页面,单击BookController:使用从父类继承来的异常处理方法超链接,发送"find"请求,异常处理之后跳转到error.jsp页面.此时浏览器显示内容如下:

1
2
异常处理页面
抛出异常信息:查找图书信息失败!