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); }