错误处理机制
- 浏览器请求返回,返回 error.html 页面
- 通过 POSTMAN 等方式接口请求,返回JSON错误信息
原理:
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = getStatus(request);
Map<String, Object> model = Collections
.unmodifiableMap(getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
}
@RequestMapping
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
HttpStatus status = getStatus(request);
if (status == HttpStatus.NO_CONTENT) {
return new ResponseEntity<>(status);
}
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
return new ResponseEntity<>(body, status);
}
}
BasicErrorController.java 为默认错误处理控制器,Spring 根据客户端请求头 accept 的属性值做不同的处理,如 text/html 则表示为页面请求,对Spring 对 produces = MediaType.TEXT_HTML_VALUE 的处理方式执行
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response)
其他则按照默认如下处理
@RequestMapping
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request)
错误数据信息,通过以下接口返回
protected Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {
WebRequest webRequest = new ServletWebRequest(request);
return this.errorAttributes.getErrorAttributes(webRequest, includeStackTrace);
}
Spring 通过ErrorMvcAutoConfiguration 对错误处理进行配置
public class ErrorMvcAutoConfiguration {
/** 错误处理属性 */
@Bean
@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
public DefaultErrorAttributes errorAttributes() {
return new DefaultErrorAttributes(this.serverProperties.getError().isIncludeException());
}
/** 错误处理控制器 */
@Bean
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes,
ObjectProvider<ErrorViewResolver> errorViewResolvers) {
return new BasicErrorController(errorAttributes, this.serverProperties.getError(),
errorViewResolvers.orderedStream().collect(Collectors.toList()));
}
/** 错误页面制定器 */
@Bean
public ErrorPageCustomizer errorPageCustomizer(DispatcherServletPath dispatcherServletPath) {
return new ErrorPageCustomizer(this.serverProperties, dispatcherServletPath);
}
}
根据具体情况重新制定 ErrorAttributes.java、ErrorController.java
Spring 异常处理拦截
@ControllerAdvice
public class MyExceptionHandler {
@ResponseBody
@ExceptionHandler(UserNotExistException.class)
public Map<String,Object> handleException(Exception e) {
Map<String,Object> map = new HashMap<>();
map.put("key","value");
return map;
}
@ResponseBody
@ExceptionHandler(UserNotExistException2.class)
public Map<String,Object> handleException2(Exception e, HttpServletRequest request) {
request.setAttribute("javax.servlet.error.status_code",500);
return "forword:error";
}
}