【SpringMvc执行流程】SpringMvc中RequestCondition的作用(三)

初始化

springmvc初始化时,会回调RequestMappingHandlerMapping中的afterPropertiesSet方法。

@Override
public void afterPropertiesSet() {
    initHandlerMethods();
}

追踪到initHandlerMethods

if (beanType != null && isHandler(beanType)) {
    detectHandlerMethods(beanName);
}
  • isHander(beanType)见名知意,是对beanType类型判断,具体实现代码为
    protected boolean isHandler(Class<?> beanType) {
      return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
              AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
    }
    最关键的是detectHandlerMethods(beanName)
    负责对所有的controller类进行处理
    Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
      (MethodIntrospector.MetadataLookup<T>) method -> {
              return getMappingForMethod(method, userType);
      });
  • method为方法名,userType为当前处理的类。遍历该类中的所有方法,对方法进行参数路径请求方式等就行处理。
    下面看下getMappingForMethod是如何对不同方法进行处理的。
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
      RequestMappingInfo info = createRequestMappingInfo(method);
      if (info != null) {
          RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType); //handlerType 是类 这里为了解决类上的@RequestMapping使用
          if (typeInfo != null) {
              info = typeInfo.combine(info);
          }
      }
      return info;
    }

可以看出为每个方法都创建了一个RequestMappingInfo,而RequestMappingInfo正是RequestCondition集合,记录了请路径、参数、方式、头等。可以看下对象内容

private final MyPatternsRequestCondition patternsCondition;

private final MyRequestMethodsRequestCondition methodsCondition;

private final MyParamsRequestCondition paramsCondition;

private final MyHeadersRequestCondition headersCondition;

private final MyConsumesRequestCondition consumesCondition;

private final MyProducesRequestCondition producesCondition;

private final MyRequestConditionHolder customConditionHolder;

获取后的RequestMappingInfo会注册到HandlerMethod中

methods.forEach((method, mapping) -> {
    Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
    registerHandlerMethod(handler, invocableMethod, mapping);
});

最终注册到mappingRegistry

protected void registerHandlerMethod(Object handler, Method method, T mapping) {
    this.mappingRegistry.register(mapping, handler, method);
    System.out.println("ssss");
}

客户端发起请求

当客户端发起请求后,tomcat的servlet会转发到DispatcherServlet的servce函数回调。经过doDispatch,getHandler,再到AbstractHandlerMapping的getHandler,getHandlerInternal,lookupHandlerMethod
看下lookupHandlerMethod代码

    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        List<Match> matches = new ArrayList<>();
        List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
        }

这时,看到了我们初始化时,加载的mappingRegistry,这时就能匹配成功,找到对应的方法。


文章作者: Ciwei
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Ciwei !
 上一篇
【SpringMvc执行流程】springMvc请求如何获取相关HandlerMapping(四) 【SpringMvc执行流程】springMvc请求如何获取相关HandlerMapping(四)
在Servlet如何关联spring中,说过当请求来后会被转发到springDispatcherServlet类中的doService方法。 @Override protected void doService(HttpServletR
2019-07-20
下一篇 
【SpringMvc执行流程】SpringMvc初始化handlerMapping(二) 【SpringMvc执行流程】SpringMvc初始化handlerMapping(二)
前面我们分析了spring如何接入Servlet,执行onRefresh方法,而HandlerMapping的初始化就在OnRefresh中调用。 protected void onRefresh(ApplicationCont
2019-07-20
  目录