3

我在Client使用ApacheConnector. 它似乎忽略了我在WriterInterceptor. 我可以说WriterInterceptor当我在WriterInterceptor#aroundWriteTo(WriterInterceptorContext). 与此相反,我可以观察到 an 的修改InputStream被保留了。

这是一个演示我的问题的可运行示例:

public class ApacheConnectorProblemDemonstration extends JerseyTest {

  private static final Logger LOGGER = Logger.getLogger(JerseyTest.class.getName());
  private static final String QUESTION = "baz", ANSWER = "qux";
  private static final String REQUEST_HEADER_NAME_CLIENT = "foo-cl", REQUEST_HEADER_VALUE_CLIENT = "bar-cl";
  private static final String REQUEST_HEADER_NAME_INTERCEPTOR = "foo-ic", REQUEST_HEADER_VALUE_INTERCEPTOR = "bar-ic";
  private static final int MAX_CONNECTIONS = 100;
  private static final String PATH = "/";

  @Path(PATH)
  public static class TestResource {
    @POST
    public String handle(InputStream questionStream,
                         @HeaderParam(REQUEST_HEADER_NAME_CLIENT) String client,
                         @HeaderParam(REQUEST_HEADER_NAME_INTERCEPTOR) String interceptor) 
        throws IOException {
      assertEquals(REQUEST_HEADER_VALUE_CLIENT, client);
      // Here, the header that was set in the client's writer interceptor is lost.
      assertEquals(REQUEST_HEADER_VALUE_INTERCEPTOR, interceptor);
      // However, the input stream got gzipped so the WriterInterceptor has been partly applied.
      assertEquals(QUESTION, new Scanner(new GZIPInputStream(questionStream)).nextLine());
      return ANSWER;
    }
  }

  @Provider
  @Priority(Priorities.ENTITY_CODER)
  public static class ClientInterceptor implements WriterInterceptor {
    @Override
    public void aroundWriteTo(WriterInterceptorContext context) 
        throws IOException, WebApplicationException {
      context.getHeaders().add(REQUEST_HEADER_NAME_INTERCEPTOR, REQUEST_HEADER_VALUE_INTERCEPTOR);
      context.setOutputStream(new GZIPOutputStream(context.getOutputStream()));
      context.proceed();
    }
  }

  @Override
  protected Application configure() {
    enable(TestProperties.LOG_TRAFFIC);
    enable(TestProperties.DUMP_ENTITY);
    return new ResourceConfig(TestResource.class);
  }

  @Override
  protected Client getClient(TestContainer tc, ApplicationHandler applicationHandler) {
    ClientConfig clientConfig = tc.getClientConfig() == null ? new ClientConfig() : tc.getClientConfig();
    clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, makeConnectionManager(MAX_CONNECTIONS));
    clientConfig.register(ClientInterceptor.class);
    // If I do not use the Apache connector, I avoid this problem.
    clientConfig.connector(new ApacheConnector(clientConfig));
    if (isEnabled(TestProperties.LOG_TRAFFIC)) {
      clientConfig.register(new LoggingFilter(LOGGER, isEnabled(TestProperties.DUMP_ENTITY)));
    }
    configureClient(clientConfig);
    return ClientBuilder.newClient(clientConfig);
  }

  private static ClientConnectionManager makeConnectionManager(int maxConnections) {
    PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();
    connectionManager.setMaxTotal(maxConnections);
    connectionManager.setDefaultMaxPerRoute(maxConnections);
    return connectionManager;
  }

  @Test
  public void testInterceptors() throws Exception {
    Response response = target(PATH)
        .request()
        .header(REQUEST_HEADER_NAME_CLIENT, REQUEST_HEADER_VALUE_CLIENT)
        .post(Entity.text(QUESTION));
    assertEquals(200, response.getStatus());
    assertEquals(ANSWER, response.readEntity(String.class));
  }
}

我想使用ApacheConnector来优化通过PoolingClientConnectionManager. 我搞砸了配置吗?

PS:使用GrizzlyConnector.

4

1 回答 1

3

经过进一步研究,我认为这是默认Connector使用HttpURLConnection. 正如我在我的另一个自我回答的问题中解释的那样,文档指出

过滤器主要用于操纵请求和响应参数,如 HTTP 标头、URI 和/或 HTTP 方法,而拦截器旨在通过操纵实体输入/输出流来操纵实体

AWriterInterceptor不应该操纵标头值,而 a{Client,Server}RequestFilter不应该操纵实体流。如果您需要同时使用这两个组件,则应将两个组件捆绑在一个javax.ws.rs.core.Feature实现两个接口的类中或同一个类中。(如果您需要设置两个不同Priority的 s,这可能会出现问题。)

尽管如此,所有这一切都是非常不幸的,因为JerseyTest使用了Connector使用. 另外,我希望泽西岛不会抑制变化,而是会给我一些例外。(这是我在泽西岛遇到的一个普遍问题。例如,当我使用太新版本的接口重命名为时,我只是在一行日志语句中被告知我所有的配置工作都被忽略了。我没有发现这个日志声明直到开发的很晚。)HttpURLConnectionApacheConnectorClientConnectionManagerHttpClientConnectionManager

于 2013-11-07T09:24:51.517 回答