上一篇简单介绍了spring mvc 的一些基本内容 和DispatcherServlet 的doc。这一篇将会继续写我对Spring Mvc 源代码的理解。直接上代码:

  1. /**
  2. * This implementation calls {@link #initStrategies}. --这里实现调用
  3. */
  4. @Override
    //这里可以跟踪进,看到最终调用这个的是在:org\apache\tomcat\embed\tomcat-embed-core\8.5.23\tomcat-embed-core-8.5.23-sources.jar!\javax\servlet\GenericServlet.java中的init()方法中,而 GenericServlet.java 则是实现了Servlet接口的init()
  5. protected void onRefresh(ApplicationContext context) {
  6. initStrategies(context);
  7. }
  8. /**
  9. * Initialize the strategy objects that this servlet uses.
  10. * <p>May be overridden in subclasses in order to initialize further strategy objects.
  11. */
  12. protected void initStrategies(ApplicationContext context) {
    //上传文件流
  13. initMultipartResolver(context);
    //国际化
  14. initLocaleResolver(context);
    //主题
  15. initThemeResolver(context);
    //url映射
  16. initHandlerMappings(context);
    //适配器
  17. initHandlerAdapters(context);
    //处理异常
  18. initHandlerExceptionResolvers(context);
    //视图名转换
  19. initRequestToViewNameTranslator(context);
    //视图处理器
  20. initViewResolvers(context);
  21. initFlashMapManager(context);
  22. }

 先看下匹配器 initHandlerMappings(context);

  1. /**
  2. * Initialize the HandlerMappings used by this class.
  3. * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
  4. * we default to BeanNameUrlHandlerMapping.
  5. */
  6. private void initHandlerMappings(ApplicationContext context) {
  7. this.handlerMappings = null;
  8. if (this.detectAllHandlerMappings) { //是否检索所有的HandlerMapping 映射。默认是true
  9. // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
    //查询所有的映射,包括祖先context的
  10. Map<String, HandlerMapping> matchingBeans =
  11. BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
  12. if (!matchingBeans.isEmpty()) {
  13. this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
  14. // 放在一个排序的list中
  15. AnnotationAwareOrderComparator.sort(this.handlerMappings);
  16. }
  17. }
  18. else {
  19. try {
  20. HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
  21. this.handlerMappings = Collections.singletonList(hm);
  22. }
  23. catch (NoSuchBeanDefinitionException ex) {
  24. // Ignore, we'll add a default HandlerMapping later.
  25. }
  26. }
  27. // Ensure we have at least one HandlerMapping, by registering
  28. // a default HandlerMapping if no other mappings are found.
    // 如果没有handlerMapping ,则使用默认的handlerMapping
  29. if (this.handlerMappings == null) {
  30. this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
  31. if (logger.isDebugEnabled()) {
  32. logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
  33. }
  34. }
  35. }

最终会得到一个list:List<HandlerMapping>

——————————————————————

下面看 initHandlerAdapters

  1. /**
  2. * Initialize the HandlerAdapters used by this class.
  3. * <p>If no HandlerAdapter beans are defined in the BeanFactory for this namespace,
  4. * we default to SimpleControllerHandlerAdapter.
  5. */
  6. private void initHandlerAdapters(ApplicationContext context) {
  7. this.handlerAdapters = null;
  8. if (this.detectAllHandlerAdapters) {
  9. // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
  10. Map<String, HandlerAdapter> matchingBeans =
  11. BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
  12. if (!matchingBeans.isEmpty()) {
  13. this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values());
  14. // We keep HandlerAdapters in sorted order.
  15. AnnotationAwareOrderComparator.sort(this.handlerAdapters);
  16. }
  17. }
  18. else {
  19. try {
  20. HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
  21. this.handlerAdapters = Collections.singletonList(ha);
  22. }
  23. catch (NoSuchBeanDefinitionException ex) {
  24. // Ignore, we'll add a default HandlerAdapter later.
  25. }
  26. }
  27. // Ensure we have at least some HandlerAdapters, by registering
  28. // default HandlerAdapters if no other adapters are found.
  29. if (this.handlerAdapters == null) {
  30. this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
  31. if (logger.isDebugEnabled()) {
  32. logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
  33. }
  34. }
  35. }

