前言 : spring boot 默认支持自适应的全局错误异常处理。当浏览器访问返回错误页面,当移动设备或者支持异步请求返回对应的json格式。
一、spring Boot 自适应错误处理
如果你想拥有springboot 默认自适应错误处理 ,将错误异常交给默认的控制器 /error 。
tips: 浏览器能显示错误异常页面, 是根据不同的错误响应码给浏览器。
- 定义错误处理器
@ControllerAdvice
public class ExceptionsHandler {
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
public String httpRequestMethodNotSupportedException(Exception e, HttpServletRequest request) {
e.printStackTrace();
String method = ((HttpRequestMethodNotSupportedException) e).getMethod();
return setFailMessage(request, method.concat("请求方式不正确"));
}
@ExceptionHandler({Exception.class})
public String exceptionHandler(Exception e, HttpServletRequest request) {
e.printStackTrace();
return setFailMessage(request, "服务器开小差了");
}
// 根据自己业务需要配置不同的错误异常......
// 将错误异常交给springboot管理
private String setFailMessage(HttpServletRequest request, String msg) {
request.setAttribute("javax.servlet.error.message", msg);
return "forward:/error";
}
}
2. 修改默认的错误属性
@Component
public class ExceptionConfig extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
// 从请求中拿到请求状态码和异常消息。这里的状态码由spring设置进去的。
Integer statusCode = (Integer) webRequest.getAttribute("javax.servlet.error.status_code", 0);
String msg = (String)webRequest.getAttribute("javax.servlet.error.message", 0);
// 构建自定义错误信息返回
return BeanUtil.beanToMap(JSONReturn.buildFailure(StringUtils.isEmpty(msg)?getStatusMessage(statusCode) : msg, statusCode));
}
// 获取不到错误信息,说明这些异常是spring 抛出来的。可以直接根据不同的状态码去获取不同的错误提示。也可以根据自己的业务需求更改提示信息。
private String getStatusMessage(Integer statusCode) {
String defaultMessage = "服务器异常";
if(ObjectUtil.isNull(statusCode)) return defaultMessage ;
for (HttpStatus httpStatus : HttpStatus.values()) {
if (statusCode == httpStatus.value()) return httpStatus.getReasonPhrase();
}
return defaultMessage;
}
}
3 .修改自定义的错误页面
1. 如果你使用了模版引擎,resources/templates 下创建error目录。如果没有resources/static 下创建error目录
2. 将你的错误页面放在里面,如:404.html, 500.html ,如果401 ,403,404等错误页面你想使用同一个页面 你可以取名为4xx.html, 按照状态码精确优先匹配规则找到页面展示。
注意: 以上都是springboot默认去寻找的错误页面。名字不能随便改。
浏览器效果:
Postman效果:
二、前后分离的应用
前后分离项目,只需提供json数据就可以了。
方式一:
1. 定义全局的错误异常
@ControllerAdvice
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public class ExceptionsHandler {
// 配置了throw-exception-if-no-handler-found: true 才会触发这个异常
@ExceptionHandler(NoHandlerFoundException.class)
public JSONReturn handlerNoFoundException(Exception e) {
e.printStackTrace();
return JSONReturn.buildFailure("路径不存在,请检查路径是否正确",HttpStatus.NOT_FOUND.value());
}
@ExceptionHandler({Exception.class})
public JSONReturn exceptionHandler(Exception e) {
e.printStackTrace();
return JSONReturn.buildFailure("服务器异常");
}
}
2 .配置yaml
spring:
# 抛出所有异常信息
mvc:
throw-exception-if-no-handler-found: true
# 2.4.0 版后过时,替换配置为: spring.web.resources.add-mappings=false
resources:
add-mappings: false
这种方式会禁用映射。会导致一些静态资源访问不到。[如果你的项目里没有静态资源,可以这样配置,否者这样配置了后,访问不到静态资源]
解决办法: 在web配置文件中,重写 `addResourceHandlers()` 方法,
贴出源码:
方式二:
思路: 修改默认异常处理器
1. 定义全局的错误异常
@ControllerAdvice
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public class ExceptionsHandler {
@ExceptionHandler({Exception.class})
public JSONReturn exceptionHandler(Exception e) {
e.printStackTrace();
return JSONReturn.buildFailure("服务器异常");
}
}
2. 重新springboot默认提供错误处理器
@Controller
public class NotFoundException implements ErrorController {
@Override
public String getErrorPath() {
return "/error";
}
// 当404错误被/error拦截
@RequestMapping(value = {"/error"})
@ResponseBody
public Object error(HttpServletRequest request) {
Integer state = (Integer)request.getAttribute("javax.servlet.error.status_code");
return JSONReturn.buildFailure(getStatusMessage(state), state);
}
private String getStatusMessage(Integer statusCode) {
String defaultMessage = "服务器异常";
if(ObjectUtil.isNull(statusCode)) return defaultMessage ;
for (HttpStatus httpStatus : HttpStatus.values()) {
if (statusCode == httpStatus.value()) return httpStatus.getReasonPhrase();
}
return defaultMessage;
}
}