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

一:先看看springboot默认的错误处理机制

springboot默认会判断是否是浏览器(http请求头Accept是否含有 text/html)来选择返回html错误页面或json错误信息

原因在于BasicErrorController 控制器中的这两个映射

  errorHtml响应来自浏览器的请求,而error响应来自其他客户端的请求;

  在errorHtml中最后两句,如果没有自定义的页面,就会使用系统默认的错误解析视图

二:那么如何定制自己的错误页面呢?

由BasicErrorController 控制器中errorHtml的最后调用

1 ModelAndView modelAndView = resolveErrorView(request, response, status, model);

获取用户自定义的对应的错误页面

(DefaultErrorViewResolver)

resolve方法或先查找模板引擎的页面中是否有error/(错误状态码) 页面,如果有就直接返回视图,如果没有就查找静态资源文件下有没有,如果也没有就返回null,使用springboot默认的

这样的话,我们就只需要在模板引擎解析目录或者静态资源目录的error文件夹下放入(错误状态码).html 即可,(也可以是4xx , 5xx)

模板页面里能获取到一些信息

timestamp:时间戳
status:状态码
error:错误提示
exception:异常对象
message:异常消息
errors:JSR303数据校验的错误都在这里

例如:(我是thymleaf)

 1 <!DOCTYPE html>
 2 <html lang="en"  xmlns:th="http://www.thymeleaf.org">
 3 <head>
 4     <meta charset="UTF-8">
 5     <!--/*@thymesVar id="status" type="java"*/-->
 6     <title th:text="${status}"></title>
 7 </head>
 8 <body>
 9 <h2>timestamp : [[${timestamp}]]</h2>
10 <h2>status : [[${status}]]</h2>
11 <h2>error : [[${error}]]</h2>
12 <h2>exception : [[${exception}]]</h2>
13 <h2>message : [[${message}]]</h2>
14 <h2>errors : [[${errors}]]</h2>
15 </body>
16 </html>

三:定制json格式错误响应

利用自定义异常处理机制来定制json数据响应

 1 @ControllerAdvice
 2 public class MyExceptionHandler {
 3     @ResponseBody
 4     @ExceptionHandler(Exception.class)
 5     public Map<String, Object> exceptionHandler1(Exception e){
 6         Map<String, Object> map = new HashMap<>();
 7         map.put("status", 400);
 8         map.put("msg", e.getMessage());
 9         map.put("data", null);
10         return map;
11     }
12 }
1     @GetMapping("/222")
2     public void test4(){
3         throw new RuntimeException("23333");
4     }

四:需要像springboot默认的一样自动选择响应html页面还是json

html错误页面上的数据和json的数据都是通过errorAttributes.getErrorAttributes得到的,

所以我们可以在自定义异常处理中转发到/error, 并自定义ErrorAttributes,来实现

 1 @ControllerAdvice
 2 public class MyExceptionHandler {
 3     @ExceptionHandler(Exception.class)
 4     public String exceptionHandler1(Exception e, HttpServletRequest request){
 5         Map<String, Object> map = new HashMap<>();
 6         map.put("msg", e.getMessage());
 7         map.put("data", null);
 8         request.setAttribute("errorMap", map);
 9
10         request.setAttribute("javax.servlet.error.status_code",400);
11
12         return "forward:/error";
13     }
14 }
1 @Component
2 public class MyErrorAttributes extends DefaultErrorAttributes {
3     @Override
4     public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
5         Map<String, Object> map = (Map<String, Object>) requestAttributes.getAttribute("errorMap", 0);
6
7         return map;
8     }
9 }

还有之前的4xx.html

效果:

五:完全由我们自己实现

编写一个ErrorController的实现类【或者是编写AbstractErrorController的子类】,放在容器中,来达到自定义效果

原文地址:https://www.cnblogs.com/REdrsnow/p/10630921.html

时间: 2024-10-25 09:14:12

学习小片段——springboot 错误处理的相关文章

linux网络编程学习笔记之二 -----错误异常处理和各种碎碎(更新中)

errno 在unix系统中对大部分系统调用非正常返回时,通常返回值为-1,并设置全局变量errno(errno.h),如socket(), bind(), accept(), listen().erron存放一个正整数来保存上次出错的错误值. 对线程而言,每个线程都有专用的errno变量,不必考虑同步问题. strerror converts to English (Note: use strerror_r for thread safety) perror is simplified str

