java - 在 Jersey 动态(取消)部署资源

标签 java jersey jersey-2.0

我需要在 Jersey ServletContainer 中热部署和取消部署资源。

似乎没有办法在 ResourceConfig 上“取消注册”资源,所以我遵循的路线是用新集合替换所有资源。

虽然the documentation说 ResourceConfig 上的 registerResources 替换了所有资源,浏览源代码似乎与此相矛盾。

我找到的解决方案是使用全新的 ResourceConfig 重新加载 ServletContainer。

Set<Class<?>> classes = ...
ResourceConfig config = new ResourceConfig(classes);
container.reload(config);

在我部署导致 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);
    }
}

ModelValidationException 是从 WebComponent 构造函数中抛出的。 之后,任何对 reload 的调用都会导致 onShutdown 方法出现异常,这是由 ServiceLocatorImpl 的 preDestroy 方法中的 checkState 引起的。

我可以通过忽略验证错误来避免异常

ResourceConfig config = new ResourceConfig(classes);
config.property(ServerProperties.RESOURCE_VALIDATION_IGNORE_ERRORS,
    Boolean.TRUE);
container.reload(config);

但是,现在除了探索日志记录之外,没有办法查明是否有任何错误,这同样糟糕,真的。

根据 heenenee's comment我尝试将 ServletContainer 子类化,但这样的事情会产生问题,因为 ResourceConfig 不能放在两个 WebComponents 中。

我尝试在关闭之前创建 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?

最佳答案

我认为如果不使用支持热部署的 servlet 容器,这是无法实现的。以我的经验,这样做的一个好方法是使用支持 OSGi 的容器。你可以看看Eclipse VirgoApache Karaf .

例如,在 OSGi 环境中,您可以创建模块(称为 bundle ),这些模块可以拖放到扫描的文件夹中以在运行时启用功能,或从文件夹中删除以禁用某些功能。这类似于插件在 Eclipse IDE 中的工作方式,其中新插件安装/卸载不一定需要重新启动。

关于java - 在 Jersey 动态(取消)部署资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33940935/

相关文章:

java - 使用 JAXB 读取我的 XML

java - Spring 3.2 和 Jersey 2.4 的 Autowiring 问题

javascript - JAX RS - Jersey 文件传输,响应不应重定向

jersey-2.0 - Jersey(2.10.4) 实体提供者选择算法对自定义提供者(MessageBodyWriter)的优先级较低,使其不被调用

java - 替换字符串中包含数字或特殊符号的单词

java - Tableview javaFX - getColumns() 的类型是错误的

java - docx4j java API 中的删除线选项

java - Java RESTful 服务中的 httpcontext

java - tomcat 为我的 webapp 返回 404

java - 获取 HTTP 状态 415 - Jersey 不支持的媒体类型