Raf*_*ter 14 glassfish jax-rs jersey
我正在尝试编写一个简单的Jersey应用程序,它将文件从Jersey客户端发送到Jersey服务器并返回.但是,文件似乎只是在从客户端到服务器的路上编码而不是其他方式.我想知道如何改变这种行为.
我在一个简单的例子中测试它:
public class GZipEncodingTest extends JerseyTest {
private static final String PATH = "/";
private static final String QUESTION = "foo", ANSWER = "bar";
private static final String ENCODING_GZIP = "gzip";
@Path(PATH)
public static class MyResource {
@POST
public Response handle(String question) throws IOException {
assertEquals(QUESTION, question);
return Response.ok(ANSWER).build(); // (1)
}
}
@Override
protected Application configure() {
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
return new ResourceConfig(MyResource.class, GZipEncoder.class);
}
@Override
@SuppressWarnings("unchecked")
protected void configureClient(ClientConfig config) {
config.register(new EncodingFeature(ENCODING_GZIP, GZipEncoder.class));
}
@Test
public void testHeaders() throws Exception {
Response response = target().path(PATH).request().post(Entity.text(QUESTION));
assertEquals(ANSWER, response.readEntity(String.class));
}
}
Run Code Online (Sandbox Code Playgroud)
从记录的转储中,我可以看出请求是按预期的:内容编码在标头中发出信号并应用在请求消息正文中.在接受编码也被设置.服务器了解应用的gzip压缩并解压缩请求消息正文.但是,它忽略了客户端接受gzip压缩响应并发送未压缩响应消息体的事实.
当我追加encoding(ENCODING_GZIP)
的线(1)在Response
-builder链,我得到我期待的结果.但是,我想仅在请求中将其标记为可接受时才应用编码.此外,我希望将此功能应用于整个范围,而不仅仅是针对特定的响应.
我当然可以手动添加这样一个功能WriterInterceptor
:
public class GZipWriterInterceptor implements WriterInterceptor {
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {
context.getHeaders().add(HttpHeaders.CONTENT_ENCODING, ENCODING_GZIP);
context.proceed();
}
}
Run Code Online (Sandbox Code Playgroud)
但我确信这是不必要的锅炉板.
的EncodingFeature
似乎只能是客户端库的一部分.我基本上正在寻找一种可能性,当请求通过accept-encoding建议编码时,Jersey服务器将数据编码为gzip.
当我尝试在网上搜索解决方案时,我发现了很多.他们中的大多数都关注Jersey 1.他们中的一些人建议为GrizzlyServer添加一个监听器(这将是Jersey特定而不是JAX-RS?).然后在Jersey 2依赖树中有很多类建议GZip编码:
org.glassfish.grizzly.http.GZipContentEncoding
org.glassfish.jersey.message.GZipEncoder
org.glassfish.grizzly.compression.zip.GZipEncoder
org.glassfish.grizzly.compression.zip.GZipDecoder
org.glassfish.grizzly.compression.zip.GZipFilter
我发现网络上的人建议使用它们中的任何一个,即使我认为这org.glassfish.jersey
似乎是正确的选择,因为它是一个真正的泽西岛依赖.不要说ApacheConnector
相关图书馆中的那些.我不知道我应该使用哪一个.
Raf*_*ter 20
我通过浏览泽西岛图书馆找到了它.对于服务器端,需要以下配置:
@Override
@SuppressWarnings("unchecked")
protected Application configure() {
ResourceConfig resourceConfig = new ResourceConfig(MyResource.class);
EncodingFilter.enableFor(resourceConfig, GZipEncoder.class);
return resourceConfig;
}
Run Code Online (Sandbox Code Playgroud)
在转换下,EncodingFilter#enableFor(ResourceConfig.Class<? extends ContentEncoder>[])
注册一个EncodingFilter
和指定GZipEncoder
的给定ResourceConfig
.
我想在注册中绕道而行的原因在于任何编码都需要分两个阶段进行.首先,EncodingFilter
(这是一个实际的ContainerResponseFilter
通过设置修改响应的头Content-Encoding
到gzip
.同时,过滤器不能由于过滤器被调用之前甚至创建此流.因此,流修改消息主体的实体流修改必须由WriterInterceptor
处理过滤器之后以及创建实体流之后触发的处理.
出于这个原因,只有在客户端设置标头时才注册该GZipEncoder
标志将用于请求解码,这与服务器的创建无关.Content-Encoding
gzip
我用'GZipWriterInterceptor'给出的例子基本上是一个执行不佳的版本EncodingFilter
.当然,标题应该设置在过滤器中,而不是设置在拦截器中.它在文档中说:
过滤器主要用于处理请求和响应参数,如HTTP头,URI和/或HTTP方法,而拦截器旨在通过操纵实体输入/输出流来操纵实体
因此,gzip编码不能简单地通过注册a激活GZipEncoder
,它也需要注册过滤器.这就是为什么我希望两者都捆绑在一起Feature
.
重要提示:EncodingFilter
泽西岛内有两个班级.一个属于客户端,另一个属于服务器实现.不要使用错误的,因为他们做了根本不同的事情.不幸的是,在运行单元测试时,您将在类路径上拥有它们,因为它们依赖于客户端接口.
归档时间: |
|
查看次数: |
12095 次 |
最近记录: |