1. 首页
  2. >
  3. 技术专题
  4. >
  5. SpringBoot

springboot 项目之默认全局异常拦截

在web项目中,不可避免地会出现系统异常,例如资源找不到的404错误,服务器异常的5**错误,如果对这些异常不进行任何处理,则是非常不友好的。今天就对springboot项目中的异常拦截处理进行一个简单的使用说明。这里我使用的是springboot默认的异常拦截,也就是新建一个BasicErrorController类继承BasicErrorController。

默认异常拦截

在springboot项目中,不管是404错误还是其他错误,浏览器访问的时候,都会抛出一个非常不友好的异常,如下

springboot 项目之默认全局异常拦截

默认ajax异常

如果在客户端(非ajax)请求,则会返回一个json对象,如下

springboot 项目之默认全局异常拦截

默认非ajax异常

这样的异常是非常不友好的,接下来我们需要来对异常进行加工处理。

thymeleaf定制化页面

这里使用thymeleaf模板来新建页面。在pom中添加依赖即可。

        <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-thymeleaf</artifactId>             <version>2.4.1</version>         </dependency>

新建一个继承BaseErrorController的类

在项目下新建一个error(可任意)包,新建一个继承BaseErrorController的类。如下

springboot 项目之默认全局异常拦截

BaseErrorController目录

springboot 项目之默认全局异常拦截

自定义BaseErrorController继承代码

BaseErrorController里面有对异常进行拦截,我们可以进入到该类的源码中查看

springboot 项目之默认全局异常拦截

BaseErrorController 源码 errorHtml

springboot 项目之默认全局异常拦截

BaseErrorController 源码 error

可以看到在errorHtml()中返回了异常页面,在error()中返回了postman(非ajax)请求。

那么我们自定义的类继承该类写这两个方法,就可以实现异常的自定义拦截

package meicius.ori.error; import org.springframework.boot.autoconfigure.web.ErrorProperties; import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; import org.springframework.boot.web.servlet.error.DefaultErrorAttributes; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.servlet.ModelAndView;   import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Map;   @Controller public class MyBasicErrorController extends BasicErrorController {         public MyBasicErrorController() {         super(new DefaultErrorAttributes(), new ErrorProperties());     }       @Override     protected Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {         return super.getErrorAttributes(request, includeStackTrace);     }       @Override     public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {         ModelAndView modelAndView = super.errorHtml(request, response);         String httpStatus = modelAndView.getModel().get("status").toString();         if(httpStatus.equals("404")){             modelAndView.setViewName("/error/404");             return modelAndView;         }         Map<String, Object> stringObjectMap = getErrorAttributes(request, true);         modelAndView.addObject("stackTrace", stringObjectMap.get("trace").toString());         modelAndView.setViewName("/error/error");         return modelAndView;     }     @Override     public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {         Map<String, Object> body = getErrorAttributes(request,isIncludeStackTrace(request, MediaType.TEXT_HTML));         Map<String, Object> bodyRes = new HashMap<String, Object>();         bodyRes.put("message", "异常拦截");         bodyRes.put("data", body);         HttpStatus status = getStatus(request);         return new ResponseEntity<Map<String, Object>>(bodyRes, status);     } }

代码中重写了errorHtml() 和 error()

errorHtml()方法

在该方法中,我做了一个404错误和非404错误的判断,如果是404错误,则会返回一个定制化的页面,只有一张图片。如果是非404错误,则会返回相关的错误信息。在templates中建立error文件夹,在该文件夹下面放抛出异常的页面

error.html

<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org" layout:decorator="layout"> <head>     <title>Spring Boot ori统一异常拦截</title>     <script type="text/javascript">     </script>     <style>         *{             margin: 0;             padding: 0;         }         html, body, .container, .navbar{             height: 100%;             width: 100%;             overflow: hidden;         }         .navbar{             margin-left: 20px;         }         h1{             height: 60px;         }         h3{             height: 40px;         }         .debugDiv{             display: flex;             margin-left: 20px;             align-content: center;             margin-bottom: 20px;         }         .linkDiv{             width: 140px;             height: 60px;             margin-left: 10px;             line-height: 60px;             text-align: center;         }         .linkDiv:nth-child(1){             background-color: cornflowerblue;         }         .linkDiv:nth-child(2){             background-color: aquamarine;         }         .linkDiv:nth-child(3){             background-color: chocolate;         }         .trace{             width: 80%;             height: calc(100% - 400px);             overflow: auto !important;             border: 2px solid cornflowerblue;             padding: 5px;         }         .trace::-webkit-scrollbar{             width: 10px;         }         .trace::-webkit-scrollbar-track{             background-color: cornflowerblue;             /*-webkit-border-radius: 2em;*/             /*-moz-border-radius: 2em;*/             /*border-radius: 2em;*/         }         .trace::-webkit-scrollbar-thumb{             background-color: chocolate;             /*-webkit-border-radius: 2em;*/             /*-moz-border-radius: 2em;*/             /*border-radius: 2em;*/         }     </style> </head> <body>     <div class="container" layout:fragment="content" th:remove="tag">         <div class="navbar">             <h1 th:text="'ori 系统异常统一处理'"></h1>             <h3 th:text="'时间:'+${timestamp}"></h3>             <h3 th:text="'状态码:'+${status}"></h3>             <h3 th:text="'错误状态:'+${error}"></h3>             <h3 th:text="'地址:'+${path}"></h3>             <h3>调试</h3>             <div class="debugDiv">                   <div class="linkDiv">                     <a th:href="@{'https://www.google.com/webhp?hl=zh-CN#safe=strict&hl=zh-CN&q='+${error}}"                        class="btn btn-default btn-lg" target="_blank" id="Google">Google</a>                 </div>                   <div class="linkDiv">                     <a th:href="@{'https://www.baidu.com/s?wd='+${error}}"                        class="btn btn-default btn-lg" target="_blank" id="Baidu">Baidu</a>                 </div>                   <div class="linkDiv">                     <a th:href="@{'http://stackoverflow.com/search?q='+${error}}"                        class="btn btn-default btn-lg"  target="_blank" id="StackOverFlow">StackOverFlow</a>                 </div>             </div>               <h3>异常堆栈跟踪日志StackTrace</h3>             <div class="trace" th:each="line:${stackTrace}">                 <div th:text="${line}"></div>             </div>         </div>     </div> </body> </html>

404页面

<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org" layout:decorator="layout"> <head>     <title>Spring Boot ori统一异常拦截</title>     <script type="text/javascript">     </script>     <style>         *{             margin: 0;             padding: 0;         }         html, body, .container{             height: 100%;             width: 100%;             overflow: hidden;         }         img{             height: 100%;             width: 100%;         }      </style> </head> <body>     <div class="container">         <img src="/404.png"/>     </div> </body> </html>

其中404.html页面引入了一张图片,图片放在static下面。整个目录如下

springboot 项目之默认全局异常拦截

页面目录

这样就完成了ajax请求的异常拦截

springboot 项目之默认全局异常拦截

自定义ajax拦截

springboot 项目之默认全局异常拦截

自定义ajax拦截

error()

error()方法里面是对非ajax请求的处理,例如使用postman请求

springboot 项目之默认全局异常拦截

自定义非ajax请求

至此,springboot默认全局异常处理就完成了。这种方式不仅可以获取到异常的接口路径、错误状态、错误代码、还可以获取到堆栈日志等信息。

java初探Tess4j识别图片文字
« 上一篇 2021年01月13日 pm20:20
架构解密从分布式到微服务:深入理解网络,NIO
下一篇 » 2021年01月13日 pm20:37

相关推荐