博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot的定制错误数据
阅读量:3966 次
发布时间:2019-05-24

本文共 5159 字,大约阅读时间需要 17 分钟。

1、SpringBoot 默认的错误处理机制

1、浏览器访问的默认的错误处理效果:

在这里插入图片描述

2、如果是其他客户端,默认响应一个 json 数据;

在这里插入图片描述

2、错误处理原理分析

我们看到自动配置类:ErrorMvcAutoConfiguration 错误处理的自动配置类; 这里面注入了几个很重要的 bean;

  • 1、DefaultErrorAttributes
  • 2、BasicErrorController
  • 3、ErrorPageCustomizer
  • 4、DefaultErrorViewResolver

错误处理步骤:

ErrorPageCustomizer

一旦系统出现了 4xx 或者 5xx 之类的错误,ErrorPageCustomizer 就会生效(定制错误的响应规则)

@Beanpublic ErrorPageCustomizer errorPageCustomizer(DispatcherServletPath dispatcherServletPath) {
// 点进这个类 return new ErrorPageCustomizer(this.serverProperties, dispatcherServletPath);}

ErrorPageCustomizer

发现一个方法registerErrorPages 注册错误页面

@Overridepublic void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
ErrorPage errorPage = new ErrorPage( // 这里有个 getPath() 路径,我们点进去 this.dispatcherServletPath.getRelativePath(this.properties.getError().getPath())); errorPageRegistry.addErrorPages(errorPage);}// getPatpublic String getPath() {
return this.path;}// this.path@Value("${error.path:/error}") private String path = "/error";

BasicErrorController

系统一旦出现错误之后就会来到 /error 请求进行处理;这个请求会被 BasicErrorController 处理:

@Bean@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)public BasicErrorController basicErrorController(ErrorAttributes errorAttributes,		ObjectProvider
errorViewResolvers) {
//点进这个类 return new BasicErrorController(errorAttributes, this.serverProperties.getError(), errorViewResolvers.orderedStream().collect(Collectors.toList()));}

BasicErrorController

@Controller// 处理默认的 /error 请求@RequestMapping("${server.error.path:${error.path:/error}}")public class BasicErrorController extends AbstractErrorController {
}

这个类有两个方法:

// 产生html类型的数据,浏览器发送的请求会被这个方法处理@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = getStatus(request); Map
model = Collections .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); // 去哪个页面拿错误页面呢?resolveErrorView 方法 ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);}// 返回 json 类型的数据,其他的客户端请求会被这个方法处理@RequestMappingpublic ResponseEntity
> error(HttpServletRequest request) {
HttpStatus status = getStatus(request); if (status == HttpStatus.NO_CONTENT) {
return new ResponseEntity<>(status); } Map
body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL)); return new ResponseEntity<>(body, status);}

我们来看看resolveErrorView 这个方法

protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status,		Map
model) {
// 拿到所有的 errorViewResolvers 错误视图解析器 for (ErrorViewResolver resolver : this.errorViewResolvers) {
ModelAndView modelAndView = resolver.resolveErrorView(request, status, model); if (modelAndView != null) {
return modelAndView; } } return null;}

DefaultErrorViewResolver

我们在之前看到有这样一个bean DefaultErrorViewResolver 默认的错误视图解析器

@Bean@ConditionalOnBean(DispatcherServlet.class)@ConditionalOnMissingBean(ErrorViewResolver.class)DefaultErrorViewResolver conventionErrorViewResolver() {
//点进这个类 return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties);}

DefaultErrorViewResolver

public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {
private static final Map
SERIES_VIEWS; static {
Map
views = new EnumMap<>(Series.class); views.put(Series.CLIENT_ERROR, "4xx");// 客户端错误 views.put(Series.SERVER_ERROR, "5xx");// 服务端错误 SERIES_VIEWS = Collections.unmodifiableMap(views); } // .... @Override// HttpStatus 状态码 public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map
model) {
ModelAndView modelAndView = resolve(String.valueOf(status.value()), model); if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
// 通过状态码解析视图 modelAndView = resolve(SERIES_VIEWS.get(status.series()), model); } return modelAndView; } // 去 error 路径下解析视图 private ModelAndView resolve(String viewName, Map
model) {
// 比如 error/404 error/500 String errorViewName = "error/" + viewName; TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext); if (provider != null) {
return new ModelAndView(errorViewName, model); } return resolveResource(errorViewName, model); }//.....

所以说:定制错误页面,我们可以建立一个 error 目录,然后放入对应的错误码html文件! 比如:404.html 500.html 4xx.html 5xx.html

DefaultErrorAttributes

这些页面的信息数据在哪里呢?我们找到 DefaultErrorAttributes 这个bean对象;

@Bean@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)public DefaultErrorAttributes errorAttributes() {
return new DefaultErrorAttributes();}

DefaultErrorAttributes里面有很多的 addxx 方法,就是添加不同的信息;

// addStatus // addErrorDetails // addErrorMessage // addStackTrace // addPath// 这里面存了一些错误的信息,我们可以在错误页面直接取出

转载地址:http://qmuki.baihongyu.com/

你可能感兴趣的文章
调试 Perl 脚本
查看>>
增强的for循环语句
查看>>
方法的可变参数
查看>>
静态导入
查看>>
java 泛型
查看>>
控制结构
查看>>
标准输入输出
查看>>
运算符
查看>>
数据类型之列表与数组
查看>>
比较字符串
查看>>
Java EE 精萃
查看>>
Open Source 精萃
查看>>
Java EE 简介
查看>>
Weblogic 简介
查看>>
观察者模式 (Observer)
查看>>
Java 集合框架
查看>>
Weblogic 精萃
查看>>
Servlet 精萃
查看>>
XStream 精萃
查看>>
XStream 环境设置
查看>>