1.HandlerMapping的配置和设计

在初始化完成时,所有的handlerMapping都已经被加载,handlerMapping存储着HTTP请求对应的映射数据,每一个handlerMapping持有从URL请求到Controller的映射。

这里以SimpleUrlHandlerMapping为例来分析它的设计与实现。在SimpleUrlHandlerMapping中,定义了一个map来维持映射关系,即URL请求和控制器对应关系,

是SpringMVC应用可以根据HTTP请求确定对一个对应的Controller,具体来说,这些映射关系是通过接口类HandlerMapping来封装,在HandlerMapping接口中定义了一个getHandler方法,

通过这个方法,可以获得与HTTP请求对应的HandlerExecutionChain,在这个HandlerExecutionChain中,封装具体的Controller对象。

SimpleUrlHandlerMapping中的urlMap:

  1. public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {
  2. //url和controller映射的map
  3. private final Map<String, Object> urlMap = new HashMap<String, Object>();

HandlerMapping中的getHandler

  1. public interface HandlerMapping {
  2. //省略。。。
  3.  
  4. HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
  5.  
  6. }

 接下来,看一下HandlerExecutionChain的实现。

  1. public class HandlerExecutionChain {
  2.  
  3. private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
  4.  
  5. private final Object handler;//处理对象,也就是controller对象
  6.  
  7. private HandlerInterceptor[] interceptors;//拦截器
  8.  
  9. private List<HandlerInterceptor> interceptorList;//拦截器
  10.  
  11. private int interceptorIndex = -1;
  12.  
  13. /**
  14. * Create a new HandlerExecutionChain.
  15. * @param handler the handler object to execute
  16. */
  17. public HandlerExecutionChain(Object handler) {
  18. this(handler, (HandlerInterceptor[]) null);
  19. }
  20.  
  21. /**
  22. * Create a new HandlerExecutionChain.
  23. * @param handler the handler object to execute
  24. * @param interceptors the array of interceptors to apply
  25. * (in the given order) before the handler itself executes
  26. *///初始化
  27. public HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors) {
  28. if (handler instanceof HandlerExecutionChain) {
  29. HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
  30. this.handler = originalChain.getHandler();
  31. this.interceptorList = new ArrayList<HandlerInterceptor>();
  32. CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
  33. CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
  34. }
  35. else {
  36. this.handler = handler;
  37. this.interceptors = interceptors;
  38. }
  39. }
  40.  
  41. /**
  42. * Return the handler object to execute.
  43. * @return the handler object
  44. *///获取handler,本质就是controller对象
  45. public Object getHandler() {
  46. return this.handler;
  47. }
  48.     //添加拦截器
  49. public void addInterceptor(HandlerInterceptor interceptor) {
  50. initInterceptorList().add(interceptor);
  51. }
  52. //添加多个拦截器
  53. public void addInterceptors(HandlerInterceptor... interceptors) {
  54. if (!ObjectUtils.isEmpty(interceptors)) {
  55. initInterceptorList().addAll(Arrays.asList(interceptors));
  56. }
  57. }
  58.  
  59. private List<HandlerInterceptor> initInterceptorList() {
  60. if (this.interceptorList == null) {
  61. this.interceptorList = new ArrayList<HandlerInterceptor>();
  62. if (this.interceptors != null) {
  63. // An interceptor array specified through the constructor
  64. this.interceptorList.addAll(Arrays.asList(this.interceptors));
  65. }
  66. }
  67. this.interceptors = null;
  68. return this.interceptorList;
  69. }
  70.  
  71. /**
  72. * Return the array of interceptors to apply (in the given order).
  73. * @return the array of HandlerInterceptors instances (may be {@code null})
  74. */
  75. public HandlerInterceptor[] getInterceptors() {
  76. if (this.interceptors == null && this.interceptorList != null) {
  77. this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
  78. }
  79. return this.interceptors;
  80. }
  81.  
  82. /**
  83. * Apply preHandle methods of registered interceptors.
  84. * @return {@code true} if the execution chain should proceed with the
  85. * next interceptor or the handler itself. Else, DispatcherServlet assumes
  86. * that this interceptor has already dealt with the response itself.
  87. *///执行之前调用拦截器
  88. boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
  89. HandlerInterceptor[] interceptors = getInterceptors();
  90. if (!ObjectUtils.isEmpty(interceptors)) {
  91. for (int i = 0; i < interceptors.length; i++) {
  92. HandlerInterceptor interceptor = interceptors[i];
  93. if (!interceptor.preHandle(request, response, this.handler)) {
  94. triggerAfterCompletion(request, response, null);
  95. return false;
  96. }
  97. this.interceptorIndex = i;
  98. }
  99. }
  100. return true;
  101. }
  102.  
  103. /**
  104. * Apply postHandle methods of registered interceptors.
  105. *///执行之后调用拦截器
  106. void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
  107. HandlerInterceptor[] interceptors = getInterceptors();
  108. if (!ObjectUtils.isEmpty(interceptors)) {
  109. for (int i = interceptors.length - 1; i >= 0; i--) {
  110. HandlerInterceptor interceptor = interceptors[i];
  111. interceptor.postHandle(request, response, this.handler, mv);
  112. }
  113. }
  114. }
  115.  
  116. /**
  117. * Trigger afterCompletion callbacks on the mapped HandlerInterceptors.
  118. * Will just invoke afterCompletion for all interceptors whose preHandle invocation
  119. * has successfully completed and returned true.
  120. *///调用拦截器的afterCompletion方法
  121. void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
  122. throws Exception {
  123.  
  124. HandlerInterceptor[] interceptors = getInterceptors();
  125. if (!ObjectUtils.isEmpty(interceptors)) {
  126. for (int i = this.interceptorIndex; i >= 0; i--) {
  127. HandlerInterceptor interceptor = interceptors[i];
  128. try {
  129. interceptor.afterCompletion(request, response, this.handler, ex);
  130. }
  131. catch (Throwable ex2) {
  132. logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
  133. }
  134. }
  135. }
  136. }
  137.  
  138. /**
  139. * Apply afterConcurrentHandlerStarted callback on mapped AsyncHandlerInterceptors.
  140. */
  141. void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
  142. HandlerInterceptor[] interceptors = getInterceptors();
  143. if (!ObjectUtils.isEmpty(interceptors)) {
  144. for (int i = interceptors.length - 1; i >= 0; i--) {
  145. if (interceptors[i] instanceof AsyncHandlerInterceptor) {
  146. try {
  147. AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptors[i];
  148. asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
  149. }
  150. catch (Throwable ex) {
  151. logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex);
  152. }
  153. }
  154. }
  155. }
  156. }
  157.  
  158. /**
  159. * Delegates to the handler's {@code toString()}.
  160. */
  161. @Override
  162. public String toString() {
  163. if (this.handler == null) {
  164. return "HandlerExecutionChain with no handler";
  165. }
  166. StringBuilder sb = new StringBuilder();
  167. sb.append("HandlerExecutionChain with handler [").append(this.handler).append("]");
  168. if (!CollectionUtils.isEmpty(this.interceptorList)) {
  169. sb.append(" and ").append(this.interceptorList.size()).append(" interceptor");
  170. if (this.interceptorList.size() > 1) {
  171. sb.append("s");
  172. }
  173. }
  174. return sb.toString();
  175. }
  176.  
  177. }

 下面是拦截器的执行图

