说在前面

本次主要介绍DispatcherServlet,关注”天河聊架构“更多精彩。

springmvc配置解析

进入方法org.springframework.web.bind.annotation.support.HandlerMethodInvoker#resolveHttpEntityRequest

private HttpEntity<?> resolveHttpEntityRequest(MethodParameter methodParam, NativeWebRequest webRequest)
      throws Exception {

   HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
   Class<?> paramType = getHttpEntityType(methodParam);
   Object body = readWithMessageConverters(methodParam, inputMessage, paramType);
   return new HttpEntity<Object>(body, inputMessage.getHeaders());
}

返回方法org.springframework.web.bind.annotation.support.HandlerMethodInvoker#resolveRequestParam

private Object resolveRequestParam(String paramName, boolean required, String defaultValue,
         MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
         throws Exception {

      Class<?> paramType = methodParam.getParameterType();
      if (Map.class.isAssignableFrom(paramType) && paramName.length() == 0) {
         return resolveRequestParamMap((Class<? extends Map<?, ?>>) paramType, webRequest);
      }
      if (paramName.length() == 0) {
         paramName = getRequiredParameterName(methodParam);
      }
      Object paramValue = null;
//    解析上传文件的属性名
      MultipartRequest multipartRequest = webRequest.getNativeRequest(MultipartRequest.class);
      if (multipartRequest != null) {
         List<MultipartFile> files = multipartRequest.getFiles(paramName);
         if (!files.isEmpty()) {
            paramValue = (files.size() == 1 ? files.get(0) : files);
         }
      }
      if (paramValue == null) {
//       底层还是调用request.getParameterValues方法
         String[] paramValues = webRequest.getParameterValues(paramName);
         if (paramValues != null) {
            paramValue = (paramValues.length == 1 ? paramValues[0] : paramValues);
         }
      }
//    赋默认值
      if (paramValue == null) {
         if (defaultValue != null) {
            paramValue = resolveDefaultValue(defaultValue);
         }
//       如果是必填值就抛异常
         else if (required) {
            raiseMissingParameterException(paramName, paramType);
         }
         paramValue = checkValue(paramName, paramValue, paramType);
      }
//    创建属性绑定器
      WebDataBinder binder = createBinder(webRequest, null, paramName);
//    初始化参数绑定 -》
      initBinder(handlerForInitBinderCall, paramName, binder, webRequest);
      return binder.convertIfNecessary(paramValue, paramType, methodParam);
   }

进入方法org.springframework.web.bind.annotation.support.HandlerMethodInvoker#initBinder

protected void initBinder(Object handler, String attrName, WebDataBinder binder, NativeWebRequest webRequest)
         throws Exception {

      if (this.bindingInitializer != null) {
         this.bindingInitializer.initBinder(binder, webRequest);
      }
      if (handler != null) {
         Set<Method> initBinderMethods = this.methodResolver.getInitBinderMethods();
         if (!initBinderMethods.isEmpty()) {
            boolean debug = logger.isDebugEnabled();
            for (Method initBinderMethod : initBinderMethods) {
//             获取带有@InitBinder注解的方法
               Method methodToInvoke = BridgeMethodResolver.findBridgedMethod(initBinderMethod);
               String[] targetNames = AnnotationUtils.findAnnotation(initBinderMethod, InitBinder.class).value();
               if (targetNames.length == 0 || Arrays.asList(targetNames).contains(attrName)) {
//                参数绑定 -》
                  Object[] initBinderArgs =
                        resolveInitBinderArguments(handler, methodToInvoke, binder, webRequest);
                  if (debug) {
                     logger.debug("Invoking init-binder method: " + methodToInvoke);
                  }
                  ReflectionUtils.makeAccessible(methodToInvoke);
//                执行方法-》
                  Object returnValue = methodToInvoke.invoke(handler, initBinderArgs);
                  if (returnValue != null) {
                     throw new IllegalStateException(
                           "InitBinder methods must not have a return value: " + methodToInvoke);
                  }
               }
            }
         }
      }
   }

返回方法org.springframework.web.bind.annotation.support.HandlerMethodInvoker#resolveRequestHeader

private Object resolveRequestHeader(String headerName, boolean required, String defaultValue,
         MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
         throws Exception {

      Class<?> paramType = methodParam.getParameterType();
      if (Map.class.isAssignableFrom(paramType)) {
         return resolveRequestHeaderMap((Class<? extends Map<?, ?>>) paramType, webRequest);
      }
      if (headerName.length() == 0) {
         headerName = getRequiredParameterName(methodParam);
      }
      Object headerValue = null;
      String[] headerValues = webRequest.getHeaderValues(headerName);
      if (headerValues != null) {
         headerValue = (headerValues.length == 1 ? headerValues[0] : headerValues);
      }
      if (headerValue == null) {
         if (defaultValue != null) {
            headerValue = resolveDefaultValue(defaultValue);
         }
         else if (required) {
            raiseMissingHeaderException(headerName, paramType);
         }
         headerValue = checkValue(headerName, headerValue, paramType);
      }
      WebDataBinder binder = createBinder(webRequest, null, headerName);
//    初始化绑定器-》
      initBinder(handlerForInitBinderCall, headerName, binder, webRequest);
      return binder.convertIfNecessary(headerValue, paramType, methodParam);
   }

返回方法org.springframework.web.bind.annotation.support.HandlerMethodInvoker#readWithMessageConverters

private Object readWithMessageConverters(MethodParameter methodParam, HttpInputMessage inputMessage, Class<?> paramType)
         throws Exception {

      MediaType contentType = inputMessage.getHeaders().getContentType();
      if (contentType == null) {
         StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));
         String paramName = methodParam.getParameterName();
         if (paramName != null) {
            builder.append(' ');
            builder.append(paramName);
         }
         throw new HttpMediaTypeNotSupportedException(
               "Cannot extract parameter (" + builder.toString() + "): no Content-Type found");
      }

      List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
      if (this.messageConverters != null) {
//       执行转换器
         for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
            allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
            if (messageConverter.canRead(paramType, contentType)) {
               if (logger.isDebugEnabled()) {
                  logger.debug("Reading [" + paramType.getName() + "] as \"" + contentType
                        +"\" using [" + messageConverter + "]");
               }
               return messageConverter.read((Class) paramType, inputMessage);
            }
         }
      }
      throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
   }

