我需要在Jersey ServletContainer中热部署和-undeploy资源。
似乎无法在ResourceConfig上“取消注册”资源,因此我所遵循的路线是用新集合替换所有资源。
虽然the documentation表示ResourceConfig上的registerResources取代了所有资源,但浏览源代码似乎与此相矛盾。
我找到的解决方案是使用全新的ResourceConfig重新加载ServletContainer。
double
这样可以正常工作,直到我部署导致ModelValidationException的资源。之后,我无法让ServletContainer恢复正常状态。
如果我看一下源代码:
Set<Class<?>> classes = ...
ResourceConfig config = new ResourceConfig(classes);
container.reload(config);
从WebComponent构造函数抛出ModelValidationException。 之后,任何重新加载调用都会导致onShutdown方法发生异常,这是由ServiceLocatorImpl的preDestroy方法中的checkState引起的。
我可以通过忽略验证错误来避免异常
public void reload(final ResourceConfig configuration) {
try {
containerListener.onShutdown(this);
webComponent = new WebComponent(webComponent.webConfig, configuration);
containerListener = webComponent.appHandler;
containerListener.onReload(this);
containerListener.onStartup(this);
} catch (final ServletException ex) {
LOGGER.log(Level.SEVERE, "Reload failed", ex);
}
}
现在没有办法找出是否有任何错误,但要探索记录,这真的很糟糕。
Per heenenee's comment我尝试了对ServletContainer进行子类化,但这样的事情会产生问题,因为ResourceConfig不能放在两个WebComponents中。
我尝试在关闭之前创建WebComponent,以便提前退出,但如果资源中没有错误,则无法实际重新加载(因为在创建web组件后无法修改resourceconfig)
ResourceConfig config = new ResourceConfig(classes);
config.property(ServerProperties.RESOURCE_VALIDATION_IGNORE_ERRORS,
Boolean.TRUE);
container.reload(config);
还有另一种热取消部署资源的方法吗?有没有办法在重新加载失败后重置ServletContainer?
答案 0 :(得分:1)
我不认为这可以在不使用支持热部署的servlet容器的情况下实现。根据我的经验,这样做的一个好方法是使用支持OSGi的容器。您可以查看Eclipse Virgo或Apache Karaf。
例如,在OSGi环境中,您可以创建可以删除到扫描文件夹的模块(称为软件包),以便在运行时启用功能,或从文件夹中删除功能,以禁用某些功能。这与插件在Eclipse IDE中的工作方式类似,其中新的插件安装/卸载并不一定需要重新启动。
答案 1 :(得分:0)
Jersey在技术上不是servlet容器,它是在servlet容器上运行的REST / JaxB框架。
大多数可嵌入的servlet容器,Tomcat,Jetty,Grizzly允许您在运行时重新部署应用程序和servlet。但是,重新部署通常不是您在代码中嵌入容器时使用的功能。
热重新部署在生产中最有用,允许您不断部署新版本。 在Tomcat上,您可以在同一服务器上部署新旧版本的应用程序,tomcat确保在应用程序的最新版本上启动新会话,但旧版本将继续使用它们启动时的应用程序版本。当应用程序没有使用时,它会自动取消部署。