我是靠谱客的博主 仁爱台灯,最近开发中收集的这篇文章主要介绍SpringBoot web--错误处理(学习笔记19),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1、比如说:

我先注释掉拦截器,让问题重现一下:



这里我访问一个不存在的请求路径,就出现了错误(There was an unexpected error (type=Not Found, status=404).)。通过客户端 Postman 模拟请求一下(下图所示),默认响应一个  JSON 数据:


原理:

    可以参照 ErrorMvcAutoConfiguration 进行错误处理的自动配置。

    给容器中添加了以下组件:

    1、DefaultErrorAttributes

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

    2、BasicErrorController:处理默认 /error 请求

        @Bean
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers);
}

    下面两个方法:第一个是产生 html 类型的数据(浏览器请求),第二个是产生 JSON 数据(客户端请求)

        @RequestMapping(produces = "text/html")
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
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = getStatus(request);
return new ResponseEntity<>(body, status);
}

    区分是浏览器请求还是客户端请求:

    浏览器:

    

    客户端:    

    


3、ErrorPageCustomizer

        @Bean
public ErrorPageCustomizer errorPageCustomizer() {
return new ErrorPageCustomizer(this.serverProperties);
}

    4、DefaultErrorViewResolver

        @Bean
@ConditionalOnBean(DispatcherServlet.class)
@ConditionalOnMissingBean
public DefaultErrorViewResolver conventionErrorViewResolver() {
return new DefaultErrorViewResolver(this.applicationContext, his.resourceProperties);
}

    规则说明:

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

        @Override
public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
ErrorPage errorPage = new ErrorPage(
this.properties.getServlet().getServletPrefix()
this.properties.getError().getPath());
errorPageRegistry.addErrorPages(errorPage);
}

        通过 this.properties.getError().getPath(), 得到 path 信息:

        /**
* Path of the error controller.
*/
@Value("${error.path:/error}")
private String path = "/error";

     就会来到/error请求; 就会被 BasicErrorController 处理(参考 BasicErrorController 下的两段代码),去哪个页面显示。去哪个页面是由 DefaultErrorViewResolver 解析的:

public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {
private static final Map<Series, String> SERIES_VIEWS;
static {
Map<Series, String> views = new EnumMap<>(Series.class);
views.put(Series.CLIENT_ERROR, "4xx");
views.put(Series.SERVER_ERROR, "5xx");
SERIES_VIEWS = Collections.unmodifiableMap(views);
}
        @Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status,
Map<String, Object> model) {
ModelAndView modelAndView = resolve(String.valueOf(status), model);
if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
}
return modelAndView;
}
private ModelAndView resolve(String viewName, Map<String, Object> model) {
String errorViewName = "error/" + viewName;
TemplateAvailabilityProvider provider = this.templateAvailabilityProviders
.getProvider(errorViewName, this.applicationContext);// 模板引擎可以解析这个页面地址就用模板引擎解析
if (provider != null) {//模板引擎可用的情况下返回到errorViewName指定的视图地址
return new ModelAndView(errorViewName, model);
}
return resolveResource(errorViewName, model);//模板引擎不可用,就在静态资源文件夹找errorViewName对应的页面 error/404.html,如果没有返回为null
}

2、如何定制错误响应

    2.1:如果是浏览器访问不存在请求路径,跳转错误页面,错误页面是定制的,要和整体网站的风格一致。

        2.1.1、有模板引擎的情况下:根据 error/状态码,将错误页面命名为:错误状态.html(404.html、4xx.html);把它们放在模板引擎文件夹里面的 error 文件夹下,发生相应的状态的错误就会找到对应的页面。

                    我们可以使用 4xx.html 和 5xx.html 页面来匹配相应状态码所有的错误(如果状态码没有匹配到具体的错误页面,就会指向此状态码统一页面。精确优先)

        2.1.2、没有模板引擎:模板引擎找不到错误页面,静态资源文件夹下存在

        2.1.3、模板引擎下没有、静态资源下也没有:就会使用默认的页面

        @Configuration
@ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", matchIfMissing = true)
@Conditional(ErrorTemplateMissingCondition.class)
protected static class WhitelabelErrorViewConfiguration {
private final SpelView defaultErrorView = new SpelView(
"<html><body><h1>Whitelabel Error Page</h1>"
+ "<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>"
+ "<div id='created'>${timestamp}</div>"
+ "<div>There was an unexpected error (type=${error}, status=${status}).</div>"
+ "<div>${message}</div></body></html>");
@Bean(name = "error")
@ConditionalOnMissingBean(name = "error")
public View defaultErrorView() {
return this.defaultErrorView;
}
// If the user adds @EnableWebMvc then the bean name view resolver from
// WebMvcAutoConfiguration disappears, so add it back in to avoid disappointment.
@Bean
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
BeanNameViewResolver resolver = new BeanNameViewResolver();
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
return resolver;
}
}

    2.2:如果是客户端请求,则要统一数据,定制返回数据

   

3、定制错误页面、返回定制错误json数据,并把定制数据进行显示

1、完全可以编写一个ErrorController的实现类 或者 编写AbstractErrorController的子类,放在容器中

2、页面上能用的数据,或者是json返回能用的数据都是通过 errorAttributes.getErrorAttributes 得到

感谢--尚硅谷


最后

以上就是仁爱台灯为你收集整理的SpringBoot web--错误处理(学习笔记19)的全部内容,希望文章能够帮你解决SpringBoot web--错误处理(学习笔记19)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部