SpringBoot默认的错误处理机制

即我们常见的白色的ErrorPage页面

浏览器发送的请求头:

如果是其他的请求方式,比如客户端,则相应一个json数据:

原理;是通过 ErrorMvcAutoConfiguration,错误处理的自动配置;

给容器中添加了以下组件

1、DefaultErrorAttributes:

帮我们在页面共享信息;
@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;
}

2、BasicErrorController:处理默认/error请求

@Controller
@RequestMapping("${server.error.path:${error.path:/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、ErrorPageCustomizer:

@Value("${error.path:/error}")
private String path = "/error"; 系统出现错误以后来到error请求进行处理;(web.xml注册的错误页面规则)

4、DefaultErrorViewResolver:

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

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

1)响应页面;去哪个页面是由DefaultErrorViewResolver解析得到的;

protected ModelAndView resolveErrorView(HttpServletRequest request,
HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
//所有的ErrorViewResolver得到ModelAndView
for (ErrorViewResolver resolver : this.errorViewResolvers) {
ModelAndView modelAndView = resolver.resolveErrorView(request, status, model);
if (modelAndView != null) {
return modelAndView;
}
}
return null;
}

2)、如何定制错误响应:

  如何定制错误的页面

1)、有模板引擎的情况下;error/状态码; 【将错误页面命名为 错误状态码.html 放在模板引擎文件夹里面的 error文件夹下】,发生此状态码的错误就会来到 对应的页面;

​ 我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码.html);

​ 页面能获取的信息;

​ timestamp:时间戳

​ status:状态码

​ error:错误提示

​ exception:异常对象

​ message:异常消息

​ errors:JSR303数据校验的错误都在这里

​ 2)、没有模板引擎(模板引擎找不到这个错误页面),静态资源文件夹下找;

​ 3)、以上都没有错误页面,就是默认来到SpringBoot默认的错误提示页面;

如何定制错误的json数据;

Controller.MyExceptionHandler

package com.project.javasystem.Controller;

import com.project.javasystem.exception.UserNotExistException;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map; @ControllerAdvice
public class MyExceptionHandler { //方法一:
//浏览器,客户端都返回的是Json数据
/* @ResponseBody//响应json数据
@ExceptionHandler(UserNotExistException.class)
public Map<String,Object> handleException(Exception e){
Map<String,Object>map = new HashMap<>();
map.put("code:","User.notExit");
map.put("message:",e.getMessage());
return map;
}*/ //方法二:自适应效果
@ExceptionHandler(UserNotExistException.class)
public String handleException(Exception e,HttpServletRequest request){
Map<String,Object>map = new HashMap<>();
//传入自定义的状态码
/*Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");*/
request.setAttribute("javax.servlet.error.status_code",500);
map.put("code:","User.NotExit");
map.put("message:","用户出错啦");
//转发到error进行自适应处理
request.setAttribute("MyError",map);
//转发到error
return "forward:/error";
}
}

3)、将我们的定制数据携带出去;

出现错误以后,会来到/error请求,会被BasicErrorController处理,响应出去可以获取的数据是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)规定的方法);

​ 1、完全来编写一个ErrorController的实现类【或者是编写AbstractErrorController的子类】,放在容器中;

​ 2、页面上能用的数据,或者是json返回能用的数据都是通过errorAttributes.getErrorAttributes得到;

​ 容器中DefaultErrorAttributes.getErrorAttributes();默认进行数据处理的;

自定义ErrorAttributes

Component.MyErrorAttributes

package com.project.javasystem.Component;

import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
import java.util.Map; @Component
public class MyErrorAttributes extends DefaultErrorAttributes { //返回值 map中就是页面和json能获取的所有字段
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> map = super.getErrorAttributes(webRequest,includeStackTrace);
map.put("CompanyName","517NA");
// 异常处理器携带的数据
Map<String,Object>MyError = (Map<String, Object>) webRequest.getAttribute("MyError", 0);
map.put("MyError",MyError);
return map;
}
}

最终的效果:响应是自适应的,可以通过定制ErrorAttributes改变需要返回的内容,

