更多内容,前往 IT-BLOG

一、SpringBoot 默认的错误处理机制


【1】浏览器返回的默认错误页面如下:
 
☞ 浏览器发送请求的请求头信息如下:text/html 会在后面的源码分析中说到。
   
【2】如果是其他客户端,默认则响应错误的 JSON字符串,如下所示:
 
☞ 其他客户端发送请求的请求头信息如下: " */* " 源码中解释。
  

二、原理分析


参照 ErrorMvcAutoConfiguration类:错误处理的自动配置类,以下4项为此类的重要信息。

【1】ErrorMvcAutoConfiguration.ErrorPageCustomizer:当系统出现 4xx或者 5xx之类的错误时,ErrorPageCustomizer就会生效(定制错误的响应规则),根据如下源码可知,将会来到 /error请求。

 1 @Bean
2 public ErrorMvcAutoConfiguration.ErrorPageCustomizer errorPageCustomizer() {
3 return new ErrorMvcAutoConfiguration.ErrorPageCustomizer(this.serverProperties);
4 }
5
6 //进入ErrorPageCustomizer方法,发现registerErrorPages方法:注册一个错误也
7 private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {
8 private final ServerProperties properties;
9
10 protected ErrorPageCustomizer(ServerProperties properties) {
11 this.properties = properties;
12 }
13
14 public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
15 ErrorPage errorPage = new ErrorPage(this.properties.getServletPrefix() +
16 this.properties.getError().getPath());
17 errorPageRegistry.addErrorPages(new ErrorPage[]{errorPage});
18 }
19 }
20
21 //进入this.properties.getError().getPath()方法,获取如下信息,得到/error请求。
22 @Value("${error.path:/error}")
23 private String path = "/error";//系统出现错误以后来到error请求进行处理;(web.xml注册的错误页面规则)

