HandlerMapping就是根據Request找到對應的處理Handler和Interceptors。HandlerMapping 的方法只有一個,根據request獲取HandlerExecutionChainapp
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
HandlerExecutionChain裏面包含了若干Interceptor和一個具體的Handler。this
在DispatcherServlet中,有個方法spa
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { for (HandlerMapping hm : this.handlerMappings) { if (logger.isTraceEnabled()) { logger.trace( "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'"); } HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; }
就是經過request,在HandlerMapping列表中查找,找到第一個就返回HandlerExecutionChaindebug
從下面註釋能夠看出,HandlerAdapter的做用就是用request來調用handler的處理類(由於每一個controller的方法的參數都是不同的)日誌
public interface HandlerAdapter { /** * 判斷當前adapter是否支持該handler示例 */ boolean supports(Object handler); /** * 使用參數中的handler處理參數中的request */ ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; long getLastModified(HttpServletRequest request, Object handler); }
在DispatcherServlet中的getHandlerAdpater方法中,也是遍歷全部的handlerAdpater,找出第一個能support的去處理。接口
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { for (HandlerAdapter ha : this.handlerAdapters) { if (logger.isTraceEnabled()) { logger.trace("Testing handler adapter [" + ha + "]"); } if (ha.supports(handler)) { return ha; } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
當在上面的處理過程當中出現Exception 的時候,就須要一個專門處理異常的類(就算出問題了,總也得給點反饋吧)。而HandlerExceptionResolver就是來作這種事情的。咱們作統一錯誤頁或者記錄錯誤日誌的時候就能夠實現該接口ip
public interface HandlerExceptionResolver { /** * 出現異常的時候會調用改方法 */ ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex); }
這個組件的做用就是渲染頁面,在Dispatcher中的應用以下:get
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { Locale locale = this.localeResolver.resolveLocale(request); response.setLocale(locale); View view; if (mv.isReference()) { // We need to resolve the view name. view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + getServletName() + "'"); } } else { // No need to lookup: the ModelAndView object contains the actual View object. view = mv.getView(); if (view == null) { throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name '" + getServletName() + "'"); } } // Delegate to the View object for rendering. if (logger.isDebugEnabled()) { logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'"); } try { if (mv.getStatus() != null) { response.setStatus(mv.getStatus().value()); } view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'", ex); } throw ex; } }
首先是先找出渲染視圖locale(地區,例如zn),而後根據locale調用ViewResolver的解析方法生成View。最後用view渲染。servlet
ViewResolver的做用就是根據視圖名(viewName)找出對應的視圖(能夠理解爲一個地址),而視圖的做用就是填充模板中的一些參數(JSTL或是Freemaker)。接口以下:flash
public interface ViewResolver { View resolveViewName(String viewName, Locale locale) throws Exception; }
前面介紹ViewResolver的做用是根據viewName來查找出對應的視圖,可是有些handler處理過程當中並無設置視圖,而RequestToViewNameTranslator就是根據request找出視圖。
用於處理上傳請求。將普通的requet封裝爲MultipartHttpServletRequest。後者直接能夠獲取文件。
這個主要是再出redirect的時候傳遞參數。
public interface FlashMapManager { /** * 恢復和更新參數 */ FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response); /** * 將參數保存到FlashMap中 */ void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response); }