编程语言
首页 > 编程语言> > DispatherServlet 源码解析

DispatherServlet 源码解析

作者:互联网

DispatherServlet 初始化做了什么?

DispatherServletOnRefresh()方法打上断点,可以看到是 Servlet 生命周期 init() 方法一直调用到了 OnRefresh() 方法, OnRefresh() 又调用了 initStrategies() 方法

image-20220403101707090

DispatherServletinitStrategies() 方法中,有9个方法完成了DispatherServlet 的初始化过程

protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}

initMultipartResolver

Multipart:是文件上传的一种格式,这个方法是初始化文件上传时用到的解析器

initLocaleResolver

spring对于国际化的支持,只要是关于一些本地化解析器的初始化,解决语言问题

image-20220403101345607

initHandlerMappings

建立一个请求路径与控制器方法的映射

/**
	 * Initialize the HandlerMappings used by this class.
	 * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
	 * we default to BeanNameUrlHandlerMapping.
	 * 初始化 HandlerMappings,如果 BeanFactory中没有,则使用默认的 BeanNameUrlHandlerMapping
	 */
private void initHandlerMappings(ApplicationContext context) {
  this.handlerMappings = null;
  // detectAllHandlerMappings 探测所有的 HandlerMapping,SpringMVC中父子容器,当前容器没有,则会去父容器探测
  if (this.detectAllHandlerMappings) {
    // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
    Map<String, HandlerMapping> matchingBeans =
      BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
    if (!matchingBeans.isEmpty()) {
      this.handlerMappings = new ArrayList<>(matchingBeans.values());
      // We keep HandlerMappings in sorted order.
      AnnotationAwareOrderComparator.sort(this.handlerMappings);
    }
  }
  else {
    HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
    this.handlerMappings = Collections.singletonList(hm);
  }

  // Ensure we have at least one HandlerMapping, by registering
  // a default HandlerMapping if no other mappings are found.
  // 如果没有发现其他的映射,通过注册一个默认的 HandlerMapping 来确保我们至少有一个 HandlerMapping 
  if (this.handlerMappings == null) {
    this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
  }

  for (HandlerMapping mapping : this.handlerMappings) {
    if (mapping.usesPathPatterns()) {
      this.parseRequestPath = true;
      break;
    }
  }
}

getDefaultStrategies 就是去类路径下读取 DispatcherServlet.properties 这个文件

image-20220403121946612

DispatcherServlet.properties 中定义了三个 HandlerMappiingimage-20220403122203809

将这三个 HandlerMapping 的实现类加入到 DispatcherServlet 的成员变量 handlerMappings

image-20220403124413127

这里为了测试方便,直接将 RequestMappingHandlerMapping 注入到 IOC 容器中

@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping(){
  return new RequestMappingHandlerMapping();
}

从容器中获取 RequestMappingHandlerMapping 对象,获得路径与控制器方法的映射关系

// 作用 解析 @RequestMapping 以及派生注解,生成路径与控制器方法的映射关系,在初始化时就生成
RequestMappingHandlerMapping requestMappingHandlerMapping = ac.getBean(RequestMappingHandlerMapping.class);
/*
            RequestMappingInfo:请求参数,请求路径,请求方式 封装在该对象中
            HandlerMethod:哪个控制器的哪个方法
*/
Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
handlerMethods.forEach((k, v) -> {
  logger.debug("K:{}==V:{}",k,v);
});

结果:

也就是解析了我们自己写的 Controller1 这个控制器

image-20220403125756899
/*
            请求来了,获取控制器方法
            HandlerExecutionChain:处理器执行链,封装了 handlerMethods 以及一些拦截器
*/
HandlerExecutionChain chain = requestMappingHandlerMapping.getHandler(new MockHttpServletRequest("GET", "/test1"));
logger.debug("{}",chain);

执行结果:

image-20220403131135332

找到一个执行链,Controller1中 test1方法,并且没有拦截器

getHandlerMethods:是去 RequestMappingHandlerMapping 对象的成员变量 mappingRegistry 中获取并进一步封装,这个 mappingRegistry 是什么时候初始化的呢?

可以看到 RequestMappingHandlerMapping 是继承了 RequestMappingHandlerMapping ,在 RequestMappingHandlerMapping 中有一个方法:afterPropertiesSet()afterPropertiesSet() 是在Spring Bean生命周期过程中自动调用的,mappingRegistry 初始化就是在这个方法中完成的

image-20220403134104422

执行链:

afterPropertiesSet -> initHandlerMethods() -> processCandidateBean(beanName) -> detectHandlerMethods(beanName) -> registerHandlerMethod(handler, invocableMethod, mapping)

initHandlerAdapters

initHandlerExceptionResolvers

标签:HandlerMapping,控制器,解析,handlerMappings,源码,RequestMappingHandlerMapping,context,Di
来源: https://www.cnblogs.com/jalivv/p/16095747.html