完善的异常处理可以让客户端有一个良好的体验,并且有利于定位出错原因,帮助更好的解决问题。
SpringBoot 内置了一个 /error 处理,当抛出异常之后,会被转到这个映射进行处理, 就是常见的 Whitelable Error Page
另外一种就是使用ajax请求,SpringBoot会返回如下的Json格式字符串信息‘’
原理很简单,SpringBoot默认提供了程序出错的结果映射路径/error。这个/error请求是会在BasicErrorController中进行处理,其内部是通过判断请求头中的Accept的内容是否是text/html来区分是客户端浏览器(浏览器通常默认自动发送请求头内容Accept:text/html)还是客户端接口的调用,以此来决定返回视图还是JSON消息的内容,如下图是BasicErrorController的底层源码(在idea中三次按shift键将进入底层源码)
定义一个简单的error.html页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" >
<head>
<meta charset="UTF-8"/>
<title>error</title>
</head>
<body>
server error
<p th:text="${errorMessage}"/>
</body>
</html>
定义一个全局的GlobalRestExceptionHandler类来进行处理ajax响应和页面请求响应
/**
* @Description: 全局异常处理,针对ajax响应和页面请求响应
*/
@RestControllerAdvice
public class GlobalRestExceptionHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
@ExceptionHandler(Exception.class)
public Object exception(HttpServletRequest reqest, HttpServletResponse response,HandlerMethod handlerMethod, Exception exception) {
Method m = handlerMethod.getMethod();
Class<?> clazz = handlerMethod.getBeanType();
//判断访问的url是否为rest接口请求
boolean isRestReq = (m.getAnnotation(ResponseBody.class)!=null
||clazz.getAnnotation(ResponseBody.class)!=null
||clazz.getAnnotation(RestController.class)!=null);
//判断访问的url是否为ajax请求
boolean isAjax = isAjax(reqest);
if (isAjax||isRestReq) {
logger.error("global exception", exception);
if (exception instanceof VeException) {
return ResultInfo.fail(VeErrorCode.UNKNOWN_EXCEPTION, exception.getMessage());
}
return ResultInfo.fail(VeErrorCode.UNKNOWN_EXCEPTION);
} else {
logger.error("界面请求异常", exception);
ModelAndView mv = new ModelAndView();
if (exception instanceof VeException) {
mv.addObject("errorMessage", exception.getMessage());
mv.setViewName("error");
return mv;
}
mv.addObject("errorMessage", "");
mv.setViewName("error");
return mv;
}
}
/**
* 判断网络请求是否为ajax
*
* @param req
* @return
*/
private boolean isAjax(HttpServletRequest req) {
String contentTypeHeader = req.getHeader("Content-Type");
String acceptHeader = req.getHeader("Accept");
String xRequestedWith = req.getHeader("X-Requested-With");
return (contentTypeHeader != null && contentTypeHeader.contains("application/json"))
|| (acceptHeader != null && acceptHeader.contains("application/json"))
|| "XMLHttpRequest".equalsIgnoreCase(xRequestedWith);
}
}
VeException 中的内容
**
* 全局异常
*/
public class VeException extends RuntimeException {
private String code;
private String message;
public VeException(VeErrorCode errorCode) {
super(errorCode.getCode());
this.code = errorCode.getCode();
this.message = errorCode.getMessage();
}
public String getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}
VeErrorCode中的内容
public enum VeErrorCode {
UNKNOWN_EXCEPTION("unknown_exception","系统内部错误");
private String code;
private String message;
private VeErrorCode(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
测试:将会出现两种
ajax请求响应![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/33cf7b5624e455e572f928baa6261798.png)
页面请求响应
测试成功
版权声明:转载请标明博客地址,谢谢!