SpringBoot——定制错误页面及原理

优质博文: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);Map<String, 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);}@RequestMapping@ResponseBody//产生json数据,其他客户端来到这个方法处理;public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {Map<String, 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, Map<String, 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等等,但是优先获取精准的页面。如果模板引擎中不存在,则会从静态页面中获取错误页面。否则返回系统默认错误页面。

 @Bean@ConditionalOnBean({DispatcherServlet.class})@ConditionalOnMissingBeanpublic DefaultErrorViewResolver conventionErrorViewResolver() {return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties);}//进入DefaultErrorViewResolver类中
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, 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, Map<String, 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 Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {Map<String, 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 {@ResponseBody@ExceptionHandler(UserNotExistException.class)public Map<String,Object> handlerException(Exception e, HttpServletRequest request){Map<String,Object> map = new HashMap<String,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 Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {//获取默认的配置,在此基础上添加自己的需求Map<String, 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】效果展示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/168605.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git提交报错error: failed to push some refs to ‘git url‘

1.产生错误原因 想把本地仓库提交到远程仓库&#xff0c;报错信息如下 git提交报错信息 error: src refspec master does not match any error: failed to push some refs to git url 错误原因&#xff1a; 我们在创建仓库的时候&#xff0c;都会勾选“使用Reamdme文件初始化…

Android相机性能提高50%

文章目录 应用举例&#xff08;可以不看这一part&#xff0c;直接跳过看具体怎么做&#xff09;&#xff1a;Snapchat 通过 Camera2 Extensions API 将新相机功能的集成速度提高了 50%**Camera2 扩展 API 可以访问高级功能更多设备上的更多机会 正文&#xff1a;开始使用扩展架…

hdlbits系列verilog解答(Exams/m2014 q4h)-44

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 实现以下电路&#xff1a; 二、verilog源码 module top_module (input in,output out);assign out in;endmodule三、仿真结果 转载请注明出处&#xff01;

Vatee万腾科技新高峰:Vatee前瞻性创新的数字化之力

Vatee万腾科技&#xff0c;一家以前瞻性创新为核心驱动力的数字化引领者&#xff0c;正迈向新的高峰。其在科技领域的卓越表现不仅体现在技术实力上&#xff0c;更展现在对未来的深刻洞察和独到思考上。 在Vatee的科技舞台上&#xff0c;前瞻性创新如一道独特的光芒&#xff0c…

【Linux】yum -- 软件包管理器

目录 一、Linux中是如何安装软件的 1.1 安装的方法 1.2 安装的本质(基本理解) 二、软件包 2.1 软件包的概念 2.2 为什么要有软件包 三、yum--软件包管理器 3.1 yum的概念 3.2 yum的使用 3.2.1 搜索一个软件 3.2.2 安装一个软件 3.2.3 卸载一个软件 3.3 yum源更新 …

Node.js入门指南(三)

目录 Node.js 模块化 介绍 模块暴露数据 导入模块 导入模块的基本流程 CommonJS 规范 包管理工具 介绍 npm cnpm yarn nvm的使用 我们上一篇文章介绍了Node.js中的http模块&#xff0c;这篇文章主要介绍Node.js的模块化&#xff0c;包管理工具以及nvm的使用。 Node…

Joint Cross-Modal and Unimodal Features for RGB-D Salient Object Detection

提出的模型 the outputs H i m _i^m im​ from the unimodal RGB or depth branch in MFFM FFM means ‘Feature Fusion Module’ 作者未提供代码

优秀软件设计特征与原则

1.摘要 一款软件产品好不好用, 除了拥有丰富的功能和人性化的界面设计之外, 还有其深厚的底层基础, 而设计模式和算法是构建这个底层基础的基石。好的设计模式能够让产品开发快速迭代且稳定可靠, 迅速抢占市场先机&#xff1b;而好的算法能够让产品具有核心价值, 例如字节跳动…

GPS 定位信息获取(北斗星通 GPS)

GPS 定位信息获取&#xff08;1&#xff09; 首先回顾北斗星通 GPS 数据获取&#xff08;1&#xff09;~&#xff08;5&#xff09; gps_pub.cpp 将接收到的串口数据转化为GPS的经纬度信息gps_path.cpp 将经纬度信息转化为全局坐标系下的XY值&#xff0c;以第一个GPS经纬度为…

【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】

初始前后端交互原生AjaxFetchaxios同源策略解决跨域 1 初识前后端交互2 原生Ajax2.1 Ajax基础2.2 Ajax案例2.3 ajax请求方式 3 Fetch3.1 fetch基础3.2 fetch案例 4 axios4.1 axios基础4.2 axios使用4.2.1 axios拦截器4.2.2 axios中断器 5 同源策略6 解决跨域6.1 jsonp6.2 其他技…

搭配:基于OpenCV的边缘检测实战

引言 计算机中的目标检测与人类识别物体的方式相似。作为人类&#xff0c;我们可以分辨出狗的形象&#xff0c;因为狗的特征是独特的。尾巴、形状、鼻子、舌头等特征综合在一起&#xff0c;帮助我们把狗和牛区分开来。 同样&#xff0c;计算机能够通过检测与估计物体的结构和性…

Linux 常见命令篇

history 获取执行的指令记录 语法格式: history [参数] 常用参数&#xff1a; -a 写入命令记录 -c 清空命令记录 -d 删除指定序号的命令记录 -n 读取命令记录 -r 读取命令记录到缓冲区 -s 将指定的命令添加到缓冲区 -w 将缓冲区信息写入到历史文件 history#获取最近的三条…

C#关键字、特性基础及扩展合集(持续更新)

一、基础 Ⅰ 关键字 1、record record&#xff08;记录&#xff09;&#xff0c;编译器会在后台创建一个类。支持类似于结构的值定义&#xff0c;但被实现为一个类&#xff0c;方便创建不可变类型&#xff0c;成员在初始化后不能再被改变 &#xff08;C#9新增&#xff09; …

Hologres性能优化指南1:行存,列存,行列共存

在Hologres中支持行存、列存和行列共存三种存储格式&#xff0c;不同的存储格式适用于不同的场景。 在建表时通过设置orientation属性指定表的存储格式&#xff1a; BEGIN; CREATE TABLE <table_name> (...); call set_table_property(<table_name>, orientation,…

Centos上安装Docker和DockerCompose

安装Docker Docker可以运行在MAC&#xff0c;Windows&#xff0c;CtenOS,UBUNTU等操作系统上。目前主流的版本有Docker CE和Docker EE&#xff0c;CE是免费的开源Docker版本&#xff0c;适用于开发人员和小型团队&#xff0c;EE是适用于企业的容器化解决方案。它基于Docker CE…

2023-11-24 LeetCode每日一题(统计和小于目标的下标对数目)

2023-11-24每日一题 一、题目编号 2824. 统计和小于目标的下标对数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 target &#xff0c;请你返回满足 0 < i < j < n 且 nums[i] nums[j] < targe…

开源的文本编辑器Notepad++ 8.6.0版本在Windows系统上的下载与安装配置

目录 前言一、Notepad 安装二、使用配置总结 前言 Notepad 是一款简单而强大的文本编辑工具&#xff0c;通常用于快速创建和编辑文本文件。以下是 Notepad 工具的详细介绍。注&#xff1a;文末附有下载链接&#xff01; 主要特点&#xff1a; ——简洁易用&#xff1a; Note…

蓝桥杯物联网竞赛_STM32L071_4_按键控制

原理图&#xff1a; 当按键S1按下PC14接GND&#xff0c;为低电平 CubMX配置: Keil配置&#xff1a; main函数&#xff1a; while (1){/* USER CODE END WHILE */OLED_ShowString(32, 0, "hello", 16);if(Function_KEY_S1Check() 1){ OLED_ShowString(16, 2, &quo…

FANUC机器人到达某个点位时,为什么不显示@符号?

FANUC机器人到达某个点位时,为什么不显示@符号? 该功能由变量$MNDSP_POSCF = 0(不显示)/1(显示)/2(光标移动该行显示) 控制,该变量设置为不同的值,则启用对应的功能。 如下图所示,为该变量设置不同的值时的对比, 其他常用的系统变量可参考以下内容: 在R寄存器指定速度…

什么是AWS CodeWhisperer?

AWS CodeWhisperer https://aws.amazon.com/cn/codewhisperer/ CodeWhisperer 经过数十亿行代码的训练&#xff0c;可以根据您的评论和现有代码实时生成从代码片段到全函数的代码建议。 ✔ 为您量身定制的实时 AI 代码生成器 ✔ 支持热门编程语言和 IDE ✔ 针对 AWS 服务的优…