亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

如果在請求映射期間發生異常或從請求處理程序(例如@Controller)拋出異常,DispatcherServlet將委托給HandlerExceptionResolver bean鏈來解決異常并提供替代處理,這通常是一個錯誤響應。

概述

如果在請求映射期間發生異常或從請求處理程序(例如@Controller)拋出異常,DispatcherServlet將委托給HandlerExceptionResolver

下表列出了可用的HandlerExceptionResolver實現:

HandlerExceptionResolver

描述

SimpleMAppingExceptionResolver

異常類名和錯誤視圖名之間的映射。用于在瀏覽器應用程序中渲染錯誤頁面。

DefaultHandlerExceptionResolver

解析Spring MVC引發的異常,并將其映射為HTTP狀態碼。另見可選的ResponseEntityExceptionHandler和REST API異常。

ResponseStatusExceptionResolver

使用@ResponseStatus注解解析異常,并根據注解中的值將異常映射為HTTP狀態碼。

ExceptionHandlerExceptionResolver

通過在@Controller或@ControllerAdvice類中調用@ExceptionHandler方法來解決異常。

異常解析器鏈

你可以在Spring配置中聲明多個HandlerExceptionResolver

HandlerExceptionResolver的約定規定它可以返回:

  • 指向錯誤視圖的ModelAndView
  • 如果異常是在解析器中處理的,則返回空的ModelAndView
  • 如果異常仍然未解決,則為null,以便后續的解析器嘗試,如果異常在最后仍然存在,則允許它向上冒泡到Servlet容器。

MVC配置自動為默認的Spring MVC異常、@ResponseStatus注解的異常以及@ExceptionHandler方法聲明了內置的解析器。

容器錯誤頁配置

如果任何HandlerExceptionResolver都無法解決異常,因此需要傳播,或者響應狀態被設置為錯誤狀態(即4xx、5xx), Servlet容器可以在html中渲染一個默認的錯誤頁面。要定制容器的默認錯誤頁面,可以在web.xml中聲明錯誤頁面映射。如下面的例子所示:?

 
<error-page>
  <location>/error</location>
</error-page>

根據前面的示例,當出現異常冒泡或響應具有錯誤狀態時,Servlet容器將在容器中向配置的URL(例如/error)發送錯誤。然后由DispatcherServlet處理,可能會將其映射到一個@Controller,這個@Controller可以實現為返回一個帶有模型的錯誤視圖名稱,或者渲染一個JSON響應,如下面的例子所示:?

 
@RestController
public class ErrorController {


  @RequestMapping(path = "/error")
  public Map<String, Object> handle(HttpServletRequest request) {
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("status", request.getAttribute("JAVAx.servlet.error.status_code"));
    map.put("reason", request.getAttribute("javax.servlet.error.message"));
    return map;
  }
}

錯誤處理原理

 
public class DispatcherServlet {
  // 取得容器中所有的異常解析器
  private List<HandlerExceptionResolver> handlerExceptionResolvers;
  protected void initStrategies(ApplicationContext context) {
    // 初始化異常解析器
    initHandlerExceptionResolvers(context);
  }
  private void initHandlerExceptionResolvers(ApplicationContext context) {
    this.handlerExceptionResolvers = null;
    if (this.detectAllHandlerExceptionResolvers) {
      // 獲取容器中所有的異常解析器
      Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
      if (!matchingBeans.isEmpty()) {
        this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());
        AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);
      }
    }
  }
}
 

發生異常后邏輯處理?

public class DispatcherServlet {
  protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
  }
  private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, 
    @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, 
    @Nullable Exception exception) throws Exception {


    boolean errorView = false;
    // 判斷當前調用是否發生了異常
    if (exception != null) {
      if (exception instanceof ModelAndViewDefiningException) {
        mv = ((ModelAndViewDefiningException) exception).getModelAndView();
      } else {
        // 獲取當前處理句柄HandlerMethod
        Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
        // 處理異常
        mv = processHandlerException(request, response, handler, exception);
        errorView = (mv != null);
      }
    }
    if (mv != null && !mv.wasCleared()) {
      render(mv, request, response);
    }
  }
  protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, 
    @Nullable Object handler, Exception ex) throws Exception {
    request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
    ModelAndView exMv = null;
    if (this.handlerExceptionResolvers != null) {
      // 遍歷在上面初始化查找到的所有異常解析器
      for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
        // 執行異常解析
        exMv = resolver.resolveException(request, response, handler, ex);
        if (exMv != null) {
          break;
        }
      }
    }
    if (exMv != null) {
      // ...
      return exMv ;
    }
    // 如果所有的異常解析器都返回null,則直接拋出異常,該異常會被Servlet進行處理
    throw ex ;
  }
}

異常解析器默認配置

public class WebMvcAutoConfiguration {
  @Configuration(proxyBeanMethods = false)
  @EnableConfigurationProperties(WebProperties.class)
  public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
  }  
}
public class WebMvcConfigurationSupport {
  @Bean
  public HandlerExceptionResolver handlerExceptionResolver(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
    List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();
    // 處理自定義異常解析器的配置
    configureHandlerExceptionResolvers(exceptionResolvers);
    if (exceptionResolvers.isEmpty()) {
      // 如果沒有異常解析器,那么添加默認的異常解析器
      addDefaultHandlerExceptionResolvers(exceptionResolvers, contentNegotiationManager);
    }
    extendHandlerExceptionResolvers(exceptionResolvers);
    HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
    // 設置高優先級,Composite成為統一的入口
    composite.setOrder(0);
    composite.setExceptionResolvers(exceptionResolvers);
    return composite;
  }
  // 默認配置
  protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers, ContentNegotiationManager mvcContentNegotiationManager) {
    ExceptionHandlerExceptionResolver exceptionHandlerResolver = createExceptionHandlerExceptionResolver();
    exceptionHandlerResolver.setContentNegotiationManager(mvcContentNegotiationManager);
    exceptionHandlerResolver.setMessageConverters(getMessageConverters());
    exceptionHandlerResolver.setCustomArgumentResolvers(getArgumentResolvers());
    exceptionHandlerResolver.setCustomReturnValueHandlers(getReturnValueHandlers());
    if (jackson2Present) {
      exceptionHandlerResolver.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
    }
    if (this.applicationContext != null) {
      exceptionHandlerResolver.setApplicationContext(this.applicationContext);
    }
    exceptionHandlerResolver.afterPropertiesSet();
    exceptionResolvers.add(exceptionHandlerResolver);
    ResponseStatusExceptionResolver responseStatusResolver = new ResponseStatusExceptionResolver();
    responseStatusResolver.setMessageSource(this.applicationContext);
    exceptionResolvers.add(responseStatusResolver);
    exceptionResolvers.add(new DefaultHandlerExceptionResolver());
  }
}

完畢!!!

分享到:
標簽:Spring
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定