返回方法org.springframework.web.bind.annotation.support.HandlerMethodInvoker#resolveCookieValue(java.lang.String, boolean, java.lang.String, org.springframework.core.MethodParameter, org.springframework.web.context.request.NativeWebRequest, java.lang.Object)

private Object resolveCookieValue(String cookieName, boolean required, String defaultValue,
         MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
         throws Exception {

      Class<?> paramType = methodParam.getParameterType();
      if (cookieName.length() == 0) {
         cookieName = getRequiredParameterName(methodParam);
      }
      Object cookieValue = resolveCookieValue(cookieName, paramType, webRequest);
      if (cookieValue == null) {
         if (defaultValue != null) {
            cookieValue = resolveDefaultValue(defaultValue);
         }
         else if (required) {
            raiseMissingCookieException(cookieName, paramType);
         }
         cookieValue = checkValue(cookieName, cookieValue, paramType);
      }
      WebDataBinder binder = createBinder(webRequest, null, cookieName);
//    初始化绑定器-》
      initBinder(handlerForInitBinderCall, cookieName, binder, webRequest);
      return binder.convertIfNecessary(cookieValue, paramType, methodParam);
   }

返回方法org.springframework.web.bind.annotation.support.HandlerMethodInvoker#resolvePathVariable(java.lang.String, org.springframework.core.MethodParameter, org.springframework.web.context.request.NativeWebRequest, java.lang.Object)

private Object resolvePathVariable(String pathVarName, MethodParameter methodParam,
         NativeWebRequest webRequest, Object handlerForInitBinderCall) throws Exception {

      Class<?> paramType = methodParam.getParameterType();
      if (pathVarName.length() == 0) {
         pathVarName = getRequiredParameterName(methodParam);
      }
      String pathVarValue = resolvePathVariable(pathVarName, paramType, webRequest);
      WebDataBinder binder = createBinder(webRequest, null, pathVarName);
//    初始化绑定器-》
      initBinder(handlerForInitBinderCall, pathVarName, binder, webRequest);
      return binder.convertIfNecessary(pathVarValue, paramType, methodParam);
   }

返回方法org.springframework.web.bind.annotation.support.HandlerMethodInvoker#resolveModelAttribute

private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
         ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {

      // Bind request parameter onto object...
      String name = attrName;
      if ("".equals(name)) {
         name = Conventions.getVariableNameForParameter(methodParam);
      }
      Class<?> paramType = methodParam.getParameterType();
      Object bindObject;
      if (implicitModel.containsKey(name)) {
         bindObject = implicitModel.get(name);
      }
      else if (this.methodResolver.isSessionAttribute(name, paramType)) {
         bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
         if (bindObject == null) {
            raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
         }
      }
      else {
         bindObject = BeanUtils.instantiateClass(paramType);
      }
      WebDataBinder binder = createBinder(webRequest, bindObject, name);
//    初始化绑定器-》
      initBinder(handler, name, binder, webRequest);
      return binder;
   }

返回方法org.springframework.web.bind.annotation.support.HandlerMethodInvoker#doBind(org.springframework.web.bind.WebDataBinder, org.springframework.web.context.request.NativeWebRequest, boolean, java.lang.Object[], boolean)

private void doBind(WebDataBinder binder, NativeWebRequest webRequest, boolean validate,
         Object[] validationHints, boolean failOnErrors) throws Exception {

      doBind(binder, webRequest);
      if (validate) {
//       执行参数验证
         binder.validate(validationHints);
      }
      if (failOnErrors && binder.getBindingResult().hasErrors()) {
         throw new BindException(binder.getBindingResult());
      }
   }

返回方法org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.ServletHandlerMethodInvoker#getModelAndView

public ModelAndView getModelAndView(Method handlerMethod, Class<?> handlerType, Object returnValue,
            ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception {
//       解析@ResponseStatus注解
         ResponseStatus responseStatus = AnnotatedElementUtils.findMergedAnnotation(handlerMethod, ResponseStatus.class);
         if (responseStatus != null) {
            HttpStatus statusCode = responseStatus.code();
            String reason = responseStatus.reason();
            if (!StringUtils.hasText(reason)) {
               webRequest.getResponse().setStatus(statusCode.value());
            }
            else {
               webRequest.getResponse().sendError(statusCode.value(), reason);
            }

            // to be picked up by the RedirectView
            webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, statusCode);
            this.responseArgumentUsed = true;
         }

         // Invoke custom resolvers if present...
         if (customModelAndViewResolvers != null) {
            for (ModelAndViewResolver mavResolver : customModelAndViewResolvers) {
//             解析modelAndView-》
               ModelAndView mav = mavResolver.resolveModelAndView(
                     handlerMethod, handlerType, returnValue, implicitModel, webRequest);
               if (mav != ModelAndViewResolver.UNRESOLVED) {
                  return mav;
               }
            }
         }

         if (returnValue instanceof HttpEntity) {
//          解析HttpEntity响应
            handleHttpEntityResponse((HttpEntity<?>) returnValue, webRequest);
            return null;
         }
//       解析@ResponseBody注解
         else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
//          -》
            handleResponseBody(returnValue, webRequest);
            return null;
         }
         else if (returnValue instanceof ModelAndView) {
//          如果返回值是modelAndView创建并返回
            ModelAndView mav = (ModelAndView) returnValue;
            mav.getModelMap().mergeAttributes(implicitModel);
            return mav;
         }
         else if (returnValue instanceof Model) {
//          返回值是model
            return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap());
         }
         else if (returnValue instanceof View) {
//          返回值是view
            return new ModelAndView((View) returnValue).addAllObjects(implicitModel);
         }
