初始化阶段
首先找到 DispatcherServlet 这个类,必然是寻找 init()方法。然后,我们发现其 init 方法其实在父类 HttpServletBean 中又 调 用 了 一 个 重 要 的 initServletBean() 方 法最后有调用了
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);//初始化九大组件
}
HandlerMapping 的 子 类 AbstractDetectingUrlHandlerMapping 实现了 initApplicationContext()方法
/** * 建立当前 ApplicationContext 中的所有 Controller 和 url 的对应关系 */ protected void detectHandlers() throws BeansException { ApplicationContext applicationContext = obtainApplicationContext(); if (logger.isDebugEnabled()) { logger.debug("Looking for URL mappings in application context: " + applicationContext); } // 获取 ApplicationContext 容器中所有 bean 的 Name String[] beanNames = (this.detectHandlersInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) : applicationContext.getBeanNamesForType(Object.class)); // 遍历 beanNames,并找到这些 bean 对应的 url for (String beanName : beanNames) { // 找 bean 上的所有 url(Controller 上的 url+方法上的 url),该方法由对应的子类实现 String[] urls = determineUrlsForHandler(beanName); if (!ObjectUtils.isEmpty(urls)) { // 保存 urls 和 beanName 的对应关系,put it to Map<urls,beanName>, // 该方法在父类 AbstractUrlHandlerMapping 中实现 registerHandler(urls, beanName); } else { if (logger.isDebugEnabled()) { logger.debug("Rejected bean name '" + beanName + "': no URL paths identified"); } } } } /** 获取 Controller 中所有方法的 url,由子类实现,典型的模板模式 **/ protected abstract String[] determineUrlsForHandler(String beanName);
运行调用阶段
这一步步是由请求触发的,所以入口为 DispatcherServlet 的核心方法为 doService(), doService()中的核心逻辑由 doDispatch()实现,控制请求的转发
getHandler取得处理当前请求的 Controller,这里也称为 hanlder处理器。handleInternal()拼接 Controller 的 url 和方法的 url,与 Request 的 url 进行匹配,找到匹配的方法