当前源码:
     
      spring-boot 2.2.5.RELEASE
     
     版本!
    
   
    
    
    1.声明
   
    
     当前内容是用来了解和复习SpringBoot中的BasicErrorController源码的,在于一次配置了日志的时候发现访问一个错误的url产生的就是一个模板错误页面
    
    
     
   
    
     使用springboot的时候产生这个肯定是访问路径没有被映射,所以才产生的
    
   
    
     本人debug发现:
    
    
     
   
    
     发现这个无论访问任何不存在的url都会调用BasicErrorController中的errorHtml方法!(所以本人决定解析这个类,并了解作用)
    
   
    
    
    2.分析BasicErrorController类
   
    
     首先通过
     
      名字发现BasicErrorController就是一个基本错误控制器
     
     ,
     
      就是一个Controller,也就是说spring可能使用@Controller注解
     
     ,其方法中必定有
     
      @RequestMapping用来处理error
     
     问题
    
   
    
     1.查看这个类的注解
    
   
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}") 
public class BasicErrorController extends AbstractErrorController {
}
    
     发现
     
      @RequestMapping("${server.error.path:${error.path:/error}}")
     
     ,可能就是用来匹配路径为/error的,本人表示有点不明白!就是使用了@Controller
    
   
    
     2.查看这个类调用的errorHtml方法
    
   
// 表示当前响应为html/text
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
	public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
		HttpStatus status = getStatus(request); // 获取http状态码
		// 获取错误的model(不可修改的)
		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);
	}
    
     发现该方法就是一个设置返回为html/text,并且居于状态码,并产生modelAndView的方法
    
   
    
     由于返回的ModelAndView是需要通过ViewResolver进行解析的成view才能返回的,所以继续找到对应的错误视图解析器
    
   
    
    
    3.找到错误视图解析器
   
    
     1.查看当前BasicErrorController所在的包,结果如下
    
    
    
    
    
     我们发现了ErrorViewResolver和DefaultErrorViewResolver(
     
      所以可以判断spring中默认就是使用DefaultErrorViewResolver进行解析的
     
     )
    
   
    
     
      ErrorMvcAutoConfiguration
     
     这个类应该就是Error视图自动配置类(
     
      访问不存在的url的配置类
     
     )
    
   
    
    
    4.查看DefaultErrorViewResolver类源码
   
    
     查看这个类的静态代码块:
    
   
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);
	}
    
     默认项SERIES_VIEWS 中添加了错误代码,分为客户端错误:
     
      4XX和服务器错误:5XX
     
     ,并且是不可修改的Map集合
    
   
    
     查看解析视图的方法
    
   
   // 解析错误的视图
	@Override
	public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
		// 传递当前的 HttpStatus 中的状态码:即4xx,5xx
		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;
	}
	//通过视图名称和model解析视图
	private ModelAndView resolve(String viewName, Map<String, Object> model) {
		String errorViewName = "error/" + viewName; // 为error/4xx,5xx
		TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName,
				this.applicationContext); // 判断是否存在模板
		if (provider != null) { // 存在就返回模板视图
			return new ModelAndView(errorViewName, model);
		}
		return resolveResource(errorViewName, model); // 否则返回资源视图(即当前文件error/中存在4xx或者5xx的html页面)
	}
	
	// 按照名称和model解析资源视图
	private ModelAndView resolveResource(String viewName, Map<String, Object> model) {
		// 获取静态资源路径
		for (String location : this.resourceProperties.getStaticLocations()) {
			try {
				// 通过路径获取resource
				Resource resource = this.applicationContext.getResource(location);
				resource = resource.createRelative(viewName + ".html"); // 通过error/4xx.html等是否存在
				if (resource.exists()) {
				    // 存在就返回他
					return new ModelAndView(new HtmlResourceView(resource), model);
				}
			}
			catch (Exception ex) {
			}
		}
		return null;
	}
    
     这里发现了HtmlResourceView这个内部类
    
   
private static class HtmlResourceView implements View {
		private Resource resource;
		HtmlResourceView(Resource resource) {
			this.resource = resource;
		}
		@Override
		public String getContentType() {
			return MediaType.TEXT_HTML_VALUE;
		}
		// 发现所有的view中都是具有这个方法的,所以通过这个方法可以实现所有的视图转发
		@Override
		public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
				throws Exception {
				// 设置响应类型
			response.setContentType(getContentType());
			// 将当前的html文件读入为输入流,并写入到响应流中
			FileCopyUtils.copy(this.resource.getInputStream(), response.getOutputStream());
		}
	}
    
     通过上面发现,为什么我们在resources文件中添加了error文件夹,并创建4xx.html,或者5xx.html的时候可以被springboot自动解析并在页面显示
    
   
    
    
    5.现在来看ErrorMvcAutoConfiguration
   
    
     首先通过ErrorMvcAutoConfiguration名称发现,这是一个错误mvc自动配置类,所以这个类必须有@Configuration注解
    
   
    
     1.查看这个类的注解
    
   
@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 })
    
     发现这个类在web应用中并且类型是Servlet在会创建,并且容器中必须有Servlet和DispatcherServlet存在,必须在WebMvcAutoConfiguration前面启动配置
    
   
==2.发现这个类中定义了很多bean,并且确实注入了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()));
	}
    
     3.发现这个类的静态内部类DefaultErrorViewResolverConfiguration(又是一个配置类),发现这个类中注入了DefaultErrorViewResolver这个错误视图解析器!
    
   
@Bean
		@ConditionalOnBean(DispatcherServlet.class)
		@ConditionalOnMissingBean(ErrorViewResolver.class)
		DefaultErrorViewResolver conventionErrorViewResolver() {
			return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties);
		}
==4.继续查看WhitelabelErrorViewConfiguration这个配置类,发现了StaticView ==
private final StaticView defaultErrorView = new StaticView();
		@Bean(name = "error")
		@ConditionalOnMissingBean(name = "error")
		public View defaultErrorView() {
			return this.defaultErrorView;
		}
    
     发现这个类名字叫error,估计有什么特殊作用
    
   
    
     5.继续查看StaticView类
    
   
    
    
    
     发现这个内容很熟悉
    
    
    
    
    
     发现结果就是这个,所以当我们访问一个不存在的url的时候就会创建StaticView,并启用render方法,写出一个text/html的模板信息
    
   
    
    
    6.总结
   
    
     1.我们使用Springboot
     
      访问一个不存在的url的时候,默认会创建error映射,并使用BasicErrorController中的@RequestMapping
     
    
   
    
     2.当
     
      BasicErrorController中的对应的@RequestMapping方法处理完后返回ModelAndView,就需要通过DefaultErrorViewResolver来解析并获取View
     
    
   
    
     3.当前
     
      解析的时候默认会使用StaticView来解析并生成(调用render方法)模板返回
     
    
   
    
     4.
     
      SpringBoot之所以这个简单,是因为ErrorMvcAutoConfiguration在启动的时候就被加载了各种需要的配置类,它将我们需要的东西都配置好了,所以我们使用起来很简单
     
     !
    
   
    
     以上纯属个人见解,如有问题请联系本人!
    
   
 
