gpt4 book ai didi

java - LoggingFilter 在 Jersey 和嵌入式 Jetty 中被忽略

转载 作者:搜寻专家 更新时间:2023-10-31 20:13:03 24 4
gpt4 key购买 nike

我正在尝试在嵌入式 Jetty 设置中为 Jersey 配置 LoggingFilter。使用的胶水代码如下:

ServletContainer servletContainer = new ServletContainer(application);
ServletHolder servletHolder = new ServletHolder(servletContainer);
servletHolder.setInitParameter("com.sun.jersey.config.feature.Debug", "true");
servletHolder.setInitParameter("com.sun.jersey.config.feature.Trace", "true");
servletHolder.setInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters",
"com.sun.jersey.api.container.filter.LoggingFilter");
servletHolder.setInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters",
"com.sun.jersey.api.container.filter.LoggingFilter");

但是日志过滤器实际上被忽略了,我在控制台中看不到相关日志。我怎样才能做到这一点?在 Jersey 1.x 和 2.x 上都进行了测试。

A relevant answer描述了如何使用 web.xml 实现此目的。

最佳答案

如果这不是一个彻头彻尾的错误,我认为这是 ServletContainer 记录行为的一个非常微妙的细微差别。 ServletContainer docs关于 init params 的主题读作:

All initialization parameters are added as properties of the created ResourceConfig.

答案就藏在那里。具体来说,如果 ResourceConfig 实例不是由 ServletContainer 创建的,则 servlet 初始化参数不会作为属性添加,因此不会影响应用程序的配置。当您提供自己的 Application 实例时,就像您对 new ServletContainer(application) 所做的那样,初始化大致遵循以下过程:

您的代码使用您的 Application 实例调用以下 ServletContainer 构造函数:

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 构造函数。 InternalWebComponent 只是对 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 实例,所以在第二个 if 的分支之一中为您构建了一个 ResourceConfig >。构造完成后,立即在新组件上调用 WebComponent.init()(请参阅上面的 ServletContainer.init() 调用,我们来自哪里)。在这个 init() 调用中,将创建文档引用的“created 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 的初始化参数复制到 ResourceConfig 实例中。不幸的是,这是进行该调用的唯一地方,在您的情况下,执行永远不会在这里进行,主要是因为您使用了一个非默认的 ServletContainer 构造函数。

我希望原作者编写 ServletContainer 时只有一个无参数构造函数,另外两个是后来添加的,以便于使用 Servlet 3.0 容器,而没有意识到引入了这种行为.否则,我希望在文档中看到一些提及它。

所以,长话短说:要么使用默认的 ServletContainer 构造函数,要么自己想办法处理这部分:

Map<String, Object> props = getInitParams(webConfig);
rc.setPropertiesAndFeatures(props);

第一种方式可能是最简单的。例如,您也可以将 Application 类指定为初始化参数,只要不需要您提前实例化它即可,例如:

servletHolder.setInitParameter("javax.ws.rs.Application", "org.foo.MyApplication");

这样,将采用“正常”初始化路径,这意味着 WebComponent 将为您创建 ResourceConfig 并正确应用初始化参数。

关于java - LoggingFilter 在 Jersey 和嵌入式 Jetty 中被忽略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15933416/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com