springboot 2.2.5 错误处理机制(源码分析)

本文深入分析了SpringBoot的错误处理机制,包括ErrorMvcAutoConfiguration、ErrorPageCustomizer和BasicErrorController。讨论了如何区分浏览器和其他客户端,并解释了如何定制错误页面和响应JSON。通过ErrorViewResolver接口和DefaultErrorViewResolver实现自定义错误视图,同时展示了如何通过@ControllerAdvice定制JSON响应。最后,文章提供了自定义错误页面和响应数据的示例。
摘要由CSDN通过智能技术生成


首先,官方doc是这样介绍error的:

For machine clients, it produces a JSON response with details of the error, the HTTP status, and the exception message. For browser clients, there is a “whitelabel” error view that renders the same data in HTML format (to customize it, add a View that resolves to error) To replace the default behavior completely, you can implement ErrorController and register a bean definition of that type or add a bean of type ErrorAttributes to use the existing mechanism but replace the contents.

对于机器客户端(非浏览器)发生错误,会返回JSON数据格式的错误信息。

对于浏览器客户端发生错误,返回一个包含错误信息的"whitelabel"页面,如果想要定制,自己实现ErrorController即可。官方推荐:继承BasicErrorController。

The BasicErrorController can be used as a base class for a custom ErrorController. This is particularly useful if you want to add a handler for a new content type (the default is to handle text/html specifically and provide a fallback for everything else). To do so, extend BasicErrorController, add a public method with a @RequestMapping that has a produces attribute, and create a bean of your new type.

ErrorMvcAutoConfiguration 错误处理自动配置类

先了解一下springboot中有关错误处理的类为:ErrorMvcAutoConfiguration。

位置:package org.springframework.boot.autoconfigure.web.servlet.error;

@Configuration(proxyBeanMethods = false)
@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, WebMvcProperties.class })
public class ErrorMvcAutoConfiguration {
   
...
	@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);
	}
}

里面比较主要的类有:BasicErrorController 、ErrorPageCustomizer

ErrorPageCustomizer 错误页面定制器

源码如下:

//ErrorMvcAutoConfiguration.java
	@Bean
	public ErrorPageCustomizer errorPageCustomizer(DispatcherServletPath dispatcherServletPath) {
   
		return new ErrorPageCustomizer(this.serverProperties, dispatcherServletPath);
	}
	
	// 静态内部类,默认的错误页面配置
	private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {
   
		private final ServerProperties properties;
		private final DispatcherServletPath dispatcherServletPath;

		protected ErrorPageCustomizer(ServerProperties properties, DispatcherServletPath dispatcherServletPath) {
   
			this.properties = properties;
			this.dispatcherServletPath = dispatcherServletPath;
		}
		
		// 注册错误页面的响应规则
		@Override
		public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
   
			ErrorPage errorPage = new ErrorPage(
					//[#2] 注意getPath()
					this.dispatcherServletPath.getRelativePath(this.properties.getError().getPath()));
			errorPageRegistry.addErrorPages(errorPage);
		}
		//...
	}

继续往下点击看[#2]处源码,默认path为/error。

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

即系统出现错误以后会来到/error请求,进行处理;(类似web.xml注册的错误页面规则)
那么问题来了,通过ErrorPageCustomizer设置后,出现错误会来到/error请求,接下来给谁处理呢??—— BasicErrorController

BasicErrorController 默认处理/error请求控制器

一旦系统出现4xx或者5xx之类的错误 --> ErrorPageCustomizer就会生效(定制错误的响应规则) --> 就会来到/error请求 --> 就会被BasicErrorController处理;

	@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()));
	}

上面的源码里,有两个没见过的东西:ErrorViewResolver、BasicErrorController。

既然是返回BasicErrorController,肯定要看一下源码:

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
// ${server.error.path:${error.path:/error}} 解释:
// 如果没有配置server.error.path,则使用error.path;如果error.path也没有配置,则使用/error
public 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值