在SpringMVC中能夠使用ControllerAdvice來作controller內部的全局異常處理,但對於未進入controller前的異常,該處理方法是沒法進行捕獲處理的,SpringBoot提供了ErrorController的處理類來處理全部的異常。java
20190530補充:web
springboot提供了/error的錯誤管理端點和默認的BasicErrorController實現類,但這個Controller實現類其實不必定符合咱們的需求,因此咱們才須要來覆蓋這個默認實現。spring
其中:BasicErrorController extend AbstractErrorController ,AbstractErrorController 又 implements ErrorController。springboot
下面的類是直接實現了ErrorController,其實咱們也能夠仿照BasicErrorController來繼承AbstractErrorController減小一些代碼的編寫。app
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 }