zoukankan      html  css  js  c++  java
  • SpringBoot全局异常处理

    在SpringMVC中可以使用ControllerAdvice来做controller内部的全局异常处理,但对于未进入controller前的异常,该处理方法是无法进行捕获处理的,SpringBoot提供了ErrorController的处理类来处理所有的异常。

     

    20190530补充:

    springboot提供了/error的错误管理端点和默认的BasicErrorController实现类,但这个Controller实现类其实不一定符合我们的需求,所以我们才需要来覆盖这个默认实现。

    其中:BasicErrorController extend AbstractErrorController ,AbstractErrorController  又 implements ErrorController。

    下面的类是直接实现了ErrorController,其实我们也可以仿照BasicErrorController来继承AbstractErrorController减少一些代码的编写。

      1 import java.util.Map;
      2 
      3 import javax.servlet.http.HttpServletRequest;
      4 
      5 import org.springframework.beans.factory.annotation.Autowired;
      6 import org.springframework.boot.autoconfigure.web.ErrorAttributes;
      7 import org.springframework.boot.autoconfigure.web.ErrorController;
      8 import org.springframework.http.HttpStatus;
      9 import org.springframework.web.bind.annotation.RequestMapping;
     10 import org.springframework.web.bind.annotation.ResponseStatus;
     11 import org.springframework.web.bind.annotation.RestController;
     12 import org.springframework.web.context.request.RequestAttributes;
     13 import org.springframework.web.context.request.ServletRequestAttributes;
     14 
     15 import com.tomato.boss.common.base.ResponseResult;
     16 
     17 import lombok.extern.slf4j.Slf4j;
     18 import springfox.documentation.annotations.ApiIgnore;
     19 
     20 /**
     21  * 全局异常处理,当异常被@ControllerAdvice时不会走到这个处理类,没被处理时会走到这里
     22  * 例如 @valid入参校验失败的是不会走ControllerAdvice的,但会走这个处理器
     23  * @author yangzhilong
     24  *
     25  */
     26 @RestController
     27 @ApiIgnore
     28 @Slf4j
     29 public class GolablExceptionEndpoint implements ErrorController{
     30     
     31     private static final String PATH = "/error";
     32     
     33     @Autowired
     34     private ErrorAttributes errorAttributes;
     35 
     36     @Override
     37     public String getErrorPath() {
     38         return PATH;
     39     }
     40     
     41     /**
     42      * 全局异常处理
     43      * 增加@ResponseStatus注解将非200的http状态码转成200
     44      * @return
     45      */
     46     @RequestMapping(value = PATH)
     47     @ResponseStatus(code=HttpStatus.OK)
     48     public ResponseResult<Object> error(HttpServletRequest request) {
     49         return handlerError(request, false);
     50     }
     51     
     52     /**
     53      * 具体的处理
     54      * @param request
     55      * @param includeStackTrace
     56      * @return
     57      */
     58     private ResponseResult<Object> handlerError(HttpServletRequest request, boolean includeStackTrace) {
     59         RequestAttributes requestAttributes = new ServletRequestAttributes(request);
     60         Throwable e = errorAttributes.getError(requestAttributes);
     61         
     62         Map<String, Object> data = errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace);
     63         
     64         String message = null;
     65         StringBuilder detailMessage = new StringBuilder("");
     66         
     67         HttpStatus status = getStatus(request);
     68         if(status == HttpStatus.BAD_REQUEST) {
     69             log.error("参数校验失败", e);
     70             message = "请检查数据填写是否合法";
     71         } else if(status == HttpStatus.INTERNAL_SERVER_ERROR) {
     72             log.error("系统错误", e);
     73             message = "系统繁忙";
     74         } else if(status == HttpStatus.NOT_FOUND) {
     75             log.error("404错误");
     76             message = "服务或者页面不存在";
     77         } else {
     78             log.error("系统错误", e);
     79             message = "系统出错,未知错误";
     80         }
     81         if(null != data.get("error")) {
     82             detailMessage.append(String.valueOf(data.get("error"))).append(":");
     83         }
     84         if(null == e || null == e.getMessage()) {
     85             if(null != data.get("message")) {
     86                 detailMessage.append(String.valueOf(data.get("message")));
     87             }
     88         } else {
     89             detailMessage.append(e.getMessage());
     90         }
     91         
     92         return ResponseResult.buildFailResponse(String.valueOf(data.get("status")), message, detailMessage.toString());
     93     }
     94     
     95     /**
     96      * 获取错误编码
     97      * @param request
     98      * @return
     99      */
    100     private HttpStatus getStatus(HttpServletRequest request) {
    101         Integer statusCode = (Integer) request
    102                 .getAttribute("javax.servlet.error.status_code");
    103         if (statusCode == null) {
    104             return HttpStatus.INTERNAL_SERVER_ERROR;
    105         }
    106         try {
    107             return HttpStatus.valueOf(statusCode);
    108         }
    109         catch (Exception ex) {
    110             return HttpStatus.INTERNAL_SERVER_ERROR;
    111         }
    112     }
    113 }
  • 相关阅读:
    node-webkit 不支持html5_video播放mp4的解决方法
    node-webkit(Windows系统) 打包成exe文件后,被360杀毒软件误报木马的解决方法
    剑指 Offer 36. 二叉搜索树与双向链表
    剑指 Offer 33. 二叉搜索树的后序遍历序列
    Leetcode96. 不同的二叉搜索树
    Leetcode95. 不同的二叉搜索树 II
    leetcode1493. 删掉一个元素以后全为 1 的最长子数组
    Leetcode1052. 爱生气的书店老板
    Leetcode92. 反转链表 II
    Leetcode495. 提莫攻击
  • 原文地址:https://www.cnblogs.com/yangzhilong/p/7904665.html
Copyright © 2011-2022 走看看