> 文档中心 > Spring Mvc源码解析

Spring Mvc源码解析


WebMvcAutoConfiguration SpringMvc自动注入类

//当前为配置类@Configuration(proxyBeanMethods = false)//当前应用必须为web应用@ConditionalOnWebApplication(type = Type.SERVLET)//必须存在  Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class//主要的入口为DispatcherServlet.class@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })//确保springbean中未注册多个WebMvcConfigurationSupport.class@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)//优先级@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,ValidationAutoConfiguration.class })public class WebMvcAutoConfiguration {

DispatcherServlet

//DispatcherServlet 继承 FrameworkServlet //而FrameworkServlet 继承httpServletBean//继承httpServletBean => httpServlet,所以DispatcherServlet 有 Servlet// 原生的方法  doGet doPostpublic class DispatcherServlet extends FrameworkServlet {

DispatcherServlet 继承关系

FrameworkServlet重写doGet、doPost等方法,这里就是我们在请求的时候进行转发的地方,当我们进行GET、POST等方法的时候会进入调用 processRequest(request, response);

processRequest(request, response),调用此方法后,加载对应的属性,调用doService(request, response)方法进行处理逻辑

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null;LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();LocaleContext localeContext = buildLocaleContext(request);RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());initContextHolders(request, localeContext, requestAttributes);try {     //主要的执行方法doService(request, response);}catch (ServletException | IOException ex) {failureCause = ex;throw ex;}catch (Throwable ex) {failureCause = ex;throw new NestedServletException("Request processing failed", ex);}finally {resetContextHolders(request, previousLocaleContext, previousAttributes);if (requestAttributes != null) {requestAttributes.requestCompleted();}logResult(request, response, failureCause, asyncManager);publishRequestHandledEvent(request, response, startTime, failureCause);}}

doService(HttpServletRequest request, HttpServletResponse response) 进入到当前方法中,调用最终执行方法 doDispatch(request, response);

//方法存在于 DispatcherServlet.class 中@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {    logRequest(request);    // Keep a snapshot of the request attributes in case of an include,    // to be able to restore the original attributes after the include.    Map attributesSnapshot = null;    if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap(); Enumeration attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) {     String attrName = (String) attrNames.nextElement();     if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {  attributesSnapshot.put(attrName, request.getAttribute(attrName));     } }    }    // Make framework objects available to handlers and view objects.    request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());    request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);    request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);    request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());    if (this.flashMapManager != null) { FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap != null) {     request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);    }    RequestPath previousRequestPath = null;    if (this.parseRequestPath) { previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE); ServletRequestPathUtils.parseAndCache(request);    }    try { //最终执行逻辑方法 doDispatch(request, response);    }    finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {     // Restore the original attribute snapshot, in case of an include.     if (attributesSnapshot != null) {  restoreAttributesAfterInclude(request, attributesSnapshot);     } } if (this.parseRequestPath) {     ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request); }    }}

doDispatch(request, response); 获取控制器,获取控制器对应的适配器,控制器执行解析数据生成modelAndView视图

checkMultipart(request):检查是否存在文件上传

getHandler(processedRequest):获取Handel 控制器

getHandlerAdapter(mappedHandler.getHandler()):获取控制器适配器

ha.handle(processedRequest, response,

mappedHandler.getHandler()):执行控制器获取modelAndView

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {    HttpServletRequest processedRequest = request;    HandlerExecutionChain mappedHandler = null;    boolean multipartRequestParsed = false;    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);    try { ModelAndView mv = null; Exception dispatchException = null; try {     //检查是否存在文件上传     processedRequest = checkMultipart(request);     multipartRequestParsed = (processedRequest != request);     // Determine handler for the current request.     //获取对应的控制器handel     mappedHandler = getHandler(processedRequest);     if (mappedHandler == null) {  noHandlerFound(processedRequest, response);  return;     }     // Determine handler adapter for the current request.     //获取Handel的适配器Adapter     HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());     // Process last-modified header, if supported by the handler.     String method = request.getMethod();     boolean isGet = HttpMethod.GET.matches(method);     if (isGet || HttpMethod.HEAD.matches(method)) {  long lastModified = ha.getLastModified(request, mappedHandler.getHandler());  if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {      return;  }     }     if (!mappedHandler.applyPreHandle(processedRequest, response)) {  return;     }     // Actually invoke the handler.     // 执行控制器方法,返回modelAndView     mv = ha.handle(processedRequest, response, mappedHandler.getHandler());     if (asyncManager.isConcurrentHandlingStarted()) {  return;     }     applyDefaultViewName(processedRequest, mv);     // 执行中通知     mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) {     dispatchException = ex; } catch (Throwable err) {     // As of 4.3, we're processing Errors thrown from handler methods as well,     // making them available for @ExceptionHandler methods and other scenarios.     dispatchException = new NestedServletException("Handler dispatch failed", err); } //业务完成通知 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);    }    catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex);    }    catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler,   new NestedServletException("Handler processing failed", err));    }    finally { if (asyncManager.isConcurrentHandlingStarted()) {     // Instead of postHandle and afterCompletion     if (mappedHandler != null) {  mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);     } } else {     // Clean up any resources used by a multipart request.     if (multipartRequestParsed) {  cleanupMultipart(processedRequest);     } }    }}

getHandler(processedRequest) 获取控制器,循环遍历获取到对应的handel控制器

@Nullableprotected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {for (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;}

handlerMappings 获取对应的handel

我们以requestMappingHandelMapping为例,当前控制器中存放的是我们注解@RequestMapping 所标记的地址,如下图,我当前controller有两个get方法,分别是user 和 testLock

我们可以看内部的实现类是我们创建类且下面对应的方法

getHandlerAdapter(Object handler):this.handlerAdapters 能过 adapter.supports(handler) 获取适配handel 的 adapter 适配器

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {if (this.handlerAdapters != null) {     //循环获取匹配handel对应的adapterfor (HandlerAdapter adapter : this.handlerAdapters) {if (adapter.supports(handler)) {return adapter;}}}throw new ServletException("No adapter for handler [" + handler +"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");}

ha.handle(processedRequest, response, mappedHandler.getHandler()):

@Override@Nullable//调用的为 HttpRequestHandlerAdapter => handlepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)    throws Exception {//调用最终执行方法    ((HttpRequestHandler) handler).handleRequest(request, response);    return null;}

((HttpRequestHandler) handler).handleRequest(request, response) 执行方法

@Override//调用的为 RequestMappingHandlerAdapter => handleInternalprotected ModelAndView handleInternal(HttpServletRequest request,   HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {    ModelAndView mav;    checkRequest(request);    // Execute invokeHandlerMethod in synchronized block if required.    // 检查是否需要在枷锁条件下执行    if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) {     Object mutex = WebUtils.getSessionMutex(session);     synchronized (mutex) {  mav = invokeHandlerMethod(request, response, handlerMethod);     } } else {     // No HttpSession available -> no mutex necessary     mav = invokeHandlerMethod(request, response, handlerMethod); }    }    else { // No synchronization on session demanded at all... // 不需要加锁执行此方法 mav = invokeHandlerMethod(request, response, handlerMethod);    }    if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {     applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else {     prepareResponse(response); }    }    return mav;}

invokeHandlerMethod(request, response, handlerMethod)

@Nullableprotected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {    ServletWebRequest webRequest = new ServletWebRequest(request, response);    try { WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);  //加载数据解析器 如@RequestParam等数据解析注解 if (this.argumentResolvers != null) {     invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } // 返回值处理器 if (this.returnValueHandlers != null) {     invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) {     Object result = asyncManager.getConcurrentResult();     mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];     asyncManager.clearConcurrentResult();     LogFormatUtils.traceDebug(logger, traceOn -> {  String formatted = LogFormatUtils.formatValue(result, !traceOn);  return "Resume with async result [" + formatted + "]";     });     invocableMethod = invocableMethod.wrapConcurrentResult(result); } //数据获取 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) {     return null; } return getModelAndView(mavContainer, modelFactory, webRequest);    }    finally { webRequest.requestCompleted();    }}

this.argumentResolvers 参数解析器,如requestParamMethodArgumentResolver解析的是注解为@RequestParam相关参数 PathVariableMethodArgumentResolver解析的是注解为@PathVariable 参数,其他依次类推

this.returnValueHandlers 返回值处理器,如reqeustResponseBodyMethodProcessor解析的是注解为@ResponseBody返回JSON数据格式,其他依次类推

invocableMethod.invokeAndHandle(webRequest, mavContainer); 数据获取方法

//ServletInvocableHandlerMethod => invokeAndHandlepublic void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {    //获取返回值    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);    setResponseStatus(webRequest);    if (returnValue == null) { if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {     disableContentCachingIfNecessary(webRequest);     mavContainer.setRequestHandled(true);     return; }    }    else if (StringUtils.hasText(getResponseStatusReason())) { mavContainer.setRequestHandled(true); return;    }    mavContainer.setRequestHandled(false);    Assert.state(this.returnValueHandlers != null, "No return value handlers");    try { this.returnValueHandlers.handleReturnValue(     returnValue, getReturnValueType(returnValue), mavContainer, webRequest);    }    catch (Exception ex) { if (logger.isTraceEnabled()) {     logger.trace(formatErrorForReturnValue(returnValue), ex); } throw ex;    }}

invokeForRequest(webRequest, mavContainer, providedArgs); 获取接口返回值

@Nullablepublic Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception { //实际执行方法Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);if (logger.isTraceEnabled()) {logger.trace("Arguments: " + Arrays.toString(args));}return doInvoke(args);}

getMethodArgumentValues(request, mavContainer, providedArgs); 数据获取

//HandlerMethod => getMethodArgumentValuesprotected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {    //获取所以参数方法 类型和注解等信息    MethodParameter[] parameters = getMethodParameters();    if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS;    }    // 遍历参数方法信息,获取注解对应参数值    Object[] args = new Object[parameters.length];    for (int i = 0; i < parameters.length; i++) { //获取当前参数详细 MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);  //找到提供参数 args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null) {     continue; } if (!this.resolvers.supportsParameter(parameter)) {     throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } try {     //获取参数解析器     args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception ex) {     // Leave stack trace for later, exception may actually be resolved and handled...     if (logger.isDebugEnabled()) {  String exMsg = ex.getMessage();  if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {      logger.debug(formatArgumentError(parameter, exMsg));  }     }     throw ex; }    }    return args;}

所有参数对象详细信息

this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); 获取参数解析器

@Override@Nullablepublic Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { //获取控制器方法的参数解析器HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);if (resolver == null) {throw new IllegalArgumentException("Unsupported parameter type [" +parameter.getParameterType().getName() + "]. supportsParameter should be called first.");}return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);}

getArgumentResolver(parameter);

@Nullable//HandlerMethodArgumentResolverComposite => getArgumentResolverprivate HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {    //参数方法对象获取对应的参数解析器 -》 缓存获取    HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);    if (result == null) { //缓存中不存在时,遍历获取当前参数解析器 for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {     if (resolver.supportsParameter(parameter)) {  result = resolver;  this.argumentResolverCache.put(parameter, result);  break;     } }    }    return result;}

就此整个请求及参数获取相关内容就是这些,如有错误理解地方,望各位大佬指导指导。

谢谢观看!!!!!

在线等待指导!!!!

天天排行榜