springboot部署到tomcat启动,以及线上部署,源码分析

1.项目环境说明:

tomcat8.5.11, springboot 1.5.6.RELEASE,maven3.3.9

2.war包eclipse配置tomcat启动。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.xxx</groupId>
    <artifactId>xxx-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
  </parent>
  <artifactId>service</artifactId>
  
  <packaging>war</packaging>
  
  <properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<transaction.version>4.0.4</transaction.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
        </dependency>
        <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
		</plugins>
		<finalName>provider</finalName>
	</build>
</project>

Application代码修改

@SpringBootApplication
@EnableTransactionManagement
@EnableScheduling
@EnableAutoConfiguration
public class Application  extends SpringBootServletInitializer {
	
	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(Application.class);
	}

}

3.war包tomcat线上部署

eclipse export war包。

把war包放到tomcat webapps目录下。

bin目录下./startup.sh

4.源码分析

jar包:执行SpringBoot主类的main方法,启动ioc容器,创建嵌入式的Servlet容器;

war包:启动服务器,服务器启动SpringBoot应用【SpringBootServletInitializer】,启动ioc容器;


servlet3.0(Spring注解版):

8.2.4 Shared libraries / runtimes pluggability:

规则:

	1)、服务器启动(web应用启动)会创建当前web应用里面每一个jar包里面ServletContainerInitializer实例:

	2)、ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下,有一个名为javax.servlet.ServletContainerInitializer的文件,内容就是ServletContainerInitializer的实现类的全类名

	3)、还可以使用@HandlesTypes,在应用启动的时候加载我们感兴趣的类;



流程:

1)、启动Tomcat

2)、org\springframework\spring-web\4.3.14.RELEASE\spring-web-4.3.14.RELEASE.jar!\META-INF\services\javax.servlet.ServletContainerInitializer:

Spring的web模块里面有这个文件:org.springframework.web.SpringServletContainerInitializer

3)、SpringServletContainerInitializer将@HandlesTypes(WebApplicationInitializer.class)标注的所有这个类型的类都传入到onStartup方法的Set<Class<?>>;为这些WebApplicationInitializer类型的类创建实例;

4)、每一个WebApplicationInitializer都调用自己的onStartup;



5)、相当于我们的SpringBootServletInitializer的类会被创建对象,并执行onStartup方法

6)、SpringBootServletInitializer实例执行onStartup的时候会createRootApplicationContext;创建容器

    protected WebApplicationContext createRootApplicationContext(
          ServletContext servletContext) {
        //1、创建SpringApplicationBuilder
       SpringApplicationBuilder builder = createSpringApplicationBuilder();
       StandardServletEnvironment environment = new StandardServletEnvironment();
       environment.initPropertySources(servletContext, null);
       builder.environment(environment);
       builder.main(getClass());
       ApplicationContext parent = getExistingRootWebApplicationContext(servletContext);
       if (parent != null) {
          this.logger.info("Root context already created (using as parent).");
          servletContext.setAttribute(
                WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, null);
          builder.initializers(new ParentContextApplicationContextInitializer(parent));
       }
       builder.initializers(
             new ServletContextApplicationContextInitializer(servletContext));
       builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class);
        
        //调用configure方法,子类重写了这个方法,将SpringBoot的主程序类传入了进来
       builder = configure(builder);
        
        //使用builder创建一个Spring应用
       SpringApplication application = builder.build();
       if (application.getSources().isEmpty() && AnnotationUtils
             .findAnnotation(getClass(), Configuration.class) != null) {
          application.getSources().add(getClass());
       }
       Assert.state(!application.getSources().isEmpty(),
             "No SpringApplication sources have been defined. Either override the "
                   + "configure method or add an @Configuration annotation");
       // Ensure error pages are registered
       if (this.registerErrorPageFilter) {
          application.getSources().add(ErrorPageFilterConfiguration.class);
       }
        //启动Spring应用
       return run(application);
    }

7)、Spring的应用就启动并且创建IOC容器

    public ConfigurableApplicationContext run(String... args) {
       StopWatch stopWatch = new StopWatch();
       stopWatch.start();
       ConfigurableApplicationContext context = null;
       FailureAnalyzers analyzers = null;
       configureHeadlessProperty();
       SpringApplicationRunListeners listeners = getRunListeners(args);
       listeners.starting();
       try {
          ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                args);
          ConfigurableEnvironment environment = prepareEnvironment(listeners,
                applicationArguments);
          Banner printedBanner = printBanner(environment);
          context = createApplicationContext();
          analyzers = new FailureAnalyzers(context);
          prepareContext(context, environment, listeners, applicationArguments,
                printedBanner);
           
           //刷新IOC容器
          refreshContext(context);
          afterRefresh(context, applicationArguments);
          listeners.finished(context, null);
          stopWatch.stop();
          if (this.logStartupInfo) {
             new StartupInfoLogger(this.mainApplicationClass)
                   .logStarted(getApplicationLog(), stopWatch);
          }
          return context;
       }
       catch (Throwable ex) {
          handleRunFailure(context, listeners, analyzers, ex);
          throw new IllegalStateException(ex);
       }
    }

猜你喜欢

转载自blog.csdn.net/u014172271/article/details/80462580