springboot(11)——异常处理和自定义错误页面
1.异常来源
要处理程序发生的异常,首先需要知道异常来自哪里?
1.前端错误的的请求路径,会使得程序发生4xx错误,最常见的就是404,springboot默认当发生这种错误的请求路径,pc端响应的页面如下
如果是移动端(手机端)将会响应json格式的数据,如下
2.springboot异常处理原理
为什么我们请求错误的路径,boot会给我们返回一个上面错误页面或者json格式数据呢?原理是怎样的呢?
springboot项目启动之后,执行有@springbootapplication注解的启动类的main方法,通过@enableautoconfiguration加载
springbootautoconfiguration.jar包下的meta-inf/spring.factories中的所有配置类(这些配置类加载之后,会将每个配置类里面的组件注入容器然后使用)其中一个自动配置
errormvcautoconfiguration,通过代码可以看到用到了以下四个组件
defaulterrorattributes、basicerrorcontroller、errorpagecustomizer、defaulterrorviewresolver
其他三个基本类似,当出现4xx或者5xx等错误时,errorpagecustomizer就会生效,this.properties.geterror().getpath())并来到/error请求,核心代码
而这个/error请求再由basicerrorcontroller处理,basicerrorcontroller是一个controller,其中里面有两种处理方法,一种是html形式,
一种是json格式。其中访问者的信息可以从geterrorattributes从获取。defaulterrorattributes是errorattributes的实现类。
关键代码
当为html模式时,就会构建一个resolveerrorview类,而resolvererrorview继续调用errorviewresolver。关键代码
在我们没有做自定义配置时,errorviewresolver就会指向defaulterrorviewresolver。
3.如何定制错误、异常响应
明白了boot处理异常机制,我们如何自定义异常响应规则呢?
第一种:pc端返回静态错误页面,手机端返回boot默认的json数据
如果项目中有模板引擎(jsp,thmeleaf,freemarker)的情况下,可以将错误页面命名为状态码.html放在模板引擎文件夹下的error文件夹下,
发生异常,不管是前端请求还是后端程序错误会来到对应的错误页面。可以将错误页面命名为4xx和5xx匹配所有的错误,
但是优先返回精确状态码.html页面;并且在模板引擎页面可以获取如下相关信息
这里模版引擎使用thmeleaf
4xx代码
我们在程序代码中人为制造一个异常,请求响应
上面是有模版引擎的情况下处理错误以及异常的方式,
如果项目中没有模板引擎,(模板引擎找不到这个错误页面),静态资源文件夹static下找对应的4xx或者5xx或者更精确的错误页面。但是如果不用模板引擎,页面不能获取上面说的页面信息;
上面两种方式使用手机访问返回都是boot默认的json数据
第二种:pc端返回动态的页面 ,手机端返回动态json数据
上面第一种可以轻松的的处理异常,只需在指定的路径下放静态页面(无模版引擎的情况)或者携带相关信息的页面(有模版引擎),
缺点就是不能在页面携带我们想要展示的数据,比如当我们程序某处放生异常,我们要返回我们自己提示的错误信息。这种异常如果处理呢?
默认情况下,在 spring boot 中,所有的异常数据其实就是第一种所展示出来的 5几条数据,这些数据定义在 org.springframework.boot.web.reactive.error.defaulterrorattributes 类中,具体定义在 geterrorattributes 方法中 :核心代码如下
defaulterrorattributes 类本身则是在 org.springframework.boot.autoconfigure.web.servlet.error.errormvcautoconfiguration 异常自动配置类中定义的,
如果开发者没有自己提供一个 errorattributes 的实例的话,那么 spring boot 将自动提供一个 errorattributes 的实例,也就是 defaulterrorattributes 。
基于此 ,开发者自定义 errorattributes 有两种方式 实现自定义数据:
1.直接实现 errorattributes 接口
2.继承 defaulterrorattributes(推荐),因为 defaulterrorattributes 中对异常数据的处理已经完成,开发者可以直接使用。
我们服务器访问 错误路径
客户端响应
访问有异常的的控制器
客户端响应
当然上面我可以在程序任意位置抛出异常,使用全局异常处理器处理
自定义异常
全局异常处理器
自定义errorattributes
第三种:pc端返回动态json数据,手机端也返回动态json数据
这种方式主要是针对前后端分离的项目,我们自定义一个异常,在程序中用于抛出
定义一个返回结果对象(也可以不用定义,直接使用map)存储异常信息
定义一个全局异常处理器