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
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 应用。
如对本文有疑问, 点击进行留言回复!!
荐 2020腾讯,阿里,美团,字节跳动面试真题整理,全网首发!面试突击必备!(含答案)
荐 SpringBoot2 整合JTA组件,多数据源事务管理
Netty架构 - EventLoop、EventLoopGroup
网友评论