对应的applyPreHandle和applyPostHandle方法代码如下:

  1. /**
  2. * Apply preHandle methods of registered interceptors.
  3. * @return {@code true} if the execution chain should proceed with the
  4. * next interceptor or the handler itself. Else, DispatcherServlet assumes
  5. * that this interceptor has already dealt with the response itself.
  6. */
  7. boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
  8. HandlerInterceptor[] interceptors = getInterceptors();
  9. if (!ObjectUtils.isEmpty(interceptors)) {
  10. for (int i = 0; i < interceptors.length; i++) {
  11. HandlerInterceptor interceptor = interceptors[i];
  12. if (!interceptor.preHandle(request, response, this.handler)) {
  13. triggerAfterCompletion(request, response, null);
  14. return false;
  15. }
  16. this.interceptorIndex = i;
  17. }
  18. }
  19. return true;
  20. }
  21.  
  22. /**
  23. * Apply postHandle methods of registered interceptors.
  24. */
  25. void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
  26. HandlerInterceptor[] interceptors = getInterceptors();
  27. if (!ObjectUtils.isEmpty(interceptors)) {
  28. for (int i = interceptors.length - 1; i >= 0; i--) {
  29. HandlerInterceptor interceptor = interceptors[i];
  30. interceptor.postHandle(request, response, this.handler, mv);
  31. }
  32. }
  33. }

  回到SimpleUrlHandlerMapping中,有一个initApplicationContext方法

  1. /**
  2. * Calls the {@link #registerHandlers} method in addition to the
  3. * superclass's initialization.
  4. */
  5. @Override
  6. public void initApplicationContext() throws BeansException {
  7. super.initApplicationContext();
  8. registerHandlers(this.urlMap);
  9. }

  继续看看registerHandlers方法,注册Handler

  1. protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
  2. if (urlMap.isEmpty()) {
  3. logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
  4. }
  5. else {
  6. for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
  7. String url = entry.getKey();
  8. Object handler = entry.getValue();
  9. // Prepend with slash if not already present.
  10. if (!url.startsWith("/")) {//不是以"/"开头的,加上"/"
  11. url = "/" + url;
  12. }
  13. // Remove whitespace from handler bean name.
  14. if (handler instanceof String) {
  15. handler = ((String) handler).trim();
  16. }
  17. registerHandler(url, handler);
  18. }
  19. }
  20. }

  AbstractUrlHandlerMapping对handler的注册

  1. /**
  2. * Register the specified handler for the given URL path.
  3. * @param urlPath the URL the bean should be mapped to
  4. * @param handler the handler instance or handler bean name String
  5. * (a bean name will automatically be resolved into the corresponding handler bean)
  6. * @throws BeansException if the handler couldn't be registered
  7. * @throws IllegalStateException if there is a conflicting handler registered
  8. */
  9. protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
  10. Assert.notNull(urlPath, "URL path must not be null");
  11. Assert.notNull(handler, "Handler object must not be null");
  12. Object resolvedHandler = handler;
  13.  
  14. // Eagerly resolve handler if referencing singleton via name.
  15. if (!this.lazyInitHandlers && handler instanceof String) {
  16. String handlerName = (String) handler;
  17. if (getApplicationContext().isSingleton(handlerName)) {
  18. resolvedHandler = getApplicationContext().getBean(handlerName);//直接从spring容器中获取handler
  19. }
  20. }
  21.  
  22. Object mappedHandler = this.handlerMap.get(urlPath);//从map中获取handler
  23. if (mappedHandler != null) {
  24. if (mappedHandler != resolvedHandler) {
  25. throw new IllegalStateException(
  26. "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
  27. "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
  28. }
  29. }
  30. else {
  31. if (urlPath.equals("/")) {
  32. if (logger.isInfoEnabled()) {
  33. logger.info("Root mapping to " + getHandlerDescription(handler));
  34. }
  35. setRootHandler(resolvedHandler);//url是"/",将其设置为根handler
  36. }
  37. else if (urlPath.equals("/*")) {
  38. if (logger.isInfoEnabled()) {
  39. logger.info("Default mapping to " + getHandlerDescription(handler));
  40. }
  41. setDefaultHandler(resolvedHandler);//默认handler
  42. }
  43. else {
  44. this.handlerMap.put(urlPath, resolvedHandler);//注册handler,url为key,controller为value的map
  45. if (logger.isInfoEnabled()) {
  46. logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
  47. }
  48. }
  49. }
  50. }

  有了上面的配置好了Url和Controller的映射关系,为SpringMVC响应HTTP请求准备好了基础的映射数据,至此SpringMVC就可以等待HTTP的请求的到来。

