Spring boot 2.x 错误处理机制 与 定制错误页面

目录

Spring boot 错误处理机制概述

Spring boot 错误处理机制原理

Spring boot 定制错误页面跳转


Spring boot 错误处理机制概述

1、Spring Boot web 应用,当浏览器访问发生错误时,默认会显然如下的错误页面,包含 时间戳、错误类型、状态码、以及错误消息等

2、显然实际开发中需要自己接手管理错误处理,定制错误页面提升用户体验。

3、当第三方的 APP 应用访问 web 应用的接口时,如果发生错误,则显然无法让它跳转到错误页面,而需要将错误参数返回。因为 app 的数据也通常是通过调用服务器接口来获取的,当发生错误时,直接返回错误数据即可,如:

{
    " timestamp": 1519637719324,
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/crud/aaa"
}

4、Spring Boot 会根据请求头信息中的 " Accept " 字段字段进行判断,发生错误时,如果是浏览器访问,则跳转到错误页面,如果是 app 内部访问,则直接返回错误数据。

Spring boot 错误处理机制原理

1、Spring Boot 关于错误处理的自动配置可以参照 “ ErrorMvcAutoConfiguration ” 类

package org.springframework.boot.autoconfigure.web.servlet.error;
.......
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
// Load before the main WebMvcAutoConfiguration so that the error View is available
@AutoConfigureBefore(WebMvcAutoConfiguration.class)
@EnableConfigurationProperties({ ServerProperties.class, ResourceProperties.class })
public class ErrorMvcAutoConfiguration {
........
ErrorMvcAutoConfiguration ” 中给容器添加了以下几个关键组件
DefaultErrorAttributes

用于提供默认的错误属性,从而可以在页面获取这些信息并显示,如 <h1>status:[[${status}]]</h1>

timestamp:时间戳
status:状态码
error:错误提示
exception:异常对象
message:异常消息
errors:JSR303数据校验的错误都在这里

BasicErrorController处理默认的 /error 请求
DefaultErrorViewResolver默认的错误视图解析器,即发生错误,应用应该去哪里找错误页面

2、BasicErrorController 处理默认的 /error 请求,源码如下:

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
	private final ErrorProperties errorProperties;
//.......
    //产生 html 类型的数据:浏览器发送的请求如果发生错误时,就来到这个方法进行处理
	@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));
	}

    //产生 json 类型的数据:如 APP 等客户端请求发生错误时,来到这个方法进行处理
	@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、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) {
        // 默认 Spring Boot 会去到 error 目录下寻找,如:error/404.html
		String errorViewName = "error/" + viewName;
        //如果 error 目录位于模板引擎(templates)目录下,则使用模板引擎解析视图
		TemplateAvailabilityProvider provider = this.templateAvailabilityProviders
				.getProvider(errorViewName, this.applicationContext);
		if (provider != null) {
            //模板引擎可用的情况下返回到 errorViewName 指定的视图地址
			return new ModelAndView(errorViewName, model);
		}
        //模板引擎不可用时,就去静态资源文件夹下找 errorViewName 对应的页面 如:error/404.html
		return resolveResource(errorViewName, model);
	}
//......
}

Spring boot 定制错误页面跳转

1、通过上面的错误处理机制原理可知,错误页面默认需要放在类路径下的 "error " 目录下,错误页面使用 http 错误代码进行命名,如 404.html、500.html 等。

2、也可以使用 4xx、5xx 作为错误页面的泛指文件名,例如当同时存在 404.html 与 4xx.html 文件,访问发生 404 错误时,优先匹配进入 404.html 页面,而发生 404 以外的错误时,则进入了 4xx.html 页面。

3、约定的 error 目录可以放在模板引擎目录(templates)下,也可以放在 4 大静态资源目录下,推荐放在 template 下,因为模板引擎下,可以使用 thymeleaf 模板引擎,静态文件夹下无法使用 Thymeleaf 模板引擎。

错误页面源码:https://github.com/wangmaoxiong/thymeleafapp/tree/master/src/main/resources/templates/error

4、如果将错误页面放在四大静态资源目录下,则跳转是没问题的,只是页面中无法再使用 thymelaf 模板引擎语法,只能自己写页面内容,无法获取后台具体的信息值,如状态码、错误信息等。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蚩尤后裔-汪茂雄

芝兰生于深林,不以无人而不芳。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值