1. 程式人生 > >14、SpringBoot-CRUD錯誤處理機制(1)

14、SpringBoot-CRUD錯誤處理機制(1)

ESS cep contex edi ide str provider boot wid

一、springboot默認的處理機制

1.瀏覽器返回一個錯誤的頁面 默認處理錯誤:返回一個錯誤的頁面: 包括錯誤類型、時間......

技術分享圖片

技術分享圖片

2.其他客戶端訪問 默認響應一個json數據

技術分享圖片

技術分享圖片

原理:

錯誤自動配置的類:ErrorMvcAutoConfiguration.java

技術分享圖片

技術分享圖片

技術分享圖片

默認配置:

@Bean
@ConditionalOnMissingBean(
    value = {ErrorAttributes.class},
    search = SearchStrategy.CURRENT
)
public DefaultErrorAttributes errorAttributes() {
    
return new DefaultErrorAttributes(this.serverProperties.getError().isIncludeException()); } @Bean @ConditionalOnMissingBean( value = {ErrorController.class}, search = SearchStrategy.CURRENT ) public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) { return new
BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers); } @Bean public ErrorMvcAutoConfiguration.ErrorPageCustomizer errorPageCustomizer() { return new ErrorMvcAutoConfiguration.ErrorPageCustomizer(this.serverProperties, this.dispatcherServletPath); } @Bean @ConditionalOnBean({DispatcherServlet.
class}) @ConditionalOnMissingBean public DefaultErrorViewResolver conventionErrorViewResolver() { return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties); }

1、DefaultErrorAttributes:

在頁面共享信息
public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
    Map<String, Object> errorAttributes = new LinkedHashMap();
    errorAttributes.put("timestamp", new Date());
    errorAttributes.put("path", request.path());
    Throwable error = this.getError(request);
    HttpStatus errorStatus = this.determineHttpStatus(error);
    errorAttributes.put("status", errorStatus.value());
    errorAttributes.put("error", errorStatus.getReasonPhrase());
    errorAttributes.put("message", this.determineMessage(error));
    this.handleException(errorAttributes, this.determineException(error), includeStackTrace);
    return errorAttributes;
}

2、BasicErrorController:處理默認/error請求

@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 = this.getStatus(request);
    Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
    response.setStatus(status.value());
    
    //去哪個頁面作為錯誤頁面,包含頁面地址和頁面內容
    ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
    return modelAndView != null ? modelAndView : new ModelAndView("error", model);
}

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

3、ErrorPageCustomizer:

public class ErrorProperties {
@Value("${error.path:/error}")
private String path = "/error";
public String getPath() {
    return this.path;
}
...
}

4、DefaultErrorViewResolver:

public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
    ModelAndView modelAndView = this.resolve(String.valueOf(status.value()), model);
    if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
        modelAndView = this.resolve((String)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);
    ///模板引擎不可用,就在靜態資源文件夾下找errorViewName對應的頁面
    return provider != null ? new ModelAndView(errorViewName, model) :
 this.resolveResource(errorViewName, model);
}

步驟:

一但系統出現4xx或者5xx之類的錯誤;ErrorPageCustomizer就會生效(定制錯誤的響應規則); 就會來到/error請求,就會被BasicErrorController進行處理 1)響應頁面(resolveErrorView方法)去那個頁面是由DefaultErrorViewResolver解析得到的
protected ModelAndView resolveErrorView(HttpServletRequest request, 
HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
    //所有的ErrorViewResolver得到ModelAndView
    Iterator var5 = this.errorViewResolvers.iterator();
    ModelAndView modelAndView;
    do {
        if (!var5.hasNext()) {
            return null;
        }
        ErrorViewResolver resolver = (ErrorViewResolver)var5.next();
        modelAndView = resolver.resolveErrorView(request, status, model);
    } while(modelAndView == null);
    return modelAndView;
}

14、SpringBoot-CRUD錯誤處理機制(1)