2.使用HandlerMapping完成请求的映射处理

当请求来时,首先AbstractHandlerMapping的getHandler被调用,方法参数是request

  1. @Override
  2. public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  3. Object handler = getHandlerInternal(request);
  4. if (handler == null) {//为空走默认的handler
  5. handler = getDefaultHandler();
  6. }
  7. if (handler == null) {
  8. return null;
  9. }
  10. // Bean name or resolved handler?
  11. if (handler instanceof String) {
  12. String handlerName = (String) handler;//从spring容器中获取
  13. handler = getApplicationContext().getBean(handlerName);
  14. }
  15. return getHandlerExecutionChain(handler, request);//把handler封装到HandlerExecutionChain中并加上拦截器
  16. }

  封装HandlerExecutionChain

  1. protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
  2. HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
  3. (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
  4. chain.addInterceptors(getAdaptedInterceptors());
  5.  
  6. String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
  7. for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {
  8. if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
  9. chain.addInterceptor(mappedInterceptor.getInterceptor());
  10. }
  11. }
  12.  
  13. return chain;
  14. }

  上面的getHnadler会调用getHandlerInternal

  1. protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
  2. String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
  3. Object handler = lookupHandler(lookupPath, request);
  4. if (handler == null) {
  5. // We need to care for the default handler directly, since we need to
  6. // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
  7. Object rawHandler = null;
  8. if ("/".equals(lookupPath)) {
  9. rawHandler = getRootHandler();
  10. }
  11. if (rawHandler == null) {
  12. rawHandler = getDefaultHandler();
  13. }
  14. if (rawHandler != null) {
  15. // Bean name or resolved handler?
  16. if (rawHandler instanceof String) {
  17. String handlerName = (String) rawHandler;
  18. rawHandler = getApplicationContext().getBean(handlerName);
  19. }
  20. validateHandler(rawHandler, request);
  21. handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
  22. }
  23. }
  24. if (handler != null && logger.isDebugEnabled()) {
  25. logger.debug("Mapping [" + lookupPath + "] to " + handler);
  26. }
  27. else if (handler == null && logger.isTraceEnabled()) {
  28. logger.trace("No handler mapping found for [" + lookupPath + "]");
  29. }
  30. return handler;
  31. }

  这里调用的是lookupHandler方法,在来看一下这个方法。

  1. protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
  2. // Direct match?
  3. Object handler = this.handlerMap.get(urlPath);
  4. if (handler != null) {
  5. // Bean name or resolved handler?
  6. if (handler instanceof String) {
  7. String handlerName = (String) handler;
  8. handler = getApplicationContext().getBean(handlerName);
  9. }
  10. validateHandler(handler, request);
  11. return buildPathExposingHandler(handler, urlPath, urlPath, null);
  12. }
  13. // Pattern match?
  14. List<String> matchingPatterns = new ArrayList<String>();
  15. for (String registeredPattern : this.handlerMap.keySet()) {
  16. if (getPathMatcher().match(registeredPattern, urlPath)) {
  17. matchingPatterns.add(registeredPattern);
  18. }
  19. }
  20. String bestPatternMatch = null;
  21. Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
  22. if (!matchingPatterns.isEmpty()) {
  23. Collections.sort(matchingPatterns, patternComparator);
  24. if (logger.isDebugEnabled()) {
  25. logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
  26. }
  27. bestPatternMatch = matchingPatterns.get(0);
  28. }
  29. if (bestPatternMatch != null) {
  30. handler = this.handlerMap.get(bestPatternMatch);
  31. // Bean name or resolved handler?
  32. if (handler instanceof String) {
  33. String handlerName = (String) handler;
  34. handler = getApplicationContext().getBean(handlerName);
  35. }
  36. validateHandler(handler, request);
  37. String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);
  38.  
  39. // There might be multiple 'best patterns', let's make sure we have the correct URI template variables
  40. // for all of them
  41. Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>();
  42. for (String matchingPattern : matchingPatterns) {
  43. if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {
  44. Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
  45. Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
  46. uriTemplateVariables.putAll(decodedVars);
  47. }
  48. }
  49. if (logger.isDebugEnabled()) {
  50. logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
  51. }
  52. return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
  53. }
  54. // No handler found...
  55. return null;
  56. }

  经过一系列的对HTTP请求进行解析和匹配handler的过程,得到了与请求对应的处理器。在返回handler中,已经完成了对HandlerExecutionChain进行封装工作,为HTTP请求响应做准备。

