java – 在Jersey和嵌入式Jetty中忽略了LoggingFilter

前端之家收集整理的这篇文章主要介绍了java – 在Jersey和嵌入式Jetty中忽略了LoggingFilter前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

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

  1. @H_404_6@ServletContainer servletContainer = new ServletContainer(application);
  2. ServletHolder servletHolder = new ServletHolder(servletContainer);
  3. servletHolder.setInitParameter("com.sun.jersey.config.feature.Debug","true");
  4. servletHolder.setInitParameter("com.sun.jersey.config.feature.Trace","true");
  5. servletHolder.setInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters","com.sun.jersey.api.container.filter.LoggingFilter");
  6. 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记录的行为的一个非常细微的细微差别,如果它不是一个彻头彻尾的bug.关于init params主题ServletContainer docs读作:

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

答案隐藏在那里.具体来说,如果ServletContainer没有创建ResourceConfig实例,那么servlet init参数不会作为属性添加,因此不会影响应用程序的配置.当您提供自己的Application实例时,就像使用新的ServletContainer(应用程序)一样,初始化大致遵循以下过程:

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

  1. @H_404_6@public ServletContainer(Application app) {
  2. this.app = app;
  3. }

容器将ServletContainer初始化为典型Servlet生命周期的一部分:

  1. @H_404_6@protected void init(WebConfig webConfig) throws ServletException {
  2. webComponent = (app == null)
  3. ? new InternalWebComponent()
  4. : new InternalWebComponent(app);
  5. webComponent.init(webConfig);
  6. }

将您的Application实例放入InternalWebComponent构造函数中. InternalWebComponent只是对WebComponent的轻微定制,因此:

  1. @H_404_6@InternalWebComponent(Application app) {
  2. super(app);
  3. }

要求:

  1. @H_404_6@public WebComponent(Application app) {
  2. if (app == null)
  3. throw new IllegalArgumentException();
  4.  
  5. if (app instanceof ResourceConfig) {
  6. resourceConfig = (ResourceConfig) app;
  7. } else {
  8. resourceConfig = new ApplicationAdapter(app);
  9. }
  10. }

这是因为您直接提供了一个Application实例,所以在第二个if的一个分支中为您构建了ResourceConfig.构造完成后,立即在新组件上调用WebComponent.init()(请参阅上面的ServletContainer.init()调用,我们来自哪里).在这个init()调用中,将创建由文档引用的“created ResourceConfig”,但在您的情况下,已经存在一个,如我们遵循的跟踪到达此处所示.即,resourceConfig不为null,因此下面的重要行不会执行:

  1. @H_404_6@public void init(WebConfig webConfig) throws ServletException {
  2. ...
  3. if (resourceConfig == null)
  4. resourceConfig = createResourceConfig(config);
  5. ...
  6. }

createResourceConfig()方法(仍在WebComponent中)读作:

  1. @H_404_6@private ResourceConfig createResourceConfig(WebConfig webConfig)
  2. throws ServletException {
  3. final Map

您可以在该调用中看到setPropertiesAndFeatures()用于将servlet的init参数复制到ResourceConfig实例中.不幸的是,这是进行调用的唯一地方,在你的情况下,执行永远不会在这里,主要是因为你使用了一个非默认的ServletContainer构造函数.

我希望原作者只用一个no-arg构造函数编写ServletContainer,并且稍后添加另外两个以便于使用Servlet 3.0容器而不会意识到这种行为正在被引入.否则,我希望在文档中看到一些提及它.

所以,长话短说:要么使用默认的ServletContainer构造函数,要么找到一种方法来自己处理这个部分:

  1. @H_404_6@Map

第一种方式可能是最简单的方法.例如,您可以将Application类指定为init参数,只要没有任何要求您提前实例化它,例如:

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

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

猜你在找的Java相关文章