//       解析@ModelAttribute注解
         else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) {
//          -》
            addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
            return new ModelAndView().addAllObjects(implicitModel);
         }
         else if (returnValue instanceof Map) {
//          返回值是map
            return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map<String, ?>) returnValue);
         }
         else if (returnValue instanceof String) {
//          返回值是string
            return new ModelAndView((String) returnValue).addAllObjects(implicitModel);
         }
         else if (returnValue == null) {
//          没有返回值
            // Either returned null or was 'void' return.
            if (this.responseArgumentUsed || webRequest.isNotModified()) {
               return null;
            }
            else {
               // Assuming view name translation...
               return new ModelAndView().addAllObjects(implicitModel);
            }
         }
         else if (!BeanUtils.isSimpleProperty(returnValue.getClass())) {
            // Assume a single model attribute...
            addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
            return new ModelAndView().addAllObjects(implicitModel);
         }
         else {
            throw new IllegalArgumentException("Invalid handler method return value: " + returnValue);
         }
      }

进入方法org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.ServletHandlerMethodInvoker#handleHttpEntityResponse

private void handleHttpEntityResponse(HttpEntity<?> responseEntity, ServletWebRequest webRequest) throws Exception {
         if (responseEntity == null) {
            return;
         }
         HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
         HttpOutputMessage outputMessage = createHttpOutputMessage(webRequest);
         if (responseEntity instanceof ResponseEntity && outputMessage instanceof ServerHttpResponse) {
            ((ServerHttpResponse) outputMessage).setStatusCode(((ResponseEntity<?>) responseEntity).getStatusCode());
         }
         HttpHeaders entityHeaders = responseEntity.getHeaders();
         if (!entityHeaders.isEmpty()) {
            outputMessage.getHeaders().putAll(entityHeaders);
         }
         Object body = responseEntity.getBody();
         if (body != null) {
//          调用转换器-》
            writeWithMessageConverters(body, inputMessage, outputMessage);
         }
         else {
            // flush headers
            outputMessage.getBody();
         }
      }