3.SpringMVC对HTTP请求的分发处理

回到DispatcherServlet中,对HTTP的请求是在doService中,DispatcherServlet是HttpServlet的子类,和其他Servlet一样,通过doService来响应HTTP请求。doService直接调用的是doDispatch方法

主要看一下这个方法。

  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  2. HttpServletRequest processedRequest = request;
  3. HandlerExecutionChain mappedHandler = null;
  4. boolean multipartRequestParsed = false;
  5.  
  6. WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
  7.  
  8. try {
  9. ModelAndView mv = null;
  10. Exception dispatchException = null;
  11.  
  12. try {
  13. processedRequest = checkMultipart(request);
  14. multipartRequestParsed = (processedRequest != request);
  15.  
  16. // Determine handler for the current request.
  17. mappedHandler = getHandler(processedRequest);//获取handler
  18. if (mappedHandler == null || mappedHandler.getHandler() == null) {
  19. noHandlerFound(processedRequest, response);
  20. return;
  21. }
  22.  
  23. // Determine handler adapter for the current request.//获取adapter
  24. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
  25.  
  26. // Process last-modified header, if supported by the handler.
  27. String method = request.getMethod();
  28. boolean isGet = "GET".equals(method);
  29. if (isGet || "HEAD".equals(method)) {
  30. long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
  31. if (logger.isDebugEnabled()) {
  32. logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
  33. }
  34. if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
  35. return;
  36. }
  37. }
  38.  
  39. if (!mappedHandler.applyPreHandle(processedRequest, response)) {
  40. return;
  41. }
  42.  
  43. // Actually invoke the handler.handler处理的结果封装到mv中
  44. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  45.  
  46. if (asyncManager.isConcurrentHandlingStarted()) {
  47. return;
  48. }
  49.  
  50. applyDefaultViewName(request, mv);
  51. mappedHandler.applyPostHandle(processedRequest, response, mv);
  52. }
  53. catch (Exception ex) {
  54. dispatchException = ex;
  55. }
  56. processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
  57. }
  58. catch (Exception ex) {
  59. triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
  60. }
  61. catch (Error err) {
  62. triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
  63. }
  64. finally {
  65. if (asyncManager.isConcurrentHandlingStarted()) {
  66. // Instead of postHandle and afterCompletion
  67. if (mappedHandler != null) {
  68. mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
  69. }
  70. }
  71. else {
  72. // Clean up any resources used by a multipart request.
  73. if (multipartRequestParsed) {
  74. cleanupMultipart(processedRequest);
  75. }
  76. }
  77. }
  78. }

  看一下getHandlerAdapter方法

  1. protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
  2. for (HandlerAdapter ha : this.handlerAdapters) {
  3. if (logger.isTraceEnabled()) {
  4. logger.trace("Testing handler adapter [" + ha + "]");
  5. }
  6. if (ha.supports(handler)) {//判断是否支持
  7. return ha;
  8. }
  9. }
  10. throw new ServletException("No adapter for handler [" + handler +
  11. "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
  12. }

 继续看一下supports方法的实现,以SimpleControlerHandlerAdapter类为例

  1. public class SimpleControllerHandlerAdapter implements HandlerAdapter {
  2.  
  3. @Override
  4. public boolean supports(Object handler) {
  5. return (handler instanceof Controller);
  6. }
  7.  
  8. @Override
  9. public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
  10. throws Exception {
  11.  
  12. return ((Controller) handler).handleRequest(request, response);
  13. }
  14.  
  15. @Override
  16. public long getLastModified(HttpServletRequest request, Object handler) {
  17. if (handler instanceof LastModified) {
  18. return ((LastModified) handler).getLastModified(request);
  19. }
  20. return -1L;
  21. }
  22.  
  23. }

  经过上面一系列的操作,得到handler对象,handler调用handleRequest方法,返回ModelAndView对象,最后通过render方法进行渲染。

