有没有办法使用 Tomcat API 从应用程序内部重新启动 webapp?

Is there a way to restart a webapp from inside the application using the Tomcat API?

基本上,当我的 webapp 启动时,我在 contextInitialized 阶段在启动时创建了一些 servlet。但是我需要能够在 webapp 仍然 运行.

时动态添加 servlet

我开始意识到这可能是不可能的,所以我的下一个解决方案是尝试重新部署 Web 应用程序或重新启动 tomcat。是否可以从应用程序内部重新部署应用程序?或者甚至在上下文已经初始化之后添加一个 servlet?

此时只要能够重新部署 .war 就足够了。

Manager app 将允许您更新应用程序。您也可以使用 JMX MBeans 做一些事情。

Manager 应用程序允许您通过 update=true 参数进行部署和重新部署。您还可以从那里开始、停止、重新启动应用程序。

这不是您想要的,但设置起来非常容易。

正如@JasonArmstrong 所说,您可以 使用 JMX Bean 触发重新加载,这些 Bean 在同一 JVM 中可用于任何应用程序。您可以重新加载自己或其他应用程序。我稍后会 post 编写代码来展示如何做到这一点。

另一方面,如果您只想部署一个额外的 servlet,您可以使用标准 Java Servlet APIs 来实现。

Java Servlet API ServletContext 接口包含一个方法,addServlet,它允许您部署一个新的 servlet。结合该方法的 return 值,您应该可以在应用程序初始化后部署新的 servlet。

例如(在Servlet

Servlet servlet = ...; // Make your servlet, here

ServletContext application = getServletContext();

ServletRegistration.Dynamic reg = application.addServlet("MyNewServlet", servlet);

reg.addMapping("/nyNewServlet");

更新 2018-12-07

对上述文字表示歉意,该文字现已撤回。除了在上下文 初始化 .

之后您不能部署新的 servlet(并且大概还有过滤器和其他类似的东西)之外,它的一切都是真实的

==返回原答案==

或者如果你想重新加载上下文,你仍然可以使用 JMX 来完成。代码看起来像这样:

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;

// Get the JVM's local "server" (there should be only one)
MBeanServer mbs = MBeanServerFactory.findMBeanServer(null).get(0);

// Create an "object name" that points to the application's
// context in Tomcat's MXBean tree. You might want to use
// jvisualvm or a similar MBean explorer to locate your
// application to get the exact right syntax for your context
// in the tree. Tomcat version may affect this value.
ObjectName objectName = new ObjectName("Catalina:j2eeType=WebModule,name=//localhost/contextname,J2EEApplication=none,J2EEServer=none");

// Invoke the "reload" method, which will 
mbs.invoke(objectName, "reload", null, null);