SpringBoot源碼篇:Spring5內置tomcat實現code-based的web.xml實現

1、簡介

  上篇文章講了SpingBoot誕生的歷史背景和技術演進背景,並經過源碼說明了SpringBoot是如何實現零配置的包括如何省去web.xml配置的原理。本文接上一篇文章,經過demo演示SpringBoot是如何內置tomcat並實現基於java配置的Servlet初始化和SpringBoot的啓動流程。html

2、基於java配置的web.xml實現

傳統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

3、代碼實現簡易版SpringBoot

 一、工程目錄結構

二、pom.xml依賴

 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>

 

三、初始化tomcat實例

 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 }

 

四、AppConfig.java

該類主要實現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 }

 

五、MyWebApplicationInitializer.java

 值得一說,該類就是基於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 }

 

六、MySpringServletContainerInitializer.java

該類上篇文章已經講的很清楚了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 }

 

 

七、META-INF/services/javax.servlet.ServletContainerInitializer

在該文件中配置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

相關文章
相關標籤/搜索