从代码可以看出,这里的代码和 initHandlerMappings 非常像,都是把bean添加到一个list里面,唯一不同的是类型而已。

———————————————————————————————————————————————————

DispatcherServlet 处理请求方法,在 doService(HttpServletRequest request, HttpServletResponse response) 。在DispatcherServlet 的父类FrameworkServlet的processRequest 中调用了这个方法。(这里又是一个模板方法模式)。doService(HttpServletRequest request, HttpServletResponse response) 源代码如下:

  1. /**
  2. * Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
  3. * for the actual dispatching.
  4. */
    //实际调用DispatcherServlet
  5. @Override
  6. protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
  7. if (logger.isDebugEnabled()) {
  8. String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
  9. logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
  10. " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
  11. }
  12. // Keep a snapshot of the request attributes in case of an include,
  13. // to be able to restore the original attributes after the include.
    //保存一份快照,方便恢复
  14. Map<String, Object> attributesSnapshot = null;
  15. if (WebUtils.isIncludeRequest(request)) {
  16. attributesSnapshot = new HashMap<String, Object>();
  17. Enumeration<?> attrNames = request.getAttributeNames();
  18. while (attrNames.hasMoreElements()) {
  19. String attrName = (String) attrNames.nextElement();
  20. if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
  21. attributesSnapshot.put(attrName, request.getAttribute(attrName));
  22. }
  23. }
  24. }
  25. // Make framework objects available to handlers and view objects.
    // 使处理器和视图都可以使用object
  26. request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
  27. request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
  28. request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
  29. request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
  30. FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
  31. if (inputFlashMap != null) {
  32. request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
  33. }
  34. request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
  35. request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
  36. try {
  37. doDispatch(request, response); //实际调度
  38. }
  39. finally {
  40. if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
  41. // Restore the original attribute snapshot, in case of an include.
  42. if (attributesSnapshot != null) {
  43. restoreAttributesAfterInclude(request, attributesSnapshot);
  44. }
  45. }
  46. }
  47. }
  1. /**
  2. * Process the actual dispatching to the handler.
  3. * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
  4. * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
  5. * to find the first that supports the handler class.
  6. * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
  7. * themselves to decide which methods are acceptable.
  8. * @param request current HTTP request
  9. * @param response current HTTP response
  10. * @throws Exception in case of any kind of processing failure
  11. */

    //真正处理请求
  12. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  13. HttpServletRequest processedRequest = request;
  14. HandlerExecutionChain mappedHandler = null;
  15. boolean multipartRequestParsed = false;
  16. WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
  17. try {
  18. ModelAndView mv = null;
  19. Exception dispatchException = null;
  20. try {
  21. processedRequest = checkMultipart(request);
  22. multipartRequestParsed = (processedRequest != request);
  23. // Determine handler for the current request.
    //查找匹配的Controller 、方法、参数、返回值、异常等消息。处理的方法是迭代 initHandlerMapping(context) 里面的注册的mapping,这个是放在一个list里面
  24. mappedHandler = getHandler(processedRequest);
  25. if (mappedHandler == null || mappedHandler.getHandler() == null) {
  26. noHandlerFound(processedRequest, response);
  27. return;
  28. }
  29. // Determine handler adapter for the current request.
  30. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); //确定请求调用的HandlerAdapter。我们自定义的HandlerAdapter,也是在这里被获取到。
  31. // Process last-modified header, if supported by the handler.
  32. String method = request.getMethod(); //获取报文里面的方法名称
  33. boolean isGet = "GET".equals(method); //是否是GET调用
  34. if (isGet || "HEAD".equals(method)) {
  35. long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); //查找url中对应的方法
  36. if (logger.isDebugEnabled()) {
  37. logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
  38. }
  39. if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
  40. return;
  41. }
  42. }
  43. if (!mappedHandler.applyPreHandle(processedRequest, response)) {
  44. return;
  45. }
  46. // Actually invoke the handler.
    // 执行处理器
  47. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  48. if (asyncManager.isConcurrentHandlingStarted()) {
  49. return;
  50. }

  51. //确定view
  52. applyDefaultViewName(processedRequest, mv);
    //应用已注册拦截器的后期方法
  53. mappedHandler.applyPostHandle(processedRequest, response, mv);
  54. }
  55. catch (Exception ex) {
  56. dispatchException = ex;
  57. }
  58. catch (Throwable err) {
  59. // As of 4.3, we're processing Errors thrown from handler methods as well,
  60. // making them available for @ExceptionHandler methods and other scenarios.
  61. dispatchException = new NestedServletException("Handler dispatch failed", err);
  62. }
    //解释模型和者视图(ModelAndView),或者是异常
  63. processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
  64. }
  65. catch (Exception ex) {
  66. triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
  67. }
  68. catch (Throwable err) {
  69. triggerAfterCompletion(processedRequest, response, mappedHandler,
  70. new NestedServletException("Handler processing failed", err));
  71. }
  72. finally {
  73. if (asyncManager.isConcurrentHandlingStarted()) {
  74. // Instead of postHandle and afterCompletion
  75. if (mappedHandler != null) {
  76. mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
  77. }
  78. }
  79. else {
  80. // Clean up any resources used by a multipart request.
  81. if (multipartRequestParsed) {
  82. cleanupMultipart(processedRequest);
  83. }
  84. }
  85. }
  86. }

