在泽西岛动态(取消)部署资源
我需要在 Jersey ServletContainer 中热部署和取消部署资源。
似乎没有办法在 ResourceConfig 上“注销”资源,所以我遵循的路线是用一个新资源集替换所有资源。
尽管文档说 ResourceConfig 上的 registerResources 会替换所有资源,但浏览源代码似乎与此相矛盾。
我发现的解决方案是使用全新的 ResourceConfig 重新加载 ServletContainer。
Set<Class<?>> classes = ...
ResourceConfig config = new ResourceConfig(classes);
container.reload(config);
这工作正常,直到我部署一个导致模型验证异常的资源。在那之后,我无法让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);
}
}
ModelValidationException 是从 WebComponent 构造函数引发的。之后,任何对重新加载的调用都会导致 onShutdown 方法出现异常,这是由 ServiceLocatorImpl 的 preDestroy 方法中的 checkState 引起的。
我可以通过忽略验证错误来避免异常
ResourceConfig config = new ResourceConfig(classes);
config.property(ServerProperties.RESOURCE_VALIDATION_IGNORE_ERRORS,
Boolean.TRUE);
container.reload(config);
然而,现在没有办法找出是否有任何错误,而是探索日志记录,这真的同样糟糕。
根据heenenee的评论,我尝试了对ServletContainer进行子类化,但是像这样的东西会带来问题,因为ResourceConfig不能放在两个WebComponent中。
我尝试在关闭之前创建WebComponent,以获得早期退出,但是如果资源中没有错误,则实际重新加载失败(因为在创建Web组件后无法修改资源配置)
@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);
}
有没有另一种方法可以热取消部署资源?有没有办法在重新加载失败后重置ServletContainer?