返回方法org.springframework.web.servlet.DispatcherServlet#applyDefaultViewName

private void applyDefaultViewName(HttpServletRequest request, ModelAndView mv) throws Exception {
   if (mv != null && !mv.hasView()) {
      mv.setViewName(getDefaultViewName(request));
   }
}

进入方法org.springframework.web.servlet.DispatcherServlet#getDefaultViewName

protected String getDefaultViewName(HttpServletRequest request) throws Exception {
   return this.viewNameTranslator.getViewName(request);
}

返回方法org.springframework.web.servlet.HandlerExecutionChain#applyPostHandle

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
      HandlerInterceptor[] interceptors = getInterceptors();
      if (!ObjectUtils.isEmpty(interceptors)) {
         for (int i = interceptors.length - 1; i >= 0; i--) {
            HandlerInterceptor interceptor = interceptors[i];
//          执行业务handler拦截器后置方法
            interceptor.postHandle(request, response, this.handler, mv);
         }
      }
   }

进入方法org.springframework.web.servlet.HandlerExecutionChain#getInterceptors

public HandlerInterceptor[] getInterceptors() {
   if (this.interceptors == null && this.interceptorList != null) {
      this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
   }
   return this.interceptors;
}

进入方法org.springframework.web.servlet.DispatcherServlet#processDispatchResult

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
         HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {

      boolean errorView = false;
      if (exception != null) {
         if (exception instanceof ModelAndViewDefiningException) {
            logger.debug("ModelAndViewDefiningException encountered", exception);
            mv = ((ModelAndViewDefiningException) exception).getModelAndView();
         }
         else {
            Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
//          用异常解析器处理异常-》
            mv = processHandlerException(request, response, handler, exception);
            errorView = (mv != null);
         }
      }

      // Did the handler return a view to render?
      if (mv != null && !mv.wasCleared()) {
         render(mv, request, response);
         if (errorView) {
//          清空绑定 -》
            WebUtils.clearErrorRequestAttributes(request);
         }
      }
      else {
         if (logger.isDebugEnabled()) {
            logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
                  "': assuming HandlerAdapter completed request handling");
         }
      }

//    异步请求,同步直接返回
      if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
         // Concurrent handling started during a forward
         return;
      }

      if (mappedHandler != null) {
//        执行拦截器的处理完成事件 -》
         mappedHandler.triggerAfterCompletion(request, response, null);
      }
   }

进入方法org.springframework.web.servlet.DispatcherServlet#processHandlerException

protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
         Object handler, Exception ex) throws Exception {

      // Check registered HandlerExceptionResolvers...
      ModelAndView exMv = null;
      for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
         exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
         if (exMv != null) {
            break;
         }
      }
      if (exMv != null) {
         if (exMv.isEmpty()) {
            request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
            return null;
         }
         // We might still need view name translation for a plain error model...
         if (!exMv.hasView()) {
//          设置默认视图
            exMv.setViewName(getDefaultViewName(request));
         }
         if (logger.isDebugEnabled()) {
            logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);
         }
//       绑定配置-》
         WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
         return exMv;
      }

      throw ex;
   }

进入方法org.springframework.web.util.WebUtils#exposeErrorRequestAttributes

public static void exposeErrorRequestAttributes(HttpServletRequest request, Throwable ex, String servletName) {
   exposeRequestAttributeIfNotPresent(request, ERROR_STATUS_CODE_ATTRIBUTE, HttpServletResponse.SC_OK);
   exposeRequestAttributeIfNotPresent(request, ERROR_EXCEPTION_TYPE_ATTRIBUTE, ex.getClass());
   exposeRequestAttributeIfNotPresent(request, ERROR_MESSAGE_ATTRIBUTE, ex.getMessage());
   exposeRequestAttributeIfNotPresent(request, ERROR_EXCEPTION_ATTRIBUTE, ex);
   exposeRequestAttributeIfNotPresent(request, ERROR_REQUEST_URI_ATTRIBUTE, request.getRequestURI());
   exposeRequestAttributeIfNotPresent(request, ERROR_SERVLET_NAME_ATTRIBUTE, servletName);
}

