1.springmvc流程分析
各种书上通用写的springmvc流程是这样的:
- 用户发送请求至前端控制器DispatcherServlet。
- DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。(也就是HandlerExecutionChain)
- DispatcherServlet调用HandlerAdapter处理器适配器。
- HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
- Controller执行完成返回ModelAndView。
- HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
- ViewReslover解析后返回具体View.
- DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
- DispatcherServlet响应用户。
2.源码分析
1.发送服务,调用servlet
servlet通过doGet和doPost执行方法 ,这两个方法在DispatcherServlet的父类FrameworkServlet中,其中调用到了doService。
1. protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2. this.processRequest(request, response); 3. }
1. protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2. long startTime = System.currentTimeMillis(); 3. Throwable failureCause = null; 4. LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); 5. LocaleContext localeContext = this.buildLocaleContext(request); 6. RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); 7. ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes); 8. WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 9. asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor()); 10. this.initContextHolders(request, localeContext, requestAttributes); 11. 12. try { 13. this.doService(request, response); 14. } catch (IOException | ServletException var16) { 15. failureCause = var16; 16. throw var16; 17. } catch (Throwable var17) { 18. failureCause = var17; 19. throw new NestedServletException("Request processing failed", var17); 20. } finally { 21. this.resetContextHolders(request, previousLocaleContext, previousAttributes); 22. if (requestAttributes != null) { 23. requestAttributes.requestCompleted(); 24. } 25. 26. this.logResult(request, response, (Throwable)failureCause, asyncManager); 27. this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause); 28. } 29. 30. }
1. protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { 2. 3. this.logRequest(request); 4. Map<String, Object> attributesSnapshot = null; 5. if (WebUtils.isIncludeRequest(request)) { 6. attributesSnapshot = new HashMap(); 7. Enumeration attrNames = request.getAttributeNames(); 8. 9. label95: 10. while(true) { 11. String attrName; 12. do { 13. if (!attrNames.hasMoreElements()) { 14. break label95; 15. } 16. 17. attrName = (String)attrNames.nextElement(); 18. } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet")); 19. 20. attributesSnapshot.put(attrName, request.getAttribute(attrName)); 21. } 22. } 23. //设置属性 24. //ApplicationContext、localeResolver、themeResolver等对象添加到request中 25. request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext()); 26. request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); 27. request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); 28. request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource()); 29. if (this.flashMapManager != null) { 30. FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); 31. if (inputFlashMap != null) { 32. request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); 33. } 34. 35. request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); 36. request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); 37. } 38. 39. try { 40. //具体的方法 41. this.doDispatch(request, response); 42. } finally { 43. if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) { 44. this.restoreAttributesAfterInclude(request, attributesSnapshot); 45. } 46. 47. } 48. 49. }
2.doDispatch
大部分操作都是在这个类中。
1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 2. HttpServletRequest processedRequest = request; 3. HandlerExecutionChain mappedHandler = null; 4. boolean multipartRequestParsed = false; 5. WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 6. 7. try { 8. try { 9. ModelAndView mv = null; 10. Object dispatchException = null; 11. 12. try { 13. // 1. 检查是否是上传文件 14. processedRequest = this.checkMultipart(request); 15. multipartRequestParsed = processedRequest != request; 16. 17. //获取到controller在factory中的所有bean的信息 18. mappedHandler = this.getHandler(processedRequest); 19. 20. if (mappedHandler == null) { 21. this.noHandlerFound(processedRequest, response); 22. return; 23. } 24. 25. //获取到处理器 也就是controller类 26. HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); 27. 28. String method = request.getMethod(); 29. boolean isGet = "GET".equals(method); 30. if (isGet || "HEAD".equals(method)) { 31. // 如果是get 根据上次修改的时间戳来判断资源是否已被修改,如果资源未被修改,则直接返回,浏览器将使用缓存 32. long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); 33. if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { 34. return; 35. } 36. } 37. 38. if (!mappedHandler.applyPreHandle(processedRequest, response)) { 39. return; 40. } 41. 42. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 43. if (asyncManager.isConcurrentHandlingStarted()) { 44. return; 45. } 46. 47. this.applyDefaultViewName(processedRequest, mv); 48. //后置处理器 49. mappedHandler.applyPostHandle(processedRequest, response, mv); 50. } catch (Exception var20) { 51. dispatchException = var20; 52. } catch (Throwable var21) { 53. dispatchException = new NestedServletException("Handler dispatch failed", var21); 54. } 55. 56. this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); 57. } catch (Exception var22) { 58. this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22); 59. } catch (Throwable var23) { 60. this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23)); 61. } 62. 63. } finally { 64. if (asyncManager.isConcurrentHandlingStarted()) { 65. if (mappedHandler != null) { 66. mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); 67. } 68. } else if (multipartRequestParsed) { 69. this.cleanupMultipart(processedRequest); 70. } 71. 72. } 73. }
1.getHandler方法
获取处理器映射器
1. @Nullable 2. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 3. 4. //mapping中放着所有的mapping信息 5. if (this.handlerMappings != null) { 6. Iterator var2 = this.handlerMappings.iterator(); 7. 8. while(var2.hasNext()) { 9. HandlerMapping mapping = (HandlerMapping)var2.next(); 10. 11. //关键方法 获取bean信息的集合 12. HandlerExecutionChain handler = mapping.getHandler(request); 13. 14. if (handler != null) { 15. return handler; 16. } 17. } 18. } 19. 20. return null; 21. }
自定义的mapping都在RequestMappingHandlerMapping 。
然后进入 Object handler = this.getHandlerInternal(request);。
1. public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 2. //主要方法 3. Object handler = this.getHandlerInternal(request); 4. if (handler == null) { 5. handler = this.getDefaultHandler(); 6. } 7. // 如果还是没有则返回 这时候 DispatcherServlet会返回 404 8. if (handler == null) { 9. return null; 10. } else { 11. // 如果返回的处理器是字符串 则认为它是一个beanName 12. if (handler instanceof String) { 13. String handlerName = (String)handler; 14. // 通过beanName从IOC容器中获取相应的处理器 15. handler = this.obtainApplicationContext().getBean(handlerName); 16. } 17. // 下面是将处理器 和 拦截器封装成处理器执行链 18. HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request); 19. if (this.logger.isTraceEnabled()) { 20. this.logger.trace("Mapped to " + handler); 21. } else if (this.logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) { 22. this.logger.debug("Mapped to " + executionChain.getHandler()); 23. } 24. 25. if (CorsUtils.isCorsRequest(request)) { 26. CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request); 27. CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request); 28. CorsConfiguration config = globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig; 29. executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config); 30. } 31. // 返回处理器执行链 32. return executionChain; 33. } 34. }
之后再进入getHandlerInternal。
1. protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { 2. //请求的路径 3. String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request); 4. this.mappingRegistry.acquireReadLock(); 5. 6. HandlerMethod var4; 7. try { 8. //主要方法 9. HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request); 10. var4 = handlerMethod != null ? handlerMethod.createWithResolvedBean() : null; 11. } finally { 12. this.mappingRegistry.releaseReadLock(); 13. } 14. 15. return var4; 16. }
之后再HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request); 在类中 通过request中的mapping在this.mappingRegistry中获取这个bean的所有信息。
1. @Nullable 2. protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { 3. List<AbstractHandlerMethodMapping<T>.Match> matches = new ArrayList(); 4. List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); 5. if (directPathMatches != null) { 6. this.addMatchingMappings(directPathMatches, matches, request); 7. } 8. 9. if (matches.isEmpty()) { 10. this.addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); 11. } 12. 13. if (!matches.isEmpty()) { 14. Comparator<AbstractHandlerMethodMapping<T>.Match> comparator = new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request)); 15. matches.sort(comparator); 16. AbstractHandlerMethodMapping<T>.Match bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0); 17. if (matches.size() > 1) { 18. if (this.logger.isTraceEnabled()) { 19. this.logger.trace(matches.size() + " matching mappings: " + matches); 20. } 21. 22. if (CorsUtils.isPreFlightRequest(request)) { 23. return PREFLIGHT_AMBIGUOUS_MATCH; 24. } 25. 26. AbstractHandlerMethodMapping<T>.Match secondBestMatch = (AbstractHandlerMethodMapping.Match)matches.get(1); 27. if (comparator.compare(bestMatch, secondBestMatch) == 0) { 28. Method m1 = bestMatch.handlerMethod.getMethod(); 29. Method m2 = secondBestMatch.handlerMethod.getMethod(); 30. String uri = request.getRequestURI(); 31. throw new IllegalStateException("Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}"); 32. } 33. } 34. 35. request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); 36. this.handleMatch(bestMatch.mapping, lookupPath, request); 37. //多个请求会返回最佳请求 38. return bestMatch.handlerMethod; 39. } else { 40. return this.handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); 41. } 42. }
然后在进行了其他操作 加入过滤器 最终返回了handler -getHandler方法结束。
2.getHandlerAdapter
获取处理器适配器。
1. protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { 2. if (this.handlerAdapters != null) { 3. Iterator var2 = this.handlerAdapters.iterator(); 4. 5. while(var2.hasNext()) { 6. HandlerAdapter adapter = (HandlerAdapter)var2.next(); 7. //和处理器映射器比对 8. if (adapter.supports(handler)) { 9. return adapter; 10. } 11. } 12. } 13. 14. throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); 15. }
3.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
调用controller方法,通过反射,调用到controller中,返回ModelAndView。
1. @Nullable 2. protected Object doInvoke(Object... args) throws Exception { 3. ReflectionUtils.makeAccessible(this.getBridgedMethod()); 4. 5. try { 6. return this.getBridgedMethod().invoke(this.getBean(), args); 7. } catch (IllegalArgumentException var4) { 8. this.assertTargetBean(this.getBridgedMethod(), this.getBean(), args); 9. String text = var4.getMessage() != null ? var4.getMessage() : "Illegal argument"; 10. throw new IllegalStateException(this.formatInvokeError(text, args), var4); 11. } catch (InvocationTargetException var5) { 12. Throwable targetException = var5.getTargetException(); 13. if (targetException instanceof RuntimeException) { 14. throw (RuntimeException)targetException; 15. } else if (targetException instanceof Error) { 16. throw (Error)targetException; 17. } else if (targetException instanceof Exception) { 18. throw (Exception)targetException; 19. } else { 20. throw new IllegalStateException(this.formatInvokeError("Invocation failure", args), targetException); 21. } 22. } 23. }
3.总结
1.首先调用进入servlet会调用doGet和doPost方法
2.然后调用中DispatcherServlet的doService
3.调用doService中的doDispatch
4.调用doDispatch中的getHandler使用handleMapping处理器映射器 去获取HandlerExecutionChain
1.通过mapping去this.mappingRegistry获取到需求bean在factory中的信息
2.将得到的hander和过滤器放在返回对象HandlerExecutionChain
5.获取Adapter
6.使用Adapter 通过反射调用controller
7.返回ModelAndView