Springboot 2使用外部Tomcat源码分析
springboot 使用外部 tomcat
1.修改 pom.xml,改为打 war 包<packaging>war</packaging>
2.将 springboot 内置 tomcat 作用域改为provided
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-tomcat</artifactid> <scope>provided</scope> </dependency>
3.重写 springbootservletinitializer
@springbootapplication public class bootstrap extends springbootservletinitializer { public static void main(string[] args) { springapplication.run(bootstrap.class, args); } @override protected springapplicationbuilder configure(springapplicationbuilder builder) { return builder.sources(bootstrap.class); } }
4.maven 打包出 war 包后,放到 tomcat 的 webapps 目录下即可。
如果要访问该 war 包的接口,默认需要在 url 加项目名作为前缀,例如:http://localhost:8080/{项目名}/users/123456
原理分析
servletcontainerinitializer
servlet 容器启动时,会扫描当前应用每个 jar 包路径meta-inf\services
下的文件javax.servlet.servletcontainerinitializer
,其文件内容就是 servletcontainerinitializer 的实现类全类名,并调用其 onstartup() 方法。比如,在 spring-web 包下,该文件内容就是org.springframework.web.springservletcontainerinitializer
,其源码如下:
// 容器启动时,将 webapplicationinitializer 的所有子类传递至 webappinitializerclasses @handlestypes(webapplicationinitializer.class) public class springservletcontainerinitializer implements servletcontainerinitializer { /** * @param webappinitializerclasses @handlestypes 导入的类 * @param servletcontext 当前 web 应用 servlet 上下文 */ @override public void onstartup(@nullable set<class<?>> webappinitializerclasses, servletcontext servletcontext) throws servletexception { list<webapplicationinitializer> initializers = new linkedlist<>(); for (class<?> waiclass : webappinitializerclasses) { // 过滤出可用的 webapplicationinitializer if (!waiclass.isinterface() && !modifier.isabstract(waiclass.getmodifiers()) && webapplicationinitializer.class.isassignablefrom(waiclass)) { initializers.add((webapplicationinitializer)reflectionutils.accessibleconstructor(waiclass).newinstance()); } } for (webapplicationinitializer initializer : initializers) { initializer.onstartup(servletcontext); } } }
容器启动时,执行 springservletcontainerinitializer.onstartup() 方法,@handlestypes 注解声明了 webapplicationinitializer 的所有子类(在前面的示例中,启动类 bootstrap 实现的 springbootservletinitializer 就是它的一个实现)会被传递给方法的参数 webappinitializerclasses。
onstartup() 方法会过滤出 webappinitializerclasses 中可用的 webapplicationinitializer 子类 bootstrap,然后回调 springbootservletinitializer 的 onstartup() 方法,其源码如下:
public void onstartup(servletcontext servletcontext) throws servletexception { webapplicationcontext rootappcontext = createrootapplicationcontext(servletcontext); } protected webapplicationcontext createrootapplicationcontext(servletcontext servletcontext) { springapplicationbuilder builder = createspringapplicationbuilder(); // 指定主类 bootstrap builder.main(getclass()); // 回调 bootstrap 重写的方法 builder = configure(builder); return run(builder.build()); }
这个方法会配置当前 web 应用程序上下文环境:指定主类、注册 servletcontext、调用 configure()、run 运行。
由于 bootstrap 重写了 configure(),所以会执行重写的方法来指定主类,最后通过 run 来完成启动 springboot 应用。
上一篇: 整合 User-Agent 大全汇总
下一篇: spring基础学习01
推荐阅读
-
Springboot 2使用外部Tomcat源码分析
-
SpringBoot 源码解析 (六)----- Spring Boot的核心能力 - 内置Servlet容器源码分析(Tomcat)
-
springboot内嵌tomcat源码分析DispatchServlet装载过程
-
springboot使用war包部署到外部tomcat过程解析
-
SpringBoot内置tomcat启动原理、以及SpringBoot初始化Servlet的源码分析
-
IDEA配置SpringBoot使用外部Servlet容器(Tomcat)
-
精尽Spring Boot源码分析 - 支持外部 Tomcat 容器的实现
-
SpringBoot 源码解析 (六)----- Spring Boot的核心能力 - 内置Servlet容器源码分析(Tomcat)
-
使用dynamic datasource springboot starter实现多数据源及源码分析
-
依赖注入框架 ----Dagger2 使用详解及源码分析