返回方法org.springframework.web.util.WebUtils#clearErrorRequestAttributes

public static void clearErrorRequestAttributes(HttpServletRequest request) {
   request.removeAttribute(ERROR_STATUS_CODE_ATTRIBUTE);
   request.removeAttribute(ERROR_EXCEPTION_TYPE_ATTRIBUTE);
   request.removeAttribute(ERROR_MESSAGE_ATTRIBUTE);
   request.removeAttribute(ERROR_EXCEPTION_ATTRIBUTE);
   request.removeAttribute(ERROR_REQUEST_URI_ATTRIBUTE);
   request.removeAttribute(ERROR_SERVLET_NAME_ATTRIBUTE);
}

返回方法org.springframework.web.servlet.HandlerExecutionChain#triggerAfterCompletion

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
         throws Exception {

//    获取拦截器 -》
      HandlerInterceptor[] interceptors = getInterceptors();
      if (!ObjectUtils.isEmpty(interceptors)) {
         for (int i = this.interceptorIndex; i >= 0; i--) {
            HandlerInterceptor interceptor = interceptors[i];
            try {
//             执行拦截器的完成事件
               interceptor.afterCompletion(request, response, this.handler, ex);
            }
            catch (Throwable ex2) {
               logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
            }
         }
      }
   }

进入方法org.springframework.web.servlet.HandlerExecutionChain#getInterceptors

public HandlerInterceptor[] getInterceptors() {
   if (this.interceptors == null && this.interceptorList != null) {
      this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
   }
   return this.interceptors;
}

返回方法org.springframework.web.servlet.DispatcherServlet#triggerAfterCompletion

private void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response,
      HandlerExecutionChain mappedHandler, Exception ex) throws Exception {

   if (mappedHandler != null) {
      mappedHandler.triggerAfterCompletion(request, response, ex);
   }
   throw ex;
}

进入方法org.springframework.web.servlet.HandlerExecutionChain#triggerAfterCompletion

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
         throws Exception {

//    获取拦截器 -》
      HandlerInterceptor[] interceptors = getInterceptors();
      if (!ObjectUtils.isEmpty(interceptors)) {
         for (int i = this.interceptorIndex; i >= 0; i--) {
            HandlerInterceptor interceptor = interceptors[i];
            try {
//             执行拦截器的完成事件
               interceptor.afterCompletion(request, response, this.handler, ex);
            }
            catch (Throwable ex2) {
               logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
            }
         }
      }
   }

返回方法org.springframework.web.servlet.HandlerExecutionChain#applyAfterConcurrentHandlingStarted

void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
   HandlerInterceptor[] interceptors = getInterceptors();
   if (!ObjectUtils.isEmpty(interceptors)) {
      for (int i = interceptors.length - 1; i >= 0; i--) {
         if (interceptors[i] instanceof AsyncHandlerInterceptor) {
            try {
               AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptors[i];
               asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
            }
            catch (Throwable ex) {
               logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex);
            }
         }
      }
   }
}

返回方法org.springframework.web.servlet.DispatcherServlet#restoreAttributesAfterInclude

private void restoreAttributesAfterInclude(HttpServletRequest request, Map<?,?> attributesSnapshot) {
   // Need to copy into separate Collection here, to avoid side effects
   // on the Enumeration when removing attributes.
   Set<String> attrsToCheck = new HashSet<String>();
   Enumeration<?> attrNames = request.getAttributeNames();
   while (attrNames.hasMoreElements()) {
      String attrName = (String) attrNames.nextElement();
      if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
         attrsToCheck.add(attrName);
      }
   }

   // Add attributes that may have been removed
   attrsToCheck.addAll((Set<String>) attributesSnapshot.keySet());
   // Iterate over the attributes to check, restoring the original value
   // or removing the attribute, respectively, if appropriate.
   for (String attrName : attrsToCheck) {
      Object attrValue = attributesSnapshot.get(attrName);
      if (attrValue == null){
         request.removeAttribute(attrName);
      }
      else if (attrValue != request.getAttribute(attrName)) {
         request.setAttribute(attrName, attrValue);
      }
   }
}

往上返回到这个方法org.springframework.web.servlet.FrameworkServlet#service

说到最后

本次源码解析仅代表个人观点,仅供参考。

03-26 22:21