问题:handlerMapping是在什么时候初始化的?

在DispatcherServlet调用init->initStrategies方法中,进行初始化。

  1. protected void initStrategies(ApplicationContext context) {
  2. initMultipartResolver(context);
  3. initLocaleResolver(context);
  4. initThemeResolver(context);
  5. //初始化handlerMapping
  6. initHandlerMappings(context);
  7. initHandlerAdapters(context);
  8. initHandlerExceptionResolvers(context);
  9. initRequestToViewNameTranslator(context);
  10. initViewResolvers(context);
  11. initFlashMapManager(context);
  12. }

  最后一个请求的流程图。

 

 

 

  

SpringMVC源码解析-HTTP请求处理和分发的更多相关文章

  1. SpringMVC源码解析- HandlerAdapter - ModelFactory(转)

    ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中 我们来看看具体的处理逻辑(直接充当分析目录): 1 ...

  2. springMVC源码解析--ViewResolver视图解析器执行(三)

    之前两篇博客springMVC源码分析--ViewResolver视图解析器(一)和springMVC源码解析--ViewResolverComposite视图解析器集合(二)中我们已经简单介绍了一些 ...

  3. Netty 4源码解析:请求处理

    Netty 4源码解析:请求处理 通过之前<Netty 4源码解析:服务端启动>的分析,我们知道在最前端"扛压力"的是NioEventLoop.run()方法.我们指定 ...

  4. SpringMVC源码解析- HandlerAdapter - ModelFactory

    ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中 我们来看看具体的处理逻辑(直接充当分析目录): 1 ...

  5. 深入了解SpringMVC源码解析

    Spring MVC源码解析 Spring MVC的使用原理其实是通过配置一个Servlet来接管所有的请求,所有的请求由这个Servlet来进行分发处理. 我们可以从web.xml里面看出这一点 & ...

  6. springmvc源码分析系列-请求处理流程

    接上一篇-springmvc源码分析开头片 上一节主要说了一下springmvc与struts2的作为MVC中的C(controller)控制层的一些区别及两者在作为控制层方面的一些优缺点.今天就结合 ...

  7. springMVC源码解析--ViewResolverComposite视图解析器集合(二)

    上一篇博客springMVC源码分析--ViewResolver视图解析器(一)中我们介绍了一些springMVC提供的很多视图解析器ViewResolver,在开发的一套springMVC系统中是可 ...

  8. springMVC源码解析--HandlerMethodArgumentResolverComposite参数解析器集合(二)

    上一篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)中我们已经介绍了参数解析相关的东西,并且也提到了HandlerMethodArgume ...

  9. springmvc源码解析MvcNamespaceHandler之<mvc:view-resolvers>

    说在前面 本次主要介绍springmvc配置解析. springmvc配置解析 本次介绍MvcNamespaceHandler. 进入到这个方法org.springframework.web.serv ...