Springboot 错误处理机制的更多相关文章

  1. SpringBoot(六) -- SpringBoot错误处理机制

    一.SpringBoot中的默认的错误处理机制 1.在SpringBootWeb开发中,当我们访问请求出现错误时,会返回一个默认的错误页面: 2.在使用其他客户端访问的时候,则返回一个json数据: ...

  2. Springboot 系列(七)Spring Boot web 开发之异常错误处理机制剖析

    前言 相信大家在刚开始体验 Springboot 的时候一定会经常碰到这个页面,也就是访问一个不存在的页面的默认返回页面. 如果是其他客户端请求,如接口测试工具,会默认返回JSON数据. { &quo ...

  3. 学习小片段——springboot 错误处理

    一:先看看springboot默认的错误处理机制 springboot默认会判断是否是浏览器(http请求头Accept是否含有 text/html)来选择返回html错误页面或json错误信息 原因 ...

  4. 4_6.springboot2.xWeb开发之错误处理机制

    1.SpringBoot默认的错误处理机制 默认效果:1).浏览器,返回一个默认的错误页面 浏览器发送请求的请求头: ​ 2).如果是其他客户端,默认响应一个json数据 原理: ​ 默认情况下,Sp ...

  5. linux系统编程之错误处理机制

    在讲解liunx错误处理机制之前我们先来看一段代码: #include<sys/types.h> #include<sys/stat.h> #include<fcntl. ...

  6. javascript中的错误处理机制

    × 目录 [1]对象 [2]类型 [3]事件[4]throw[5]try[6]常见错误 前面的话 错误处理对于web应用程序开发至关重要,不能提前预测到可能发生的错误,不能提前采取恢复策略,可能导致较 ...

  7. Map/Reduce 工作机制分析 --- 错误处理机制

    前言 对于Hadoop集群来说,节点损坏是非常常见的现象. 而Hadoop一个很大的特点就是某个节点的损坏,不会影响到整个分布式任务的运行. 下面就来分析Hadoop平台是如何做到的. 硬件故障 硬件 ...

  8. Android IOS WebRTC 音视频开发总结(七五)-- WebRTC视频通信中的错误恢复机制

    本文主要介绍WebRTC视频通信中的错误恢复机制(我们翻译和整理的,译者:jiangpeng),最早发表在[这里] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:blac ...

  9. PHP异常与错误处理机制

    先区别一下php中错误 与 异常的概念吧 PHP错误:是属于php程序自身的问题,一般是由非法的语法,环境问题导致的,使得编译器无法通过检查,甚至无法运行的情况.平时遇到的warming.notice ...

随机推荐

  1. 【Java基础】字面量相加的类型转换

    Java字面量的相加类型转换 1.Java 编译期间(javac),凡是字面量和常量的运算,都会先运算出结果 2.运行期当字符串池中有 String"字面量"时,Java 会直接用 ...

  2. Mybatis一级缓存和二级缓存总结

    1:mybatis一级缓存:级别是session级别的,如果是同一个线程,同一个session,同一个查询条件,则只会查询数据库一次 2:mybatis二级缓存:级别是sessionfactory级别 ...

  3. Java package 包的命名规范。

    Java的包名都有小写单词组成,类名首字母大写:包的路径符合所开发的 系统模块的 定义,比如生产对生产,物资对物资,基础类对基础类.以便看了包名就明白是哪个模块,从而直接到对应包里找相应的实现. 由于 ...

  4. iptables filter表案例、iptables nat表应用 使用介绍

    第7周第4次课(5月10日) 课程内容: 10.15 iptables filter表案例10.16/10.17/10.18 iptables nat表应用 扩展1. iptables应用在一个网段 ...

  5. fsockopen以Socket方式模拟HTTP下载文件

    fsockopen 的功能很强大,比如前面模拟 HTTP 访问,模拟 POST/GET 请求,什么的,这里再举一个例子,那就是下载东西.比如下载 http://www.nowamagic.net//l ...

  6. 动态规划--最长上升子序列(LIS)的长度

    l例如:对于[3,1,4,2,5],最长上升子序列的长度是3 arr = [3,1,4,5,9,2,6,5,0] def lis(arr): #dp[i]表示第i个位置的值为尾的数组的最长递增子序列的 ...

  7. 【读一本书】《昇腾AI处理器架构与编程》--神经网络基础知识(2)

    1 卷积神经网络:输入层 之前提到多层感知机的参数太多,导致训练耗时长并且对图像处理也不具有优势,因此大神们 就提出了多层神经网络,其中最经典的是卷积神经网络(Convolution Neural N ...

  8. 解密国内BAT等大厂前端技术体系-百度篇(长文建议收藏)

    1 引言 整个业界在前端框架不断迭代中,也寻找到了许多突破方向,例如跨平台中的RN.Flutter,服务端GraphQL.Serverless,前端和客户端的融合越来越紧密,前端在Node和Elect ...

  9. 记录一些实用的小技巧-CSS篇

    1.单行文本截断 .text{ width: 200px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } 2.多行 ...

  10. python 列表越界

    data = [1,8,5,9,7,4,5] print(data[10:]) #返回空 print(data[10]) #出错,越界