Bre*_*man 22 java jersey jersey-2.0
我需要在Jersey ServletContainer中热部署和-undeploy资源.
似乎无法在ResourceConfig上"取消注册"资源,因此我遵循的路线是用新集合替换所有资源.
虽然文档说ResourceConfig上的registerResources取代了所有资源,但浏览源代码似乎与此相矛盾.
我找到的解决方案是使用全新的ResourceConfig重新加载ServletContainer.
Set<Class<?>> classes = ...
ResourceConfig config = new ResourceConfig(classes);
container.reload(config);
Run Code Online (Sandbox Code Playgroud)
这可以正常工作,直到我部署导致ModelValidationException的资源.之后,我无法让ServletContainer恢复正常状态.
如果我看一下源代码:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
从WebComponent构造函数抛出ModelValidationException.之后,任何对重新加载的调用都会导致onShutdown方法的异常,这是由ServiceLocatorImpl的preDestroy方法中的checkState引起的.
我可以通过忽略验证错误来避免异常
ResourceConfig config = new ResourceConfig(classes);
config.property(ServerProperties.RESOURCE_VALIDATION_IGNORE_ERRORS,
Boolean.TRUE);
container.reload(config);
Run Code Online (Sandbox Code Playgroud)
然而,现在没有办法找出是否有任何错误,但要探索日志记录,这真的很糟糕.
根据heenenee的评论,我尝试了子类化ServletContainer,但是这样的事情会产生问题,因为ResourceConfig不能放在两个WebComponents中.
我尝试在关闭之前创建WebComponent以获得提前退出,但如果资源中没有错误,则无法实际重新加载(因为在创建web组件后无法修改resourceconfig)
@Override
public void reload(ResourceConfig configuration) {
try {
new WebComponent(new WebServletConfig(this), configuration);
} catch (ServletException e) {
LOGGER.log(Level.SEVERE, "Reload failed", e);
List<ResourceModelIssue> resources = Collections.emptyList();
throw new ModelValidationException(e.getMessage(), resources);
}
super.reload(configuration);
}
Run Code Online (Sandbox Code Playgroud)
还有另一种热取消部署资源的方法吗?有没有办法在重新加载失败后重置ServletContainer?
我认为如果不使用支持热部署的servlet容器就无法实现这一点。根据我的经验,做到这一点的一个好方法是使用支持 OSGi 的容器。您可以查看Eclipse Virgo或Apache Karaf。
例如,在 OSGi 环境中,您可以创建模块(称为捆绑包),将其拖放到扫描的文件夹中以在运行时启用功能,或从文件夹中删除以禁用某些功能。这类似于插件在 Eclipse IDE 中的工作方式,其中新插件的安装/卸载不一定需要重新启动。