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

相关文章
相关标签/搜索