【2】BasicErrorController 处理 /error错误请求:注意:text/html 和 */*就是在此处生效。

 1 @Bean
2 @ConditionalOnMissingBean(
3 value = {ErrorController.class},
4 search = SearchStrategy.CURRENT
5 )
6 public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
7 return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers);
8 }
9
10 //进入BasicErrorController对象,获取如下信息
11 @Controller
12 @RequestMapping({"${server.error.path:${error.path:/error}}"})
13 public class BasicErrorController extends AbstractErrorController {
14 private final ErrorProperties errorProperties;
15
16 public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) {
17 this(errorAttributes, errorProperties, Collections.emptyList());
18 }
19
20 @RequestMapping(
21 produces = {"text/html"}//产生html类型的数据;浏览器发送的请求来到这个方法处理
22 )
23 public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
24 HttpStatus status = this.getStatus(request);
25 Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
26 response.setStatus(status.value());
27
28 //去哪个页面作为错误页面;包含页面地址和页面内容
29 ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
30 return modelAndView != null?modelAndView:new ModelAndView("error", model);
31 }
32
33 @RequestMapping
34 @ResponseBody//产生json数据,其他客户端来到这个方法处理;
35 public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
36 Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
37 HttpStatus status = this.getStatus(request);
38 return new ResponseEntity(body, status);
39 }
40 }

☞ 如上代码中提到的错误页面解析代码,进入此方法: this.resolveErrorView(request, response, status, model);

 1 protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
2 Iterator var5 = this.errorViewResolvers.iterator();
3 ModelAndView modelAndView;
4 do {
5 //从所有的ErrorViewResolver得到ModelAndView
6 if(!var5.hasNext()) {
7 return null;
8 }
9
10 ErrorViewResolver resolver = (ErrorViewResolver)var5.next();
11 modelAndView = resolver.resolveErrorView(request, status, model);
12 } while(modelAndView == null);
13
14 return modelAndView;
15 }

【3】最终的响应页面是由 DefaultErrorViewResolver 解析得到的:最重要的信息是,SpringBoot 默认模板引擎的 /error目录下获取 ‘status’.xml 错误页面,也可以通过 4xx.xml来统配 404.xml和 400.xml等等,但是优先获取精准的页面。如果模板引擎中不存在,则会从静态页面中获取错误页面。否则返回系统默认错误页面。

 1  @Bean
2 @ConditionalOnBean({DispatcherServlet.class})
3 @ConditionalOnMissingBean
4 public DefaultErrorViewResolver conventionErrorViewResolver() {
5 return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties);
6 }
7
8 //进入DefaultErrorViewResolver类中
9 public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
10 ModelAndView modelAndView = this.resolve(String.valueOf(status), model);
11 if(modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
12
13 //调用时viewname = status ***重要
14 modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);
15 }
16
17 return modelAndView;
18 }
19
20 private ModelAndView resolve(String viewName, Map<String, Object> model) {
21
22 //默认SpringBoot可以去找到一个页面? error/404
23 String errorViewName = "error/" + viewName;
24
25 //模板引擎可以解析这个页面地址就用模板引擎解析
26 TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.
27 getProvider(errorViewName, this.applicationContext);
28
29 //模板引擎可用的情况下返回到errorViewName指定的视图地址,
30 //当模板引擎不可用,就在静态资源文件夹下找errorViewName对应的页面 error/404.html
31 return provider != null?new ModelAndView(errorViewName, model):this.resolveResource(errorViewName, model);
32 }

【4】DefaultErrorAttributes:在页面添加错误信息,供我们使用。

 1 @Bean
2 @ConditionalOnMissingBean(
3 value = {ErrorAttributes.class},
4 search = SearchStrategy.CURRENT
5 )
6 public DefaultErrorAttributes errorAttributes() {
7 return new DefaultErrorAttributes();
8 }
9
10 //进入DefaultErrorAttributes类中,发现此方法给视图中添加了status状态等信息,供我们使用。
11 public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
12 Map<String, Object> errorAttributes = new LinkedHashMap();
13 errorAttributes.put("timestamp", new Date());
14 this.addStatus(errorAttributes, requestAttributes);
15 this.addErrorDetails(errorAttributes, requestAttributes, includeStackTrace);
16 this.addPath(errorAttributes, requestAttributes);
17 return errorAttributes;
18 }

三、定制错误 JSON数据


【1】自定义异常处理类,返回定制的 JSON数据。通过上述的分析,我们得知:①、可以完全编写一个 ErrorController的实现类,或者继承 AbstractErrorController的子类,放入容器中。②、也可以自定义异常处理类,返回 JSON数据。③、页面上的数据或 JSON返回的数据都是可以通过 errorAttributes.getErrorAttributes得到的。我们可以自定义属于自己的 ErrorAttributes。

 1 //首先我们可以通过自定义异常处理,来确定返回的数据,但这个不够灵活,我们可以与③结合使用
2 /**
3 * @RequestMapping启动应用后,被 @ExceptionHandler、@InitBinder、@ModelAttribute 注解的方法,都会作用在 被 @RequestMapping
4 * 注解的方法上。
5 */
6 @ControllerAdvice
7 public class MyExceptionHandler {
8 @ResponseBody
9 @ExceptionHandler(UserNotExistException.class)
10 public Map<String,Object> handlerException(Exception e, HttpServletRequest request){
11 Map<String,Object> map = new HashMap<String,Object>();
12 request.setAttribute("javax.servlet.error.status_code","500");
13 map.put("code","user.notexist");
14 map.put("message",e.getMessage());
15 return map;
16 }
17 }
18
19 //③自定义ErrorAttributes,一定要加入容器
20 @Component
21 public class MyErrorAttributes extends DefaultErrorAttributes{
22 @Override
23 public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
24 //获取默认的配置,在此基础上添加自己的需求
25 Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace);
26 //自定义自己需要的属性
27 map.put("company","yintong");
28
29 //获取我们在异常处理类中添加的信息,
30 /*注意:当我们需要结合使用的时候异常处理必须return "forward:/error";将请求转发出去,不能直接返回map对象,
31 同时要去掉@responseBody注解,否则ErrorAttributes不生效*/
32 map.put("ext",requestAttributes.getAttribute("ext",requestAttributes.SCOPE_REQUEST));
33 return map;
34 }
35 }

【2】效果展示:
  


 ----关注公众号,获取更多内容----

