当前位置: 首页 > 科技观察

SpringBoot内嵌Tomcat如何部署多个应用?

时间:2023-03-11 21:30:50 科技观察

SpringBoot的应用大多比较特殊。添加依赖后,即使是Web应用程序最终也可以以JAR的形式运行。具体依赖容器环境通过嵌入形式隐式使用。而像这些环境、Spring配置等,更多的是隐藏在SpringBoot内部,开发者可以更专注于“业务逻辑”的开发。当“解放双手”时,话虽如此,但有时候,也有一些弊端。例如,以WAR文件的形式独立部署时,可以在容器中部署一些额外的“监控”应用,观察容器的情况,应用的请求等。嵌入这些内容时,有一些困难。沮丧的。对于习惯了SpringBoot的JAR文件便捷操作的用户,有没有什么方法可以在部署其他应用的同时,保留JAR的使用习惯,满足独立容器部署的形式和使用习惯呢?答案是肯定的。鱼和熊掌也可以兼得。后面我们将以嵌入式Tomcat为例来说明具体实现。首先,我们需要认识到这一点。对于嵌入式容器来说,本质上还是一个容器,保留了容器的大部分内容。所以独立部署的一些样式和接口还是可以使用的。不熟悉Tomcat在SpringBoot中工作原理的读者可以参考这些老文章:Tomcat是如何处理SpringBoot应用的?容器终归是容器,所以我们只要“拿到”这个容器,就可以对其进行操作了。我们在老文中提到过,SpringBoot中嵌入的Tomcat是自己创建一个新的Tomcat实例,然后将应用部署为一个Context。如果我们要部署其他应用,我们也跟着“葫芦”获取这个实例,部署应用。在SpringBoot中,由于需要支持各种Servlet容器,所以创建容器的Factory是统一抽象的。在SpringBoot1.x和2.x中,分别用EmbeddedServletContainerFactory和ServletWebServerFactory这两个接口来表示。对应工厂中创建的容器对象在1.x和2.x中分别用TomcatEmbeddedServletContainer和TomcatWebServer这两个类来表示。这个Factory也作为一个bean参与到SpringBoot的启动过程中。我们要做的就是在启动时定义这样一个Bean,并“重写”Factory中获取Tomcat实例的方法,获取之前创建的Tomcat实例,完成应用的部署。1.x的方式如下:@BeanpublicEmbeddedServletContainerFactoryservletContainerFactory(){returnnewTomcatEmbeddedServletContainerFactory(){protectedTomcatEmbeddedServletContainergetTomcatEmbeddedServletContainer(Tomcattomcat){newFile(tomcat.getServer().getCatalinaBase(),"webapptext()").{newFile(tomcat.getServer().getCatalinaBase(),"webapptext()").{mkDirs()."/test","/home/test/sample.war");//这里是要部分的应用名称和路径context.setParentClassLoader(getClass().getClassLoader());}catch(Exceptionex){thrownewIllegalStateException("Failedtoaddwebapp",ex);}returnsuper.getTomcatEmbeddedServletContainer(tomcat);}};}2.x@BeanpublicServletWebServerFactoryservletContainerFactory(){returnnewTomcatServletWebServerFactory(){protectedTomcatWebServergetTomcatWebServer(Tomcattomcat){newFile(tomcat.getServer().getCatalinaBase(),"你好").mkdirs();try{Contextcontext=tomcat.addWebapp("/foo","/home/test/sample.war");context.setParentClassLoader(getClass().getClassLoader());}catch(Exceptionex){thrownewIllegalStateException("Failedtoaddwebapp",ex);}returnsuper.getTomcatWebServer(tomcat);};};}当然,还有其他方法可以达到类似的目的。比如几年前的一篇老文章,在分析IDE中Tomcat的工作原理时,分析了Tomcat是如何在IDEA中部署应用的。实现思路是通过Tomcat注册MBean,包括应用管理的MBean。对于嵌入式Tomcat,仍然发布MBeanServer,连接上即可部署应用。需要注意的一点是,内嵌的Tomcat和Host的ObjectName与独立运行的是不一样的。否则,部署将失败。综上所述,嵌入式容器也保留了独立部署容器的管理和使用习惯。在启动和创建过程中,可以获取其容器实例进行操作。也可以通过对外暴露的MBeanServer来操作。【本文为专栏作家“侯书城”原创稿件,转载请通过作者微信公众号“Tomcat物语”获得授权】点此查看本作者更多好文