洪湖自己的网站,什么行业需要做网站和推广,网页介绍怎么写,网页制作要学什么课程优质博文#xff1a;IT-BLOG-CN
一、SpringBoot 默认的错误处理机制
【1】浏览器返回的默认错误页面如下#xff1a; ☞ 浏览器发送请求的请求头信息如下#xff1a; text/html会在后面的源码分析中说到。 【2】如果是其他客户端#xff0c;默认则响应错误的 JSON字符串IT-BLOG-CN
一、SpringBoot 默认的错误处理机制
【1】浏览器返回的默认错误页面如下 ☞ 浏览器发送请求的请求头信息如下 text/html会在后面的源码分析中说到。 【2】如果是其他客户端默认则响应错误的 JSON字符串如下所示 ☞ 其他客户端发送请求的请求头信息如下 */* 源码中解释。 二、原理分析
参照ErrorMvcAutoConfiguration类 错误处理的自动配置类以下4项为此类的重要信息。
【1】ErrorMvcAutoConfiguration.ErrorPageCustomizer 当系统出现 4xx或者 5xx之类的错误时ErrorPageCustomizer就会生效定制错误的响应规则根据如下源码可知将会来到/error请求。
Bean
public ErrorMvcAutoConfiguration.ErrorPageCustomizer errorPageCustomizer() {return new ErrorMvcAutoConfiguration.ErrorPageCustomizer(this.serverProperties);
}//进入ErrorPageCustomizer方法发现registerErrorPages方法注册一个错误也
private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {private final ServerProperties properties;protected ErrorPageCustomizer(ServerProperties properties) {this.properties properties;}public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {ErrorPage errorPage new ErrorPage(this.properties.getServletPrefix() this.properties.getError().getPath());errorPageRegistry.addErrorPages(new ErrorPage[]{errorPage});}
}//进入this.properties.getError().getPath()方法获取如下信息得到/error请求。
Value(${error.path:/error})
private String path /error;//系统出现错误以后来到error请求进行处理web.xml注册的错误页面规则【2】BasicErrorController 处理 /error错误请求 注意text/html和*/*就是在此处生效。
Bean
ConditionalOnMissingBean(value {ErrorController.class},search SearchStrategy.CURRENT
)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers);
}//进入BasicErrorController对象获取如下信息
Controller
RequestMapping({${server.error.path:${error.path:/error}}})
public class BasicErrorController extends AbstractErrorController {private final ErrorProperties errorProperties;public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) {this(errorAttributes, errorProperties, Collections.emptyList());}RequestMapping(produces {text/html}//产生html类型的数据浏览器发送的请求来到这个方法处理)public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {HttpStatus status this.getStatus(request);MapString, Object model Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));response.setStatus(status.value());//去哪个页面作为错误页面包含页面地址和页面内容ModelAndView modelAndView this.resolveErrorView(request, response, status, model);return modelAndView ! null?modelAndView:new ModelAndView(error, model);}RequestMappingResponseBody//产生json数据其他客户端来到这个方法处理public ResponseEntityMapString, Object error(HttpServletRequest request) {MapString, Object body this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));HttpStatus status this.getStatus(request);return new ResponseEntity(body, status);}
}☞ 如上代码中提到的错误页面解析代码进入此方法 this.resolveErrorView(request, response, status, model);
protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, MapString, Object model) {Iterator var5 this.errorViewResolvers.iterator();ModelAndView modelAndView;do {//从所有的ErrorViewResolver得到ModelAndViewif(!var5.hasNext()) {return null;}ErrorViewResolver resolver (ErrorViewResolver)var5.next();modelAndView resolver.resolveErrorView(request, status, model);} while(modelAndView null);return modelAndView;
}【3】最终的响应页面是由DefaultErrorViewResolver解析得到的 最重要的信息是SpringBoot默认模板引擎的/error目录下获取 ‘status’.xml 错误页面也可以通过4xx.xml来统配 404.xml和 400.xml等等但是优先获取精准的页面。如果模板引擎中不存在则会从静态页面中获取错误页面。否则返回系统默认错误页面。 BeanConditionalOnBean({DispatcherServlet.class})ConditionalOnMissingBeanpublic DefaultErrorViewResolver conventionErrorViewResolver() {return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties);}//进入DefaultErrorViewResolver类中
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, MapString, Object model) {ModelAndView modelAndView this.resolve(String.valueOf(status), model);if(modelAndView null SERIES_VIEWS.containsKey(status.series())) {//调用时viewname status ***重要modelAndView this.resolve((String)SERIES_VIEWS.get(status.series()), model);}return modelAndView;
}private ModelAndView resolve(String viewName, MapString, Object model) {//默认SpringBoot可以去找到一个页面 error/404String errorViewName error/ viewName;//模板引擎可以解析这个页面地址就用模板引擎解析TemplateAvailabilityProvider provider this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);//模板引擎可用的情况下返回到errorViewName指定的视图地址,//当模板引擎不可用就在静态资源文件夹下找errorViewName对应的页面 error/404.htmlreturn provider ! null?new ModelAndView(errorViewName, model):this.resolveResource(errorViewName, model);
}【4】DefaultErrorAttributes 在页面添加错误信息供我们使用。
Bean
ConditionalOnMissingBean(value {ErrorAttributes.class},search SearchStrategy.CURRENT
)
public DefaultErrorAttributes errorAttributes() {return new DefaultErrorAttributes();
}//进入DefaultErrorAttributes类中发现此方法给视图中添加了status状态等信息供我们使用。
public MapString, Object getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {MapString, Object errorAttributes new LinkedHashMap();errorAttributes.put(timestamp, new Date());this.addStatus(errorAttributes, requestAttributes);this.addErrorDetails(errorAttributes, requestAttributes, includeStackTrace);this.addPath(errorAttributes, requestAttributes);return errorAttributes;
}三、定制错误 JSON数据
【1】自定义异常处理类返回定制的 JSON数据。通过上述的分析我们得知 ①、可以完全编写一个ErrorController的实现类或者继承AbstractErrorController的子类放入容器中。 ②、也可以自定义异常处理类返回 JSON数据。 ③、页面上的数据或 JSON返回的数据都是可以通过errorAttributes.getErrorAttributes得到的。我们可以自定义属于自己的ErrorAttributes。
//首先我们可以通过自定义异常处理来确定返回的数据但这个不够灵活我们可以与③结合使用
/*** RequestMapping启动应用后被 ExceptionHandler、InitBinder、ModelAttribute 注解的方法都会作用在 被 RequestMapping* 注解的方法上。*/
ControllerAdvice
public class MyExceptionHandler {ResponseBodyExceptionHandler(UserNotExistException.class)public MapString,Object handlerException(Exception e, HttpServletRequest request){MapString,Object map new HashMapString,Object();request.setAttribute(javax.servlet.error.status_code,500);map.put(code,user.notexist);map.put(message,e.getMessage());return map;}
}//③自定义ErrorAttributes,一定要加入容器
Component
public class MyErrorAttributes extends DefaultErrorAttributes{Overridepublic MapString, Object getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {//获取默认的配置在此基础上添加自己的需求MapString, Object map super.getErrorAttributes(requestAttributes, includeStackTrace);//自定义自己需要的属性map.put(company,yintong);//获取我们在异常处理类中添加的信息/*注意当我们需要结合使用的时候异常处理必须return forward:/error;将请求转发出去不能直接返回map对象同时要去掉responseBody注解否则ErrorAttributes不生效*/map.put(ext,requestAttributes.getAttribute(ext,requestAttributes.SCOPE_REQUEST));return map;}
}【2】效果展示