SpringBoot——定制错误页面及原理的更多相关文章

  1. springboot 定制错误页面

    项目中经常遇到的异常情况 400-Bad Request 401-Unauthorized If the request already included Authorization credenti ...

  2. SpringBoot定制错误页面

    (1)有模板引擎的情况下,例如404错误,将会在thymeleaf的templates的error下寻找404.html,如果找不到再寻找4xx.html *所有4开头的错误状态码如果找不到特定的ht ...

  3. SpringBoot定制错误的Json数据

    (1)自定义异常处理&返回定制Json数据 @ControllerAdvice public class MyExceptionHandler { @ResponseBody @Excepti ...

  4. SpringBoot自定义错误页面,SpringBoot 404、500错误提示页面

    SpringBoot自定义错误页面,SpringBoot 404.500错误提示页面 SpringBoot 4xx.html.5xx.html错误提示页面 ====================== ...

  5. springboot自定义错误页面

    springboot自定义错误页面 1.加入配置: @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { re ...

  6. 【Laravel5】 定制错误页面

    laravel5   所有异常错误都由类   App\Exceptions\Handler    处理,该类包含两个方法:   report   和   render . 这里我们只看 render  ...

  7. Spring boot错误处理以及定制错误页面

    如果是浏览器访问,返回错误页面 注意浏览器发送请求的请求头:  注意区别其他客户端哦比如 postman 如果是其他客户端,返回一个Json数据 原理可以参照ErrorMvcAutoConfigura ...

  8. springboot系列六、springboot配置错误页面及全局异常

    一.spring1.x中处理方式 @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new ...

  9. Springboot - 自定义错误页面

    Springboot 没找到页面或内部错误时,会访问默认错误页面.这节我们来自定义错误页面. 自定义错误页面 1.在resources 目录下面再建一个 resources 文件夹,里面建一个 err ...

  10. apache定制错误页面

    编辑配置文件,错误页面定制支持三种形式: 1. 普通文本 2. 本地跳转 3. 外部跳转 [root@ken-node2 ~]# vim /etc/httpd/conf/httpd.conf ... ...

随机推荐

  1. python 安装步骤

    1.这个安装方法不需要配置环境变量 2. 3. 4.进入cmd,输入python -v

  2. kafka消费者3种分配策略

    0.10.2.1 版本的Kafka 有两种分配策略,由消费者测的参数partition.assignment.strategy来控制. RoundRobinAssignor分配策略 RangeAssi ...

  3. 1903021126 申文骏 Java 第七周作业 客户类测试

     项目  内容 课程班级博客链接 19级信计班(本) 作业要求链接 Java 第七周作业 博客名称 1903021126  申文骏  Java 第七周作业  客户类测试 要求 每道题要有题目,代码(使 ...

  4. modesim : mosel not define

    这个星期仿真sdram时,添加的sdram 模型文件在modesim中总是找不到,在qq群里提问和私聊别人都没有得到解决方法.于是自己摸索了好多天.终于得到了解决. 可以看到modesim里面work ...

  5. Linux命令之nc命令

    1.简介 nc是netcat的简写,是一个功能强大的网络工具,有着网络界的瑞士军刀美誉.nc命令在linux系统中实际命令是ncat,nc是软连接到ncat.nc命令的主要作用如下: 实现任意TCP/ ...

  6. IDEA 2018.3.*本地启动tomcat项目无法设置Application context localhost 404

    记录一个开发中遇到的坑,网上找了好久才找到一个能解决的办法,特此转载一下. 旧版的idea启动web项目,在tomcat配置环节,有设置Application content的功能.我们可以设置成&q ...

  7. 中值滤波 ordfilt2函数

    滤波是过滤掉信号中没用的波段 ordfilt2函数语法格式为:B=ordfilt2(A,order,domain)B=ordfilt2(A,order,domain,S)B=ordfilt2(..., ...

  8. .Net 开发 web.config参数获取

    System.Configuration.ConfigurationSettings.AppSettings["title"] 对应着 web.config下面的 <conf ...

  9. Linux 格式化 挂载 Gdisk

    对磁盘进行格式化mkfs 创建文件系统 xfs ext4/2/3 mkfs -b 设定数据区块(block)占用空间大小,目前支持1024.2048.4096 bytes每个块.默认4K mkfs - ...

  10. vue + vant 移动端适配

    1. 设置动态根字号大小,/public/phone-adapt.js,在index.html中引入 (function (doc, win) { const docEl = win.document ...