Springboot 錯誤處理機制

SpringBoot默認的錯誤處理機制

即咱們常見的白色的ErrorPage頁面html

瀏覽器發送的請求頭:java

若是是其餘的請求方式,好比客戶端,則相應一個json數據:web

 原理;是經過 ErrorMvcAutoConfiguration,錯誤處理的自動配置;spring

給容器中添加了如下組件json

一、DefaultErrorAttributes:瀏覽器

幫咱們在頁面共享信息;
@Override
    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes,
            boolean includeStackTrace) {
        Map<String, Object> errorAttributes = new LinkedHashMap<String, Object>();
        errorAttributes.put("timestamp", new Date());
        addStatus(errorAttributes, requestAttributes);
        addErrorDetails(errorAttributes, requestAttributes, includeStackTrace);
        addPath(errorAttributes, requestAttributes);
        return errorAttributes;
    }

 二、BasicErrorController:處理默認/error請求 app

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
    
    @RequestMapping(produces = "text/html")//產生html類型的數據;瀏覽器發送的請求來到這個方法處理
    public ModelAndView errorHtml(HttpServletRequest request,
            HttpServletResponse response) {
        HttpStatus status = getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
                request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
        
        //去哪一個頁面做爲錯誤頁面;包含頁面地址和頁面內容
        ModelAndView modelAndView = resolveErrorView(request, response, status, model);
        return (modelAndView == null ? new ModelAndView("error", model) : modelAndView);
    }

    @RequestMapping
    @ResponseBody    //產生json數據,其餘客戶端來到這個方法處理;
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = getStatus(request);
        return new ResponseEntity<Map<String, Object>>(body, status);
    }

 三、ErrorPageCustomizer:ide

@Value("${error.path:/error}")
    private String path = "/error";  系統出現錯誤之後來到error請求進行處理;(web.xml註冊的錯誤頁面規則)

 四、DefaultErrorViewResolver:this

@Override
    public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status,
            Map<String, Object> model) {
        ModelAndView modelAndView = resolve(String.valueOf(status), model);
        if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
            modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
        }
        return modelAndView;
    }

    private ModelAndView resolve(String viewName, Map<String, Object> model) {
        //默認SpringBoot能夠去找到一個頁面?  error/404
        String errorViewName = "error/" + viewName;
        
        //模板引擎能夠解析這個頁面地址就用模板引擎解析
        TemplateAvailabilityProvider provider = this.templateAvailabilityProviders
                .getProvider(errorViewName, this.applicationContext);
        if (provider != null) {
            //模板引擎可用的狀況下返回到errorViewName指定的視圖地址
            return new ModelAndView(errorViewName, model);
        }
        //模板引擎不可用,就在靜態資源文件夾下找errorViewName對應的頁面   error/404.html
        return resolveResource(errorViewName, model);
    }

​ 一但系統出現4xx或者5xx之類的錯誤;ErrorPageCustomizer就會生效(定製錯誤的響應規則);就會來到/error請求;就會被BasicErrorController處理;spa

 1)響應頁面;去哪一個頁面是由DefaultErrorViewResolver解析獲得的;

protected ModelAndView resolveErrorView(HttpServletRequest request,
      HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
    //全部的ErrorViewResolver獲得ModelAndView
   for (ErrorViewResolver resolver : this.errorViewResolvers) {
      ModelAndView modelAndView = resolver.resolveErrorView(request, status, model);
      if (modelAndView != null) {
         return modelAndView;
      }
   }
   return null;
}

2)、如何定製錯誤響應:

  如何定製錯誤的頁面

1)、有模板引擎的狀況下;error/狀態碼; 【將錯誤頁面命名爲 錯誤狀態碼.html 放在模板引擎文件夾裏面的 error文件夾下】,發生此狀態碼的錯誤就會來到 對應的頁面;

​ 咱們可使用4xx和5xx做爲錯誤頁面的文件名來匹配這種類型的全部錯誤,精確優先(優先尋找精確的狀態碼.html);

​ 頁面能獲取的信息;

​ timestamp:時間戳

​ status:狀態碼

​ error:錯誤提示

​ exception:異常對象

​ message:異常消息

​ errors:JSR303數據校驗的錯誤都在這裏

​ 2)、沒有模板引擎(模板引擎找不到這個錯誤頁面),靜態資源文件夾下找;

​ 3)、以上都沒有錯誤頁面,就是默認來到SpringBoot默認的錯誤提示頁面;

如何定製錯誤的json數據;

Controller.MyExceptionHandler

package com.project.javasystem.Controller;

import com.project.javasystem.exception.UserNotExistException;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class MyExceptionHandler {

  //方法一:
    //瀏覽器,客戶端都返回的是Json數據
   /* @ResponseBody//響應json數據
    @ExceptionHandler(UserNotExistException.class)
    public Map<String,Object> handleException(Exception e){
        Map<String,Object>map = new HashMap<>();
        map.put("code:","User.notExit");
        map.put("message:",e.getMessage());
        return map;
    }*/

  //方法二:自適應效果
    @ExceptionHandler(UserNotExistException.class)
    public String handleException(Exception e,HttpServletRequest request){
        Map<String,Object>map = new HashMap<>();
        //傳入自定義的狀態碼
        /*Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");*/
        request.setAttribute("javax.servlet.error.status_code",500);
        map.put("code:","User.NotExit");
        map.put("message:","用戶出錯啦");
        //轉發到error進行自適應處理
        request.setAttribute("MyError",map);
        //轉發到error
        return "forward:/error";
    }
}

 

3)、將咱們的定製數據攜帶出去;

出現錯誤之後,會來到/error請求,會被BasicErrorController處理,響應出去能夠獲取的數據是由getErrorAttributes獲得的(是AbstractErrorController(ErrorController)規定的方法);

​ 一、徹底來編寫一個ErrorController的實現類【或者是編寫AbstractErrorController的子類】,放在容器中;

​ 二、頁面上能用的數據,或者是json返回能用的數據都是經過errorAttributes.getErrorAttributes獲得;

​ 容器中DefaultErrorAttributes.getErrorAttributes();默認進行數據處理的;

自定義ErrorAttributes

Component.MyErrorAttributes

package com.project.javasystem.Component;

import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
import java.util.Map;


@Component
public class MyErrorAttributes  extends DefaultErrorAttributes {

    //返回值 map中就是頁面和json能獲取的全部字段
    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
        Map<String, Object> map = super.getErrorAttributes(webRequest,includeStackTrace);
        map.put("CompanyName","517NA");
        // 異常處理器攜帶的數據
        Map<String,Object>MyError = (Map<String, Object>) webRequest.getAttribute("MyError", 0);
        map.put("MyError",MyError);
        return map;
    }
}

 

最終的效果:響應是自適應的,能夠經過定製ErrorAttributes改變須要返回的內容,

相關文章
相關標籤/搜索