SpringBoot是如何配置DispatcherServlet的

SpringMVC的核心入口就是DispatcherServlet,无论是通过web.xml 还是 JavaConfig的方式配置,都是要遵循Servlet规范的,即想要动态的添加配置一个Servlet本质上最终还是通过 ServletContext.addServlet(),虽然有了SpringMVC一般很少有需要直接编写Servlet,但是对于理解原理还是很必要的

配置Servlet的方法有许多方式:
1. web.xml静态配置servlet
2. ServletContainerInitializer编码动态注册
3. 注解@WebServlet (v3.0+)

SpringMVC: WebApplicationInitializer

Servlet3提供了ServletContainerInitializer接口来支持动态的注册Servlet/Filter/Listener

spring-web模块里的SpringServletContainerInitializer实现并抽象出新的接口:WebApplicationInitializer

所以,它的存在基本替代web.xml配置,在初始化的时候注册并配置容器上下文,官方doc的示例:

public class MyWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletCxt) {
        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        ac.register(AppConfig.class);
        ac.refresh();
        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");
    }
}

为了简化DispatcherServlet的基本千篇一律的配置,也提供了AbstractAnnotationConfigDispatcherServletInitializer直接继承实现对应的配置类列表相关方法即可

SpringBoot: ServletContextInitializer

SpringBoot没有选择hook到Servlet规范里的的生命周期,而是抽象出自己的接口来配置嵌入的容器,把Servlet/Filter/Listener这些变成Spring Bean一样去配置

ServletContainerInitializer 生命周期是归Servlet容器管理
ServletContextInitializer 他是Spring自己管理

SpringBoot应用一般都是embbed server,默认不会去走Servlet那一套,所以想配置Servlet就是通过ServletContextInitializer或者其子类来实现注册

源码的大概流程

  1. SpringApplication.run();

  2. ServletWebServerApplicationContext#onRefresh() -> createWebServer()

创建嵌入的servlet容器的时候(默认tomcat),new TomcatWebServer()构造函数里执行了初始化initialize(),也就是日志里比较标志性的一行 Tomcat initialized with port(s): 8080 (http)

  1. Tomcat#start() -> LifecycleBase#start()
    -> StandardService#startInternal() -> StandardEngine#startInternal() -> ContainerBase#startInternal()

然后提交了异步的FutureTask,就是startStopExecutor.submit(new StartChild(children[i])),TomcatEmbeddedContext#start()的时候会执行他的ServletContextInitializer列表

ServletWebServerApplicationContext里有一个实现的ServletContextInitializer逻辑:

private void selfInitialize(ServletContext servletContext) throws ServletException {
    prepareWebApplicationContext(servletContext);
    registerApplicationScope(servletContext);
    WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
    // 这里就是完成各种Servlet Filter Listener的注册关键逻辑
    for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
        beans.onStartup(servletContext);
    }
}

getServletContextInitializerBeans()逻辑就是从BeanFactory里获取指定类型的Bean列表,当然这其中就包含了一个DispatcherServletRegistrationBean,这个Bean的配置是在DispatcherServletAutoConfiguration里配置的

总结

  1. DispatcherServletAutoConfiguration配置相应的Bean
  2. 内嵌容器start,然后会执行当然上下文里ServletContextInitializer类型的Bean完成初始化&配置
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容