一、准备工作
1.1 导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- thymeleaf模板依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
1.2 在 /templates 目录下新建 error 页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<meta charset="UTF-8"/>
<title>统一页面异常处理</title>
</head>
<body>
<h1>统一页面异常处理</h1>
<div th:text="${message}"></div>
</body>
</html>
1.3 定义异常基类
@Data
public class BaseException extends RuntimeException {
/**
* 错误码
*/
private Integer code;
/**
* 错误提示
*/
private String message;
public BaseException(Integer code, String message) {
this.code = code;
this.message = message;
}
}
二、根据 URL 后缀区分
2.1 创建 URL 异常类
@Data
public class UrlSuffixException extends BaseException {
public UrlSuffixException(Integer code, String message) {
super(code, message);
}
}
2.2 申明接口
@Controller
@RequestMapping("/error")
public class ExceptionController {
@RequestMapping("/url.html")
public void throwsUrlSuffixExceptionByHtml() {
throw new UrlSuffixException(0001, "throwUrlSuffixException");
}
@RequestMapping("/url.json")
public void throwsUrlSuffixExceptionByJson() {
throw new UrlSuffixException(0001, "throwUrlSuffixException");
}
}
2.3 全局异常处理 UrlSuffixException
@ControllerAdvice
public class GlobalExceptionHandle {
private static final String URL_SUFFIX_JSON = ".json";
@ExceptionHandler(UrlSuffixException.class)
public ModelAndView handleException(HttpServletRequest request, UrlSuffixException exception) {
String url = request.getRequestURL().toString();
if (url.endsWith(URL_SUFFIX_JSON)) {
ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
modelAndView.addObject("code", exception.getCode());
modelAndView.addObject("message", exception.getMessage());
return modelAndView;
} else {
ModelAndView modelAndView = new ModelAndView("/error");
modelAndView.addObject("message", exception.getMessage());
return modelAndView;
}
}
}
2.4 测试
访问http://localhost:8080/error/url.json
{
message: "throwUrlSuffixException",
code: 1001
}
访问 `http://localhost:8080/error/url.html
三、根据注解区分
3.1 创建注解异常类
@Data
public class AnnotationException extends BaseException {
public AnnotationException(Integer code, String message) {
super(code, message);
}
}
3.2 申明接口
@Controller
@RequestMapping("/error")
public class ExceptionController {
@RequestMapping("/annotation/html")
public void throwsAnnotationExceptionByHtml() {
throw new AnnotationException(2000, "throwAnnotationException");
}
@RequestMapping("/annotation/json")
@ResponseBody
public String throwsAnnotationExceptionByJson() {
throw new AnnotationException(2001, "throwAnnotationException");
}
}
3.3 全局异常处理
@ControllerAdvice
public class GlobalExceptionHandle {
@ExceptionHandler(AnnotationException.class)
public ModelAndView handleException(AnnotationException exception, HandlerMethod handler) {
if (isReturnJson(handler)) {
ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
modelAndView.addObject("code", exception.getCode());
modelAndView.addObject("message", exception.getMessage());
return modelAndView;
} else {
ModelAndView modelAndView = new ModelAndView("/error");
modelAndView.addObject("message", exception.getMessage());
return modelAndView;
}
}
private boolean isReturnJson(HandlerMethod handler) {
if (handler.getBeanType().isAnnotationPresent(RestController.class)) {
return true;
}
Method method = handler.getMethod();
if (method.isAnnotationPresent(ResponseBody.class)) {
return true;
}
return false;
}
}
3.4 测试
访问 http://localhost:8080/error/annotation/json
{
message: "throwAnnotationException",
code: 2001
}
访问 `http://localhost:8080/error/annotation/html
四、根据是否是 AJAX 请求区分
4.1 创建异常类
@Data
public class AjaxRequestException extends BaseException {
public AjaxRequestException(Integer code, String message) {
super(code, message);
}
}
4.2 申明接口
@Controller
@RequestMapping("/error")
public class ExceptionController {
@RequestMapping("/request")
@ResponseBody
public String throwsAjaxRequestException() {
throw new AjaxRequestException(3000, "throwAjaxRequestException");
}
}
4.3 全局异常处理
@ControllerAdvice
public class GlobalExceptionHandle {
@ExceptionHandler(AjaxRequestException.class)
public ModelAndView handleException(HttpServletRequest request, AjaxRequestException exception) {
if (isAjaxRequest(request)) {
ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
modelAndView.addObject("code", exception.getCode());
modelAndView.addObject("message", exception.getMessage());
return modelAndView;
} else {
ModelAndView modelAndView = new ModelAndView("/error");//配置需要跳转的Controller方法
modelAndView.addObject("message", exception.getMessage());
return modelAndView;
}
}
private boolean isAjaxRequest(HttpServletRequest request) {
String accept = request.getHeader("accept");
if (accept != null && accept.indexOf("application/json") != -1) {
return true;
}
String xRequestedWith = request.getHeader("X-Requested-With");
if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) {
return true;
}
String uri = request.getRequestURI();
if (uri.endsWith(".json") || uri.endsWith(".xml")) {
return true;
}
String ajax = request.getParameter("__ajax");
if (ajax.endsWith("json") || ajax.endsWith("xml")) {
return true;
}
return false;
}
}
4.4 测试
访问http://localhost:8080/error/request
ajax 形式访问http://localhost:8080/error/request