上篇文章講了SpingBoot誕生的歷史背景和技術演進背景,並經過源碼說明了SpringBoot是如何實現零配置的包括如何省去web.xml配置的原理。本文接上一篇文章,經過demo演示SpringBoot是如何內置tomcat並實現基於java配置的Servlet初始化和SpringBoot的啓動流程。html
傳統SpringMVC框架web.xml的配置內容java
1 <web-app> 2 <!-- 初始化Spring上下文 --> 3 <listener> 4 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 5 </listener> 6 <!-- 指定Spring的配置文件 --> 7 <context-param> 8 <param-name>contextConfigLocation</param-name> 9 <param-value>/WEB-INF/app-context.xml</param-value> 10 </context-param> 11 <!-- 初始化DispatcherServlet --> 12 <servlet> 13 <servlet-name>app</servlet-name> 14 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 15 <init-param> 16 <param-name>contextConfigLocation</param-name> 17 <param-value></param-value> 18 </init-param> 19 <load-on-startup>1</load-on-startup> 20 </servlet> 21 <servlet-mapping> 22 <servlet-name>app</servlet-name> 23 <url-pattern>/app/*</url-pattern> 24 </servlet-mapping> 25 </web-app>
查看Spring官方文檔https://docs.spring.io/spring/docs/5.0.14.RELEASE/spring-framework-reference/web.html#spring-webweb
文檔中給出瞭如何使用java代碼實現web.xml配置的examplespring
1 public class MyWebApplicationInitializer implements WebApplicationInitializer { 2 3 @Override 4 public void onStartup(ServletContext servletCxt) { 5 6 // Load Spring web application configuration 7 //經過註解的方式初始化Spring的上下文 8 AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext(); 9 //註冊spring的配置類(替代傳統項目中xml的configuration) 10 ac.register(AppConfig.class); 11 ac.refresh(); 12 13 // Create and register the DispatcherServlet 14 //基於java代碼的方式初始化DispatcherServlet 15 DispatcherServlet servlet = new DispatcherServlet(ac); 16 ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet); 17 registration.setLoadOnStartup(1); 18 registration.addMapping("/app/*"); 19 } 20 }
經過example可見基於java的web.xml的實現apache
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 <groupId>com.shf</groupId> 6 <artifactId>spring-tomcat</artifactId> 7 <version>0.0.1-SNAPSHOT</version> 8 <name>spring-tomcat</name> 9 <description>Demo project for Spring Boot</description> 10 11 <properties> 12 <java.version>1.8</java.version> 13 </properties> 14 15 <dependencies> 16 <dependency> 17 <groupId>org.springframework</groupId> 18 <artifactId>spring-web</artifactId> 19 <version>5.0.8.RELEASE</version> 20 </dependency> 21 <dependency> 22 <groupId>org.apache.tomcat.embed</groupId> 23 <artifactId>tomcat-embed-core</artifactId> 24 <version>8.5.32</version> 25 </dependency> 26 <dependency> 27 <groupId>org.springframework</groupId> 28 <artifactId>spring-context</artifactId> 29 <version>5.0.8.RELEASE</version> 30 </dependency> 31 <dependency> 32 <groupId>org.springframework</groupId> 33 <artifactId>spring-webmvc</artifactId> 34 <version>5.0.8.RELEASE</version> 35 </dependency> 36 </dependencies> 37 38 <build> 39 <plugins> 40 <plugin> 41 <groupId>org.springframework.boot</groupId> 42 <artifactId>spring-boot-maven-plugin</artifactId> 43 </plugin> 44 </plugins> 45 </build> 46 47 </project>
1 package com.shf.tomcat.application; 2 3 4 import org.apache.catalina.LifecycleException; 5 import org.apache.catalina.startup.Tomcat; 6 7 import javax.servlet.ServletException; 8 9 /** 10 * 描述:初始化tomcat 11 * 12 * @Author shf 13 * @Date 2019/5/26 14:58 14 * @Version V1.0 15 **/ 16 public class SpringApplication { 17 public static void run(){ 18 //建立tomcat實例 19 Tomcat tomcat = new Tomcat(); 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 }
該類主要實現Spring的配置,基於java實現spring xml的配置瀏覽器
1 package com.shf.tomcat.web; 2 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.context.annotation.ComponentScan; 5 import org.springframework.context.annotation.Configuration; 6 7 import javax.servlet.http.HttpServlet; 8 9 /** 10 * 描述:java代碼實現相似於spring-context.xml的配置 11 * 12 * @Author shf 13 * @Date 2019/5/22 21:28 14 * @Version V1.0 15 **/ 16 @Configuration 17 @ComponentScan("com.shf.tomcat") 18 public class AppConfig extends HttpServlet { 19 @Bean 20 public String string(){ 21 return new String("hello"); 22 } 23 }
值得一說,該類就是基於java的web.xml的配置tomcat
1 package com.shf.tomcat.web; 2 3 import org.springframework.web.WebApplicationInitializer; 4 import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; 5 import org.springframework.web.servlet.DispatcherServlet; 6 7 import javax.servlet.ServletContext; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRegistration; 10 11 /** 12 * 描述:WebApplicationInitializer實現web.xml的配置 13 * 14 * @Author shf 15 * @Date 2019/5/22 21:25 16 * @Version V1.0 17 **/ 18 public class MyWebApplicationInitializer implements WebApplicationInitializer { 19 public void onStartup(ServletContext servletContext) throws ServletException { 20 System.out.println("初始化 MyWebApplicationInitializer"); 21 //經過註解的方式初始化Spring的上下文 22 AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext(); 23 //註冊spring的配置類(替代傳統項目中xml的configuration) 24 ac.register(AppConfig.class); 25 // ac.refresh(); 26 27 // Create and register the DispatcherServlet 28 //基於java代碼的方式初始化DispatcherServlet 29 DispatcherServlet servlet = new DispatcherServlet(ac); 30 ServletRegistration.Dynamic registration = servletContext.addServlet("/", servlet); 31 registration.setLoadOnStartup(1); 32 registration.addMapping("/*"); 33 } 34 }
該類上篇文章已經講的很清楚了mvc
1 package com.shf.tomcat.web; 2 3 import org.springframework.core.annotation.AnnotationAwareOrderComparator; 4 import org.springframework.util.ReflectionUtils; 5 import org.springframework.web.WebApplicationInitializer; 6 7 import javax.servlet.ServletContainerInitializer; 8 import javax.servlet.ServletContext; 9 import javax.servlet.ServletException; 10 import javax.servlet.annotation.HandlesTypes; 11 import java.lang.reflect.Modifier; 12 import java.util.LinkedList; 13 import java.util.List; 14 import java.util.Set; 15 16 @HandlesTypes(MyWebApplicationInitializer.class) 17 public class MySpringServletContainerInitializer implements ServletContainerInitializer { 18 public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException { 19 List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>(); 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 }
在該文件中配置ServletContainerInitializer的實現類app
寫一個測試類框架
1 package com.shf.tomcat.controller; 2 3 import org.springframework.web.bind.annotation.RequestMapping; 4 import org.springframework.web.bind.annotation.RestController; 5 6 @RestController 7 public class TestController { 8 @RequestMapping("/app/test") 9 public String test(){ 10 System.out.println("--- hello ---"); 11 return "hello"; 12 } 13 }
1 package com.shf.tomcat; 2 3 4 import com.shf.tomcat.application.SpringApplication; 5 6 public class Main { 7 8 public static void main(String[] args) { 9 SpringApplication.run(); 10 } 11 12 }
啓動Main方法
瀏覽器訪問:http://localhost:8080/app/test
4、小結
上篇文章介紹了SpringBoot是如何實現的基於java配置的web.xml。這篇文章咱們經過一個demo來認識SpringBoot就是是如何內置tomcat而且實現零配置的。其實這個demo就像是一個簡易版的SpringBoot的框架,基本模擬了SpringBoot的啓動流程,只是差了SpringBoot最重要的能力---自動裝配。
這兩篇文章嚴格來講不該該算是SpringBoot的源碼篇,可是筆者認爲關於SpringBoot的發展歷史、技術演進路線、及SpringBoot的嵌入式tomcat和code-based web.xml配置也是認識SpringBoot重要的一部分。
下一篇文章正式開始SpringBoot的源碼閱讀之旅。
原文出處:https://www.cnblogs.com/hello-shf/p/10952362.html