springboot部署到tomcat啟動,以及線上部署,原始碼分析
阿新 • • 發佈:2019-02-17
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); } }