当前位置 : 主页 > 编程语言 > java >

Spring5 MVC——从映射关系里获取处理请求的逻辑实例

来源:互联网 收集:自由互联 发布时间:2023-02-04
SpringMVC的核心流程 建立请求和Controller方法的映射集合的流程。 根据请求查找对应的Controller方法的流程。 请求参数绑定到方法形参,执行方法处理请求,返回结果进行视图渲染的流程

SpringMVC的核心流程

  • 建立请求和Controller方法的映射集合的流程。

  • 根据请求查找对应的Controller方法的流程。

  • 请求参数绑定到方法形参,执行方法处理请求,返回结果进行视图渲染的流程。

RequestMappingHandlerMapping继承类图

HandlerMapping

HandlerMapping接口作用是将请求映射到处理程序,以及预处理和处理后的拦截器列表,映射是基于一些标准的,其中的细节因不同的实现而不相同。这是官方文档上一段描述,该接口只有一个方法getHandler(request),返回一个HandlerExecutionChain对象,接口本身很简单。

public interface HandlerMapping { String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler"; String LOOKUP_PATH = HandlerMapping.class.getName() + ".lookupPath"; String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping"; String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern"; String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping"; String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables"; String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables"; String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes"; // 返回请求的一个处理程序handler和拦截器interceptors @Nullable HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception; }

HandlerExecutionChain

HandlerExecutionChain 是Handler执行链,包含handler Object、interceptor。所以HandlerExecutionChain 提供了getHandler、getInterceptors方法,配置文件中配置的interceptor都会加入到HandlerExecutionChain。

public class HandlerExecutionChain { //handler实例 private final Object handler; //一组拦截器实例 @Nullable private HandlerInterceptor[] interceptors; //HandlerInterceptor的链表 @Nullable private List<HandlerInterceptor> interceptorList; ...... }

AbstractHandlerMapping

从类图中可知,HandlerMapping主要由AbstractHandlerMapping实现。

public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware { @Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //获取handler的具体逻辑,留给子类实现 Object handler = getHandlerInternal(request); // 如果获取到的handler为null,则采用默认的handler,即属性defaultHandler if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { //如果连DefaultHandler也为空,则直接返回空 return null; } // Bean name or resolved handler? //如果handler是beanName,从容器里获取对应的bean if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } //根据handler和request获取处理器链HandlerExecutionChain HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (logger.isTraceEnabled()) { logger.trace("Mapped to " + handler); } else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) { logger.debug("Mapped to " + executionChain.getHandler()); } if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) { CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); config = (config != null ? config.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; } }

  • 用户发起请求,会进入到AbstractHandlerMapping类中的getHandler方法中。

  • 沿着方法的调用栈发现,请求先经过FrameworkServlet的service方法去处理。

  • 在由HttpServlet的service方法转发到FrameworkServlet的doPost方法中。

  • doPost方法中会调用FrameworkServlet的processRequest方法。

  • processRequest方法会调用DispatcherServlet的doService方法。

  • doService方法会调用DispatcherServlet的doDispatch方法。

  • doDispatch方法会调用到DispatcherServlet的getHandler方法。

  • DispatcherServlet的getHandler方法会调用到AbstractHandlerMapping中的getHandler方法。

DispatcherServlet#doDispatch

public class DispatcherServlet extends FrameworkServlet { 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. // 根据当前request获取HandlerExecutionChain, // HandlerExecutionChain中包含了请求url,以及对应的controller以及controller中的方法 mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. // 通过HandlerExecutionChain获取对应的适配器,adapter负责完成参数解析 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. //处理GET、HEAD请求的Last-modified String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } // 遍历所有定义的 interceptor,执行 preHandle 方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. // 调用目标Controller中的方法 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } // 处理成默认视图名,也就是添加前缀和后缀等 applyDefaultViewName(processedRequest, mv); // 拦截器postHandle方法进行处理 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); } } } } }

DispatcherServlet#getHandler

  • 根据request信息uri找到对应HandlerExecutionChain执行链,HandlerExecutionChain中包含了请求url,以及对应的controller以及controller中的方法。
public class DispatcherServlet extends FrameworkServlet { @Nullable protected 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; } }
  • 该方法会依次调用DispatcherServlet类中的成员变量List<HandlerMapping> handlerMappings中的HandlerMapping的实现类的getHandler方法。

handlerMappings中包含4个HandlerMapping的实现类

  • requestMappingHandlerMapping -> RequestMappingHandlerMapping
  • beanNameHandlerMapping -> BeanNameUrlHandlerMapping
  • routerFunctionMapping -> RouterFunctionMapping
  • defaultServletHandlerMapping -> SimpleUrlHandlerMapping

这里主要关注RequestMappingHandlerMapping

  • 因为其他的HandlerMapping实现类并不会对主流的RequestMapping注解进行处理。
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware { @Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //获取handler的具体逻辑,留给子类实现 Object handler = getHandlerInternal(request); // 如果获取到的handler为null,则采用默认的handler,即属性defaultHandler if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { //如果连DefaultHandler也为空,则直接返回空 return null; } // Bean name or resolved handler? //如果handler是beanName,从容器里获取对应的bean if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } //根据handler和request获取处理器链HandlerExecutionChain HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (logger.isTraceEnabled()) { logger.trace("Mapped to " + handler); } else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) { logger.debug("Mapped to " + executionChain.getHandler()); } if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) { CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); config = (config != null ? config.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; } }

getHandlerInternal

  • 从AbstractHandlerMapping的子类方法实现里获取到真正的Handler实例。
public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo> { @Override protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); try { return super.getHandlerInternal(request); } finally { ProducesRequestCondition.clearMediaTypesAttribute(request); } } } public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean { @Override protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { // 获取 request 中的 url,用来匹配 handler String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); request.setAttribute(LOOKUP_PATH, lookupPath); this.mappingRegistry.acquireReadLock(); try { // 根据路径寻找 Handler,并封装成 HandlerMethod HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); // 根据 handlerMethod 中的 bean 来实例化 Handler,并添加进 HandlerMethod return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } } }

AbstractHandlerMethodMapping#lookupHandlerMethod

  • 根据路径寻找Handler,并封装成 HandlerMethod
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean { @Nullable protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List<Match> matches = new ArrayList<>(); // 通过 lookupPath 属性中查找。如果找到了,就返回对应的RequestMappingInfo List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { // 如果匹配到了,检查其他属性是否符合要求,如请求方法,参数,header 等 addMatchingMappings(directPathMatches, matches, request); } if (matches.isEmpty()) { // No choice but to go through all mappings... // 没有直接匹配到,则遍历所有的处理方法进行通配符匹配 addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); } if (!matches.isEmpty()) { Match bestMatch = matches.get(0); // 如果有多个匹配的,会找到第二个最合适的进行比较 if (matches.size() > 1) { // 如果方法有多个匹配,不同的通配符等,则排序选择出最合适的一个 Comparator<Match> comparator = new MatchComparator(getMappingComparator(request)); matches.sort(comparator); bestMatch = matches.get(0); if (logger.isTraceEnabled()) { logger.trace(matches.size() + " matching mappings: " + matches); } if (CorsUtils.isPreFlightRequest(request)) { return PREFLIGHT_AMBIGUOUS_MATCH; } Match secondBestMatch = matches.get(1); if (comparator.compare(bestMatch, secondBestMatch) == 0) { Method m1 = bestMatch.handlerMethod.getMethod(); Method m2 = secondBestMatch.handlerMethod.getMethod(); String uri = request.getRequestURI(); throw new IllegalStateException( "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}"); } } request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); // 设置 request 参数(RequestMappingHandlerMapping 对其进行了覆写) handleMatch(bestMatch.mapping, lookupPath, request); // 返回匹配的 url 的处理的方法 return bestMatch.handlerMethod; } else { // 调用 RequestMappingHandlerMapping 类的 handleNoMatch 方法再匹配一次 return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } } }

AbstractHandlerMapping#getHandlerExecutionChain

  • 根据handler和request获取处理器链HandlerExecutionChain
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware { protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { //判断handler是不是执行器链,如果不是则创建一个执行器链 HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH); //包装拦截器 /** * <mvc:interceptor> * <mvc:mapping path="/shopadmin/**" /> * <bean id="ShopInterceptor" * class="com.imooc.o2o.interceptor.shopadmin.ShopLoginInterceptor" /> * </mvc:interceptor> */ for (HandlerInterceptor interceptor : this.adaptedInterceptors) { if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; } }

到此,根据请求查找对应的Controller方法的流程就梳理完毕了。

网友评论