在Spring Boot项目中,可能大家都会碰到如下页面:
当我们系统出错或者访问地址不正确时就会这个页面,这个页面是Spring Boot自带的白色错误页面
当然这个不是我们想要的,如果我们把这个展示给用户看,用户也会一脸懵,看不懂,那么我们既要页面美观,不是一堆看不懂的英文,也要让用户明确的知道是什么问题
接下来我们就去Spring Boot 官方文档去看看如何解决。
进入到Spring Boot官方文档中,我们找到Customize the ‘whitelabel’ Error Page(自定义白板错误页面),点击进入
文档中第一段给我们介绍了当我们服务出错后就会显示SpringBoot自带的whitelabel错误页面,第二段告诉我们可以在application.properties中配置server.error.whitelabel.enabled=false来关闭SpringBoot中自带的错误页面,当然我们也可以使用模板技术来覆盖自带的错误页面,如果使用Thymeleaf模板需要新建一个error.html模板,如果使用FreeMarker,需要定义error.ftl模板,一般来说需要定义一个Controller来处理/error路径,除非使用配置类替换默认配置,这两种方式都是可以的。详细处理可以参照“Error Handing”
1.创建一个thymeleaf的error.html页面
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<!-- 踩过的坑,springboot引入静态资源路径不要加/static/,否则会报404-->
<title>出错了</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="/bootstrap-3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/community.css">
<link rel="stylesheet" href="//at.alicdn.com/t/font_1643567_rm1fqucxtan.css">
<link rel="stylesheet" href="/bootstrap-3.3.7/css/bootstrap-theme.min.css">
<script src="/jquery-1.12.4/jquery-1.12.4.min.js"></script>
<script src="/bootstrap-3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div th:replace="navigation :: nav"></div>
<div class="jumbotron">
<h1>哎呀,出错了!</h1>
<h3 th:text="${errorMsg}"></h3>
<p><a class="btn btn-primary btn-lg" href="/" role="button">回到首页</a></p>
</div>
</body>
</html>
2.创建一个Controller实现ErrorController,添加一个具有@ProductMapping且具有Produces属性的公共方法,这里我们的Produces类型是text/html
CustomizeErrorController.java 用于页面跳转,请求服务报错
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class CustomizeErrorController implements ErrorController {
@Override
public String getErrorPath() {
return "error";
}
//处理text/html类型页面异常
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView errorHtml(HttpServletRequest request, Model model) {
HttpStatus status = getStatus(request);
//如果状态码是4xx,请求出现问题
if (status.is4xxClientError()) {
model.addAttribute("errorMsg", "请求出错,要不然换个姿势?");
}
//如果状态码是5xx,服务器异常
if (status.is5xxServerError()) {
model.addAttribute("errorMsg", "服务器出错了,请稍后再试!!!");
}
return new ModelAndView("error");
}
//获取请求信息
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request
.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
try {
return HttpStatus.valueOf(statusCode);
} catch (Exception ex) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
}
}
3.创建一个类,并添加@ControllerAdvice注解,这个类可以用来处理自定义JSON或者异常类型返回,将返回的结果显示在error.html页面上
CustomizeErrorAdvice.java
//处理JSON数据或者服务异常报错,并返回显示到前端
@ControllerAdvice
public class CustomizeErrorAdvice {
//拦截所有异常并处理
@ExceptionHandler(Exception.class)
ModelAndView handle(HttpServletRequest request, Throwable e, Model model) {
//如果异常类型为自定义异常
if(e instanceof CustomizeException){
model.addAttribute("errorMsg",e.getMessage());
}else{
//其他异常
model.addAttribute("errorMsg","服务器出错了,过一会再试试吧");
}
return new ModelAndView("error");
}
}
需要编写一个异常处理类,用于填写异常信息
CustomizeException.java
public class CustomizeException extends RuntimeException {
private String message;
public CustomizeException(CustomizeErrorCode errorCode) {
this.message = errorCode.getMessage();
}
@Override
public String getMessage() {
return message;
}
}
创建一个异常信息枚举类,用于常用异常常量编写
CustomizeErrorCode.java
public enum CustomizeErrorCode{
SYS_ERROR("服务器出错了,过一会再试试吧"),
FILE_NOT_FIND("您要找的资源不存在或者被删除了,您可以查看其他文章"),
;
private String message;
CustomizeErrorCode(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
在可能出现异常的地方将异常抛出,部分代码如下
@GetMapping("/article/detail/{id}")
public String articleDetails(@PathVariable(name = "id") long id,
Model model){
Article article = articleService.selectArticleById(id);
//没有找到对应的文章信息,将异常抛出
if(article==null){
throw new CustomizeException(CustomizeErrorCode.FILE_NOT_FIND);
}
model.addAttribute("ArticleDetail",article);
return "articleDetail";
}