一、简介
上篇文章讲了SpingBoot诞生的历史背景和技术演进背景,并通过源码说明了SpringBoot是如何实现零配置的包括如何省去web.xml配置的原理。本文接上一篇文章,通过demo演示SpringBoot是如何内置tomcat并实现基于java配置的Servlet初始化和SpringBoot的启动流程。
二、基于java配置的web.xml实现
传统SpringMVC框架web.xml的配置内容
1
2
3
4 org.springframework.web.context.ContextLoaderListener
5
6
7
8 contextConfigLocation
9 /WEB-INF/app-context.xml
10
11
12
13 app
14 org.springframework.web.servlet.DispatcherServlet
15
16 contextConfigLocation
17
18
19 1
20
21
22 app
23 /app/*
24
25
文档中给出了如何使用java代码实现web.xml配置的example
1 public class MyWebApplicationInitializer implementsWebApplicationInitializer {2
3 @Override4 public voidonStartup(ServletContext servletCxt) {5
6 //Load Spring web application configuration7 //通过注解的方式初始化Spring的上下文
8 AnnotationConfigWebApplicationContext ac = newAnnotationConfigWebApplicationContext();9 //注册spring的配置类(替代传统项目中xml的configuration)
10 ac.register(AppConfig.class);11 ac.refresh();12
13 //Create and register the DispatcherServlet14 //基于java代码的方式初始化DispatcherServlet
15 DispatcherServlet servlet = newDispatcherServlet(ac);16 ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);17 registration.setLoadOnStartup(1);18 registration.addMapping("/app/*");19 }20 }
通过example可见基于java的web.xml的实现
三、代码实现简易版SpringBoot
1、工程目录结构
2、pom.xml依赖
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4 4.0.0
5 com.shf
6 spring-tomcat
7 0.0.1-SNAPSHOT
8 spring-tomcat
9 Demo project for Spring Boot
10
11
12 1.8
13
14
15
16
17 org.springframework
18 spring-web
19 5.0.8.RELEASE
20
21
22 org.apache.tomcat.embed
23 tomcat-embed-core
24 8.5.32
25
26
27 org.springframework
28 spring-context
29 5.0.8.RELEASE
30
31
32 org.springframework
33 spring-webmvc
34 5.0.8.RELEASE
35
36
37
38
39
40
41 org.springframework.boot
42 spring-boot-maven-plugin
43
44
45
46
47
3、初始化tomcat实例
1 packagecom.shf.tomcat.application;2
3
4 importorg.apache.catalina.LifecycleException;5 importorg.apache.catalina.startup.Tomcat;6
7 importjavax.servlet.ServletException;8
9 /**
10 * 描述:初始化tomcat11 *12 * @Author shf13 * @Date 2019/5/26 14:5814 * @Version V1.015 **/
16 public classSpringApplication {17 public static voidrun(){18 //创建tomcat实例
19 Tomcat tomcat = newTomcat();20 //设置tomcat端口
21 tomcat.setPort(8000);22 try{23 //此处随便指定一下webapp,让tomcat知道这是一个web工程
24 tomcat.addWebapp("/", "D:\\");25 //启动tomcat
26 tomcat.start();27 tomcat.getServer().await();28 } catch(LifecycleException e) {29 e.printStackTrace();30 } catch(ServletException e) {31 e.printStackTrace();32 }33 }34 }
4、AppConfig.java
该类主要实现Spring的配置,基于java实现spring xml的配置
1 packagecom.shf.tomcat.web;2
3 importorg.springframework.context.annotation.Bean;4 importorg.springframework.context.annotation.ComponentScan;5 importorg.springframework.context.annotation.Configuration;6
7 importjavax.servlet.http.HttpServlet;8
9 /**
10 * 描述:java代码实现类似于spring-context.xml的配置11 *12 * @Author shf13 * @Date 2019/5/22 21:2814 * @Version V1.015 **/
16 @Configuration17 @ComponentScan("com.shf.tomcat")18 public class AppConfig extendsHttpServlet {19 @Bean20 publicString string(){21 return new String("hello");22 }23 }
5、MyWebApplicationInitializer.java
值得一说,该类就是基于java的web.xml的配置
1 packagecom.shf.tomcat.web;2
3 importorg.springframework.web.WebApplicationInitializer;4 importorg.springframework.web.context.support.AnnotationConfigWebApplicationContext;5 importorg.springframework.web.servlet.DispatcherServlet;6
7 importjavax.servlet.ServletContext;8 importjavax.servlet.ServletException;9 importjavax.servlet.ServletRegistration;10
11 /**
12 * 描述:WebApplicationInitializer实现web.xml的配置13 *14 * @Author shf15 * @Date 2019/5/22 21:2516 * @Version V1.017 **/
18 public class MyWebApplicationInitializer implementsWebApplicationInitializer {19 public void onStartup(ServletContext servletContext) throwsServletException {20 System.out.println("初始化 MyWebApplicationInitializer");21 //通过注解的方式初始化Spring的上下文
22 AnnotationConfigWebApplicationContext ac = newAnnotationConfigWebApplicationContext();23 //注册spring的配置类(替代传统项目中xml的configuration)
24 ac.register(AppConfig.class);25 //ac.refresh();26
27 //Create and register the DispatcherServlet28 //基于java代码的方式初始化DispatcherServlet
29 DispatcherServlet servlet = newDispatcherServlet(ac);30 ServletRegistration.Dynamic registration = servletContext.addServlet("/", servlet);31 registration.setLoadOnStartup(1);32 registration.addMapping("/*");33 }34 }
6、MySpringServletContainerInitializer.java
该类上篇文章已经讲的很清楚了
1 packagecom.shf.tomcat.web;2
3 importorg.springframework.core.annotation.AnnotationAwareOrderComparator;4 importorg.springframework.util.ReflectionUtils;5 importorg.springframework.web.WebApplicationInitializer;6
7 importjavax.servlet.ServletContainerInitializer;8 importjavax.servlet.ServletContext;9 importjavax.servlet.ServletException;10 importjavax.servlet.annotation.HandlesTypes;11 importjava.lang.reflect.Modifier;12 importjava.util.LinkedList;13 importjava.util.List;14 importjava.util.Set;15
16 @HandlesTypes(MyWebApplicationInitializer.class)17 public class MySpringServletContainerInitializer implementsServletContainerInitializer {18 public void onStartup(Set> webAppInitializerClasses, ServletContext servletContext) throwsServletException {19 List initializers = new LinkedList();20
21 if (webAppInitializerClasses != null) {22 for (Class>waiClass : webAppInitializerClasses) {23 if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
24 WebApplicationInitializer.class.isAssignableFrom(waiClass)) {25 try{26 initializers.add((WebApplicationInitializer)27 ReflectionUtils.accessibleConstructor(waiClass).newInstance());28 }29 catch(Throwable ex) {30 throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);31 }32 }33 }34 }35
36 if(initializers.isEmpty()) {37 servletContext.log("No Spring WebApplicationInitializer types detected on classpath");38 return;39 }40
41 servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");42 AnnotationAwareOrderComparator.sort(initializers);43 for(WebApplicationInitializer initializer : initializers) {44 initializer.onStartup(servletContext);45 }46 }47 }
7、META-INF/services/javax.servlet.ServletContainerInitializer
在该文件中配置ServletContainerInitializer的实现类
8、测试类
写一个测试类
1 packagecom.shf.tomcat.controller;2
3 importorg.springframework.web.bind.annotation.RequestMapping;4 importorg.springframework.web.bind.annotation.RestController;5
6 @RestController7 public classTestController {8 @RequestMapping("/app/test")9 publicString test(){10 System.out.println("--- hello ---");11 return "hello";12 }13 }
9、主类
1 packagecom.shf.tomcat;2
3
4 importcom.shf.tomcat.application.SpringApplication;5
6 public classMain {7
8 public static voidmain(String[] args) {9 SpringApplication.run();10 }11
12 }
10、测试
启动Main方法
四、小结
上篇文章介绍了SpringBoot是如何实现的基于java配置的web.xml。这篇文章我们通过一个demo来认识SpringBoot就是是如何内置tomcat并且实现零配置的。其实这个demo就像是一个简易版的SpringBoot的框架,基本模拟了SpringBoot的启动流程,只是差了SpringBoot最重要的能力---自动装配。
这两篇文章严格来说不应该算是SpringBoot的源码篇,但是笔者认为关于SpringBoot的发展历史、技术演进路线、及SpringBoot的嵌入式tomcat和code-based web.xml配置也是认识SpringBoot重要的一部分。
下一篇文章正式开始SpringBoot的源码阅读之旅。