跟我一起,利用bitcms内容管理系统从0到1学习小程序开发:一、IIS下SSL环境搭建

缘起 1.从事互联网十来年了,一直想把自己的从事开发过程遇到的问题给写出来,分享给大家.可是可是这只是个种想法,想想之后就放下了,写出来的类文章是少之又少.古人说无志之人常立志,有志之人立长志.今天,就从学习小程序开始,记录在学习过程中的遇到点点滴滴,先做“无志之人常立志”吧. 强调的是,微信小程序开发,我也是从0到1的过程,肯定会有错误或遗漏,还望给指导指导,让我的学习知识更完善,再此先谢过了. 2.bitcms开源内容管理系统也发布了,运营对一个程序老猿来说,确实是个艰巨的任务.自己的想法很

我是如何学习小程序的

前段时间和大家一起分享了一篇关于学习方法内容<大牛与搬运工的差距--学习方法的力量>.我们将学习过程分成八步,并借鉴了敏捷开发的迭代思想,以达到自我迭代学习的效果.行胜于言,理论结合实践才是王道,所以本文我将基于前面的学习方法,分享我是如何学习微信小程序的. 关于小程序 小程序是继订阅号.服务号.企业号后,16年腾讯新推出的又一种开发能力.小程序无需下载安装,可以在微信内便捷地获取和传播,可谓是一款"即扫即用,用完即扔"的便捷应用,同时具有近似APP般的出色使用体验. 坦白

[学习笔记]iphone学习小技巧

1. 版本控制 -- 是否响应某个方法 .查看当前系统版本. eg: [self respondsToSelector:@Selector(presentModalViewController:animated:)]//Yes:表示响应这个方法 [[UIDevice currentDevice].systemVersion floatValue] < 7.0 //判断当前系统是否小于7.0 2. 模态视图动画设置 eg: ModalViewController *modalVC = [[Moda

Android学习小Demo(20)关于Fragment的应用

Android在3.0之后引入了Fragment的概念,我猜测其想法可能只是想更好地兼容大屏幕或者平板的开发,因为大屏幕可以展示更多的内容,而内容一多,逻辑有可能就乱,而利用Fragment,则可以将不同的逻辑封装进不同的Fragment中,但是展现呢,还是在同一个Activity中,在同一个屏幕上显示.而对于屏幕并不大的手机来说,如果一个页面展示的东西并不多,那么其实将逻辑直接写在Activity,利用多个Activity实现多个页面的展示,我觉得也是可以接受的,毕竟用Activity还是用F

COM 学习小记录

COM组件程序:模块,它可以是 动态连接库(DLL) && 可执行程序(EXE),称为 进程内组件(in-of-process component) && 进程外组件(out-of-process component). COM对象:建立在二进制可执行代码级的基础上,因此COM对象是语言无关的,这一特性使得使用不同编程语言开发的组件对象进行交互成为可能. COM标准:规范 && 实现.规范:定义了组件和组件之间的通信机制,不依赖于特定的语言和操作系统:实现:

MongoDB 学习小笔记

1.配置:mongod --dbpath=D:\MongoDB\data mongo2.基本的增删查改 find() update()-- 整体更新,局部更新. 修改器: $inc db.person.update({"age":23},{$inc:{"salary":1000}}) 第一个参数为条件.第二个参数为修改的值,但值必须为整数.($inc allowed for numbers only) $set 修改器: db.person.update({&quo

Android学习小Demo(19)利用Loader来实时接收短信

之前写过一篇文章<Android学习小Demo(13)Android中关于ContentObserver的使用>,在里面利用ContentOberver去监测短信URI内容的变化.我们先来回顾一下,是如何利用ContentOberver来监测短信内容的变化的. 1)要自定义一个类,比如SmsContentObserver,继承ContentObserver,并且实现其onChange方法. 2)在onChange方法中去查询对应Uri,比如短信收件箱的内容,并将对应的记录利用Handler发送

C++学习,两个小的语法错误-network-programming

1.bool CServerSocket::initSocket(const char* ip=NULL,const UINT &port)://会出现默认参数为2的错误 解决方案: //C++语法规定:只要有一个默认参数,那么该参数后面的所有参数都必须指定默认值//所以将initSocket的两个参数的位置调换了一下. bool CServerSocket::initSocket(const UINT &port,const char* ip=NULL)://正确 2.出现错误:WIND