多平台统一管理软件接口,如何实现多平台统一管理软件接口
252
2022-11-27
SpringBoot2.3定制错误页面的方法示例
一. 问题背景
后台: SpringBoot 2.3.1(官方2.3版本修改了很多,抛弃了很多以前能用的方法)
前端: Layui(前端用哪个框架问题不大)
技术: SpringBoot+Thymeleaf+Layui
情况:我想将Layui提供好的错误页面作为SpringBoot默认的错误页面,而且Layui提供的错误页面位置并不是放在/静态资源文件夹/error,而是在如下:
二. SpringBoot的错误页面机制
错误页面机制的原理详情可以看Day41——错误处理原理&定制错误页面以及Day42——定制错误数据。
首先要知道SpringBoot的错误页面机制原理自动配置是由ErrorMvcAutoConfiguration配置的。所以定制错误页面的解决方案都可以参考ErrorMvcAutoConfiguration类以及参考他人博客。
这里只做简单的回顾,如下:
三. 定制错误页面
首先我项目里面在application.properties配置了静态资源路径为classpath:/templates/layuimini/,如下:
#自定义静态资源路径
spring.resources.static-locations=classpath:/templates/layuimini/
大家根据需要自行调整自己项目里面的静态资源路径,后面的定制错误页面的路径会根据这个配置好的路径去寻找,或者拼串。
3.1 方案一(最简单的,但是不推荐)
3.1.1 步骤
最简单是 在静态资源文件夹下面创建一个error文件夹,在里面放置自己的错误页面,如下:
不推荐的原因是,我当前的目录结构是所有的页面都是放在/templates/layuimini/page/文件夹下面的,如果按照上面做法,会破坏我的目录结构,后期维护很困难。
3.1.2 原理
在BasicErrorController中,封装视图的时候,当前项目如果有模板引擎,会先用模板引擎解析,找不到再去静态资源文件夹寻找视图(视图名是error/状态码.html,这是指error文件夹下的状态码.html文件,这是由私有方法实现的,所以外部无法修改)。因此上面的步骤就是SpringBoot先去templates文件夹下找,找不到,再去/templates/layuimini/这个静态资源文件夹找(前提是你设置了静态资源文件夹;否则默认按SpringBoot的默认静态资源文件夹找,比如resources、public、static、resource)
3.2 方案二(不能实现自适应定制错误页面,不推荐)
3.2.1 步骤
首先放置好自定义的错误页面,是在/templates/layuimini/page/error/,如下:
然后再创建一个MyErrorPageConfig类,最最最关键的是new ErrorPage()中第二个入参,如果是加了.html,那么就会直接找页面,如果没有加,那么将它当作请求去找controller,如下:
@Configuration
public class MyErrorPageConfig {
@Bean
public WebServerFactoryCustomizer
return new WebServerFactoryCustomizer
@Override
public void customize(ConfigurableWebServerFactory factory) {
ErrorPage errorPage1 = new ErrorPage(HttpStatus.NOT_FOUND, "/page/error/4xx.html");
ErrorPage errorPage2 = new ErrorPage(HttpStatus.NOT_FOUND, "/page/error/5xx.html");
factory.addErrorPages(errorPage1, errorPage2);
}
};
}
}
3.2.2 原理
详情可以参考Day46——SpringBoot2.x版本的嵌入式Servlet容器自动配置原理以及Day47——嵌入式Servlet容器启动原理
首先要知道SpringBoot2.x版本的嵌入式Servlet容器是由ServletWebServerFactoryAutoConfiguration类配置的。一切的配置信息以及解决方案都可以参考这个类。
这里只做简单解释,如下:
这样它就会执行上面步骤中的customize()方法中的方法
3.3 方案三(实现自适应)
自适应就是根据发送的/error请求是浏览器还是客户端,使用不同的controller方法进行处理,并返回不同类型的数据
3.3.1 步骤
创建一个实现了ErrorController接口的MyBasicErrorController类,如下:
/**
* 定制ErrorController,目的是能使SpringBoot找到自己定制的错误页面
* 大部分的代码BasicController一致,关键点是修改错误页面的路径
*/
@Controller
@RequestMapping(value = "/error")
public class MyBasicErrorController http://implements ErrorController {
@RequestMapping(produces = {"text/html"})//返回给浏览器
public String handlerError(HttpServletRequest request, Model model){
WebRequest webRequest = new ServletWebRequest(request);//对request进行包装,目的是能操作更多的方法
HttpStatus status = this.getStatus(request);//获取status
String path = (StringISVqu) webRequest.getAttribute("javax.servlet.error.request_uri", 0);
String message = (String) webRequest.getAttribute("javax.servlet.error.message", 0);
if(message.equals("")){
message = "No Available Message";
}
//携带错误数据信息
model.addAttribute("timestamp", new Date());
model.addAttribute("statusCode", status.value());
model.addAttribute("error", status.getReasonPhrase());
model.addAttribute("message", message);
model.addAttribute("path", path);
int i = status.value() / 100;//判断是4xx还是5xx错误
if(i == 4){
return "layuimini/page/error/4xx";//使用自己定制的错误页面
}else if(i == 5){
return "layuimini/page/error/5xx";//使用自己定制的错误页面
}
return null;
}
@RequestMapping//返回给客户端
public ResponseEntity
WebRequest webRequest = new ServletWebRequest(request);//对request进行包装,目的是能操作更多的方法
HttpStatus status = this.getStatus(request);//获取status
Map
if (status == HttpStatus.NO_CONTENT) {
return new ResponseEntity(status);
} else {
String path = (String) webRequest.getAttribute("javax.servlet.error.request_uri", 0);
String message = (String) webRequest.getAttribute("javax.servlet.error.message", 0);
map.put("timestamp", new Date());
map.put("statusCode", status.value());
map.put("error", status.getReasonPhrase());
map.put("message", message);
map.put("path", path);
return new ResponseEntity(map, status);
}
}
protected HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
} else {
try {
return HttpStatus.valueOf(statusCode);
} catch (Exception var4) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
}
}
@Override
public String getErrorPath() {
return "null";
}
}
3.3.2 原理
SpringBoot的错误页面机制的自适应,是由BasicErrorController实现的,而这个BasicErrorController只有在容器中没有ErrorController的情况下,才会被注册进容器,因此我们创建一个实现了ErrorController接口的类,这个BasicErrorController就失效,然后我们仿照BasicErrorController里面的方法来实现自己的controller就可以了。如下:
@Bean
@ConditionalOnMissingBean(
value = {ErrorController.class},//没有ErrorController才会去注册BasicErrorController
search = SearchStrategy.CURRENT
)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes, ObjectProvider
return new BasicErrorController(errorAttributes, this.serverProperties.getError(), (List)errorViewResolvers.orderedStream().collect(Collectors.toList()));
}
上面实现步骤中的一些错误数据是参照DefaultErrorAttributes中的方法实现的
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~