随机推荐

  1. UE4蓝图小记

    http://www.element3ds.com/forum.php?mod=viewthread&tid=76930&page=1&authorid=104414 http ...

  2. Unity Shader学习笔记 - 用UV动画实现沙滩上的泡沫

    这个泡沫效果来自远古时代的Unity官方海岛Demo, 原效果直接复制3个材质球在js脚本中做UV动画偏移,这里尝试在shader中做动画并且一个pass中完成: // Upgrade NOTE: r ...

  3. 前端开发工程师 - 01.页面制作 - 第4章.CSS

    第4章.CSS CSS简介 Cascading Style Sheet 层叠样式表:定义页面中的表现样式 history: CSS1(1996)--CSS2(1998)--着手CSS3草案(拆分成很多 ...

  4. List和String数组相互转化

    在工作中经常会遇到需要String[] 参数的地方,我们可以先定义一个list,再转成String[] 来使用,使用list的好处自然是可以随时方便的添加删除元素,下面是方法: List list = ...

  5. 165. Merge Two Sorted Lists【LintCode by java】

    Description Merge two sorted (ascending) linked lists and return it as a new sorted list. The new so ...

  6. 深入理解java虚拟机学习笔记(二)

    第三章 垃圾收集器与内存分配策略 概述 ​ 程序计数器.虚拟机栈.本地方法栈3个区随线程而生,随线程而灭.因此大体上可认为这几个区域的内存分配和回收都具备确定性.在方法/线程结束时,内存自然就跟着回收 ...

  7. NodeJs学习笔记01-你好Node

    如果你对NodeJs略知一二,不禁会感叹,使用JS的语法和代码习惯就能开发一个网站的后台,实现复杂的数据交互,牛! 对于学习java和php就夹生的小码农来说,简直就是靡靡之音呐~~~ 今晚带着忐忑的 ...

  8. C语言struct中的长度可变数组(Flexible array member)

    C_struct中的长度可变数组(Flexible array member) Flexible array member is a feature introduced in the C99 sta ...

  9. javascript打开新窗口

    一.window.open()支持环境: JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二.基本语法: window.open(pageURL,name, ...

  10. 第十六次ScrumMeeting会议

    第十六次Scrum Meeting 时间:2017/12/6 地点:线上+SPR咖啡馆 人员:蔡帜 王子铭 游心 解小锐 王辰昱 李金奇 杨森 陈鑫 照片: 目前工作进展 名字 今日 明天的工作 遇到 ...