How to implement your own custom error return page in SpringBoot

Customized exception handling returns an error page

a) PassErrorMvcAutoConfigurationAutomatic configuration class to understand the principle of exception handling

​ There are four core processing methods in this automatic configuration class, as follows:

​ 1)ErrorPageCustomizer

	//第一步:系统出现错误以后来到error请求进行处理
private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {
    
    

		private final ServerProperties properties;

		protected ErrorPageCustomizer(ServerProperties properties) {
    
    
			this.properties = properties;
		}

		@Override
		public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
    
    
			ErrorPage errorPage = new ErrorPage(this.properties.getServletPrefix()
					+ this.properties.getError().getPath());//系统出现错误以后来到error请求进行处理
            	/*
            		@Value("${error.path:/error}")
                   	 private String path = "/error";
                   	 
                   	 public String getPath() {
						return this.path;
					}
			   	*/
			errorPageRegistry.addErrorPages(errorPage);
		}

		@Override
		public int getOrder() {
    
    
			return 0;
		}

	}

​ 2)BasicErrorController

	//第二步:处理/error请求,根据请求判断响应格式
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")//处理/error请求
public class BasicErrorController extends AbstractErrorController {
    
    
    
    @RequestMapping(produces = "text/html")//产生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 ? new ModelAndView("error", model) : modelAndView);
	}

	@RequestMapping
	@ResponseBody    //产生json数据,其他客户端来到这个方法处理;
	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<Map<String, Object>>(body, status);
	}

​ 3)DefaultErrorViewResolver

	//第三步:根据视图解析跳转页面
public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {
    
    

	private static final Map<Series, String> SERIES_VIEWS;

	static {
    
    
		Map<Series, String> views = new HashMap<Series, String>();
		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);//调用resolve方法
		}
		return modelAndView;
	}

	private ModelAndView resolve(String viewName, Map<String, Object> model) {
    
    
        //默认SpringBoot可以去找到一个页面?  error/404
		String errorViewName = "error/" + viewName;
        
        //模板引擎可以解析这个页面地址就用模板引擎解析
		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);
	}
}

Insert picture description here

​ 4)DefaultErrorViewResolver

//在错误页面共享信息
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DefaultErrorAttributes
		implements ErrorAttributes, HandlerExceptionResolver, Ordered {
    
    
@Override
	public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes,
			boolean includeStackTrace) {
    
    
		Map<String, Object> errorAttributes = new LinkedHashMap<String, Object>();
		errorAttributes.put("timestamp", new Date());
		addStatus(errorAttributes, requestAttributes);
		addErrorDetails(errorAttributes, requestAttributes, includeStackTrace);
		addPath(errorAttributes, requestAttributes);
		return errorAttributes;
	}

	private void addStatus(Map<String, Object> errorAttributes,
			RequestAttributes requestAttributes) {
    
    
		Integer status = getAttribute(requestAttributes,
				"javax.servlet.error.status_code");
		if (status == null) {
    
    
			errorAttributes.put("status", 999);
			errorAttributes.put("error", "None");
			return;
		}
		errorAttributes.put("status", status);
		try {
    
    
			errorAttributes.put("error", HttpStatus.valueOf(status).getReasonPhrase());
		}
		catch (Exception ex) {
    
    
			// Unable to obtain a reason
			errorAttributes.put("error", "Http Status " + status);
		}
	}
}

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_45496190/article/details/107296832