从这里看出,基本流程就是:查到需要调用的方法–> 执行方法 —>返回模型和视图(ModelAndView)或者异常   –> 解释返回的模型和视图

ha.handle(processedRequest, response, mappedHandler.getHandler()) 的源代码如下:

  1. @Override
  2. protected ModelAndView handleInternal(HttpServletRequest request,
  3. HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
  4. ModelAndView mav;
  5. checkRequest(request); //检查是否是支持的http请求(GET、POST)和 需要session 支持
  6. // Execute invokeHandlerMethod in synchronized block if required. //是否需要同步执行方法
  7. if (this.synchronizeOnSession) {
  8. HttpSession session = request.getSession(false);
  9. if (session != null) {
  10. Object mutex = WebUtils.getSessionMutex(session);
  11. synchronized (mutex) {
  12. mav = invokeHandlerMethod(request, response, handlerMethod);
  13. }
  14. }
  15. else {
  16. // No HttpSession available -> no mutex necessary
  17. mav = invokeHandlerMethod(request, response, handlerMethod);
  18. }
  19. }
  20. else {
  21. // No synchronization on session demanded at all...
  22. mav = invokeHandlerMethod(request, response, handlerMethod); //查找、执行方法,准备视图
  23. }
  24. if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
  25. if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
  26. applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
  27. }
  28. else {
  29. prepareResponse(response);
  30. }
  31. }
  32. return mav;
  33. }
  1. /**
  2. * Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}
  3. * if view resolution is required.
  4. * @since 4.2
  5. * @see #createInvocableHandlerMethod(HandlerMethod)
  6. */
  7. protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
  8. HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
  9. ServletWebRequest webRequest = new ServletWebRequest(request, response); //获取url相关
  10. try {
  11. WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
  12. ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
  13. ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); //获取要Controller、method、args、return type 等信息
  14. invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
  15. invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
  16. invocableMethod.setDataBinderFactory(binderFactory);
  17. invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
  18. ModelAndViewContainer mavContainer = new ModelAndViewContainer();
  19. mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
  20. modelFactory.initModel(webRequest, mavContainer, invocableMethod);
  21. mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
  22. AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
  23. asyncWebRequest.setTimeout(this.asyncRequestTimeout);
  24. WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
  25. asyncManager.setTaskExecutor(this.taskExecutor);
  26. asyncManager.setAsyncWebRequest(asyncWebRequest);
  27. asyncManager.registerCallableInterceptors(this.callableInterceptors);
  28. asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
  29. if (asyncManager.hasConcurrentResult()) {
  30. Object result = asyncManager.getConcurrentResult();
  31. mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
  32. asyncManager.clearConcurrentResult();
  33. if (logger.isDebugEnabled()) {
  34. logger.debug("Found concurrent result value [" + result + "]");
  35. }
  36. invocableMethod = invocableMethod.wrapConcurrentResult(result);
  37. }
  38. invocableMethod.invokeAndHandle(webRequest, mavContainer); //真正地使用反射来执行方法,并返回值
  39. if (asyncManager.isConcurrentHandlingStarted()) {
  40. return null;
  41. }
  42. return getModelAndView(mavContainer, modelFactory, webRequest); //返回ModelAndView
  43. }
  44. finally {
  45. webRequest.requestCompleted();
  46. }
  47. }

 invocableMethod.invokeAndHandle(webRequest, mavContainer) 的代码如下:

  1. /**
  2. * Invoke the method and handle the return value through one of the
  3. * configured {@link HandlerMethodReturnValueHandler}s.
  4. * @param webRequest the current request
  5. * @param mavContainer the ModelAndViewContainer for this request
  6. * @param providedArgs "given" arguments matched by type (not resolved)
  7. */
  8. public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
  9. Object... providedArgs) throws Exception {
  10. Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); //执行请求
  11. setResponseStatus(webRequest);
  12. if (returnValue == null) {
  13. if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
  14. mavContainer.setRequestHandled(true);
  15. return;
  16. }
  17. }
  18. else if (StringUtils.hasText(getResponseStatusReason())) {
  19. mavContainer.setRequestHandled(true);
  20. return;
  21. }
  22. mavContainer.setRequestHandled(false);
  23. try {
  24. this.returnValueHandlers.handleReturnValue(
  25. returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
  26. }
  27. catch (Exception ex) {
  28. if (logger.isTraceEnabled()) {
  29. logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
  30. }
  31. throw ex;
  32. }
  33. }
  1. /**
  2. * Invoke the method after resolving its argument values in the context of the given request.
  3. * <p>Argument values are commonly resolved through {@link HandlerMethodArgumentResolver}s.
  4. * The {@code providedArgs} parameter however may supply argument values to be used directly,
  5. * i.e. without argument resolution. Examples of provided argument values include a
  6. * {@link WebDataBinder}, a {@link SessionStatus}, or a thrown exception instance.
  7. * Provided argument values are checked before argument resolvers.
  8. * @param request the current request
  9. * @param mavContainer the ModelAndViewContainer for this request
  10. * @param providedArgs "given" arguments matched by type, not resolved
  11. * @return the raw value returned by the invoked method
  12. * @exception Exception raised if no suitable argument resolver can be found,
  13. * or if the method raised an exception
  14. */
  15. public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
  16. Object... providedArgs) throws Exception {
  17. Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); //获取参数
  18. if (logger.isTraceEnabled()) {
  19. logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
  20. "' with arguments " + Arrays.toString(args));
  21. }
  22. Object returnValue = doInvoke(args); //执行方法
  23. if (logger.isTraceEnabled()) {
  24. logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
  25. "] returned [" + returnValue + "]");
  26. }
  27. return returnValue;
  28. }
  1. /**
  2. * Invoke the handler method with the given argument values.
  3. */
  4. protected Object doInvoke(Object... args) throws Exception {
  5. ReflectionUtils.makeAccessible(getBridgedMethod());
  6. try {
  7. return getBridgedMethod().invoke(getBean(), args); //使用反射执行方法
  8. }
  9. catch (IllegalArgumentException ex) {
  10. assertTargetBean(getBridgedMethod(), getBean(), args);
  11. String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
  12. throw new IllegalStateException(getInvocationErrorMessage(text, args), ex);
  13. }
  14. catch (InvocationTargetException ex) {
  15. // Unwrap for HandlerExceptionResolvers ...
  16. Throwable targetException = ex.getTargetException();
  17. if (targetException instanceof RuntimeException) {
  18. throw (RuntimeException) targetException;
  19. }
  20. else if (targetException instanceof Error) {
  21. throw (Error) targetException;
  22. }
  23. else if (targetException instanceof Exception) {
  24. throw (Exception) targetException;
  25. }
  26. else {
  27. String text = getInvocationErrorMessage("Failed to invoke handler method", args);
  28. throw new IllegalStateException(text, targetException);
  29. }
  30. }
  31. }

