我认为这是记录行为的一个非常微妙的细微差别,ServletContainer
如果它不是一个彻底的错误。关于 init params 主题的ServletContainer
文档如下:
所有初始化参数都作为创建的 ResourceConfig 的属性添加。
答案就藏在那里。具体来说,如果 ResourceConfig 实例不是由 ServletContainer 创建的,则 servlet 初始化参数不会作为属性添加,因此不会影响应用程序的配置。当您提供自己的Application
实例时,就像您对 . 所做的那样new ServletContainer(application)
,初始化大致遵循以下过程:
您的代码使用您的实例调用以下ServletContainer
构造函数:Application
public ServletContainer(Application app) {
this.app = app;
}
容器将您初始化ServletContainer
为典型Servlet
生命周期的一部分:
protected void init(WebConfig webConfig) throws ServletException {
webComponent = (app == null)
? new InternalWebComponent()
: new InternalWebComponent(app);
webComponent.init(webConfig);
}
您的Application
实例进入InternalWebComponent
构造函数。AnInternalWebComponent
只是对 的轻微定制WebComponent
,因此:
InternalWebComponent(Application app) {
super(app);
}
调用:
public WebComponent(Application app) {
if (app == null)
throw new IllegalArgumentException();
if (app instanceof ResourceConfig) {
resourceConfig = (ResourceConfig) app;
} else {
resourceConfig = new ApplicationAdapter(app);
}
}
在这里,由于您Application
直接提供了一个实例,因此 aResourceConfig
在该 second 的一个分支中为您构建if
。构建后立即在WebComponent.init()
新组件上调用(请参阅ServletContainer.init()
上面的调用,我们来自哪里)。在此调用中,将init()
创建文档引用的“创建的 ResourceConfig” ,但在您的情况下,已经存在一个,如我们遵循的路径所示。即,不为空,因此下面的重要行不执行:resourceConfig
public void init(WebConfig webConfig) throws ServletException {
...
if (resourceConfig == null)
resourceConfig = createResourceConfig(config);
...
}
该createResourceConfig()
方法(仍在WebComponent
)显示为:
private ResourceConfig createResourceConfig(WebConfig webConfig)
throws ServletException {
final Map<String, Object> props = getInitParams(webConfig);
final ResourceConfig rc = createResourceConfig(webConfig, props);
rc.setPropertiesAndFeatures(props);
return rc;
}
您可以在该调用中看到setPropertiesAndFeatures()
用于将 servlet 的 init 参数复制到ResourceConfig
实例中。不幸的是,这是进行该调用的唯一地方,在您的情况下,执行永远不会在这里进行,主要是因为您使用了非默认ServletContainer
构造函数之一。
我希望原始作者ServletContainer
只使用一个无参数构造函数编写,而其他两个是后来添加的,以便在 Servlet 3.0 容器中使用,而没有意识到引入了这种行为。否则,我希望在文档中看到一些提及它。
所以,长话短说:要么使用默认ServletContainer
构造函数,要么自己找到一种方法来处理这部分:
Map<String, Object> props = getInitParams(webConfig);
rc.setPropertiesAndFeatures(props);
第一种方法可能是最简单的。例如,您也可以将您的Application
类指定为 init 参数,只要没有什么需要您提前实例化它,例如:
servletHolder.setInitParameter("javax.ws.rs.Application", "org.foo.MyApplication");
这样,将采用“正常”初始化路径,这意味着WebComponent
将为您创建ResourceConfig
并正确应用 init 参数。