———————————————————————————————

继续跟进 getModelAndView(mavContainer, modelFactory, webRequest) 方法,源代码如下:

  1. private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
  2. ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
  3. modelFactory.updateModel(webRequest, mavContainer);
  4. if (mavContainer.isRequestHandled()) {
  5. return null;
  6. }
  7. ModelMap model = mavContainer.getModel();
  8. ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
  9. if (!mavContainer.isViewReference()) {
  10. mav.setView((View) mavContainer.getView());
  11. }
  12. if (model instanceof RedirectAttributes) {
  13. Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
  14. HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
  15. RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
  16. }
  17. return mav;
  18. }
  1. ModelAndView 代码如下:
  1. public class ModelAndView {
  2. /** View instance or view name String */
  3. private Object view;
  4. /** Model Map */
  5. private ModelMap model;
  6. /** Optional HTTP status for the response */
  7. private HttpStatus status;
  8. /** Indicates whether or not this instance has been cleared with a call to {@link #clear()} */
  9. private boolean cleared = false;
  10. //************************ 省略
  11. }

再返回看下解释视图和模型或者异常的方法 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException) ,源代码如下:

  1. /**
  2. * Handle the result of handler selection and handler invocation, which is
  3. * either a ModelAndView or an Exception to be resolved to a ModelAndView.
  4. */
  5. private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
  6. HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
  7. boolean errorView = false;
  8. if (exception != null) {
  9. if (exception instanceof ModelAndViewDefiningException) {
  10. logger.debug("ModelAndViewDefiningException encountered", exception);
  11. mv = ((ModelAndViewDefiningException) exception).getModelAndView();
  12. }
  13. else {
  14. Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
  15. mv = processHandlerException(request, response, handler, exception);
  16. errorView = (mv != null);
  17. }
  18. }
  19. // Did the handler return a view to render?
  20. if (mv != null && !mv.wasCleared()) {
  21. render(mv, request, response); //解释、渲染视图和模型
  22. if (errorView) {
  23. WebUtils.clearErrorRequestAttributes(request);
  24. }
  25. }
  26. else {
  27. if (logger.isDebugEnabled()) {
  28. logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
  29. "': assuming HandlerAdapter completed request handling");
  30. }
  31. }
  32. if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
  33. // Concurrent handling started during a forward
  34. return;
  35. }
  36. if (mappedHandler != null) {
  37. mappedHandler.triggerAfterCompletion(request, response, null);
  38. }
  39. }
  1. /**
  2. * Render the given ModelAndView.
  3. * <p>This is the last stage in handling a request. It may involve resolving the view by name.
  4. * @param mv the ModelAndView to render
  5. * @param request current HTTP servlet request
  6. * @param response current HTTP servlet response
  7. * @throws ServletException if view is missing or cannot be resolved
  8. * @throws Exception if there's a problem rendering the view
  9. */
  10. protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
  11. // Determine locale for request and apply it to the response.
    //国际化、本地化
  12. Locale locale = this.localeResolver.resolveLocale(request);
  13. response.setLocale(locale);
  14. View view;
  15. if (mv.isReference()) { //引用视图
  16. // We need to resolve the view name.
  17. view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
  18. if (view == null) {
  19. throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
  20. "' in servlet with name '" + getServletName() + "'");
  21. }
  22. }
  23. else {
  24. // No need to lookup: the ModelAndView object contains the actual View object.
  25. view = mv.getView(); //获取视图
  26. if (view == null) {
  27. throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
  28. "View object in servlet with name '" + getServletName() + "'");
  29. }
  30. }
  31. // Delegate to the View object for rendering.
    // 委托模式
  32. if (logger.isDebugEnabled()) {
  33. logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
  34. }
  35. try {
  36. if (mv.getStatus() != null) {
  37. response.setStatus(mv.getStatus().value());
  38. }
    //真正渲染的方法
  39. view.render(mv.getModelInternal(), request, response);
  40. }
  41. catch (Exception ex) {
  42. if (logger.isDebugEnabled()) {
  43. logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
  44. getServletName() + "'", ex);
  45. }
  46. throw ex;
  47. }
  48. }

—————————————————————————————————————————

以上就是我的基本分析,当然还有很多细节没有看,只是看了基本的流程和核心代码。如果有错,请大神指正。

posted on 2018-09-19 08:49 drafire 阅读() 评论() 编辑 收藏

版权声明:本文为drafire原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/drafire/p/9669192.html