2

我正在使用 Resteasy 开发一个小型 JAX-RS 应用程序。我希望应用程序为 Javascript 和 CSS 文件等提供一些静态内容,并且我想利用打包在webjars.org的 jar 中的资源的 gzip 压缩版本。因此,我需要处理Accept-Encoding标题并检查是否.gz存在(或不存在)。

到目前为止,我所拥有的是:

@Path("res/{path:.*}")
@GET
public Response webjars(@PathParam("path") String path, @HeaderParam("Accept-Encoding") String acceptEncoding) {

    // Guesses MIME type from the path extension elsewhere.
    String mime = mimes.getContentType(path);

    if (acceptEncoding.contains("gzip")) {
        InputStream is = getClass().getResourceAsStream("/META-INF/resources/webjars/" + path + ".gz");
        if (is != null)
            return Response.ok().type(mime).encoding("gzip").entity(is).build();
    }

    InputStream is = getClass().getResourceAsStream("/META-INF/resources/webjars/" + path);
    if (is != null)
        return Response.ok().type(mime).entity(is).build();

    return Response.status(Status.NOT_FOUND).build();
}

但它不起作用。提供的内容完全被破坏了。到目前为止,我发现了一个再次压缩流的组件:org.jboss.resteasy.plugins.interceptors.encoding.GZIPEncodingInterceptor,因为我手动填充了Content-Encoding标题(使用ResponseBuilder.encoding方法)。

这对我来说似乎是一个错误,因为显然没有办法共享已经压缩过的流。但是,这可以使用 JAX-RS 实现吗?这是一个 Resteasy 错误吗?

我可以想出多种方法在 Resteasy 外部实现同样的事情,比如映射 webjars.org servlet(我不在 Servlet API 3.0 环境中,所以我没有META-INF/resources/自动类路径映射)。尽管如此,我的问题仍然占上风。它适用于其他几个场景。

更新:

作为记录,我已经填写了问题RESTEASY-1170

4

1 回答 1

4

这是我上述评论的示例实现。

我要说的是,如果您不希望它由当前拦截器处理,请不要设置标头,创建一个将名称绑定的拦截器,使用您自己的注释,并将优先级设置为比你想避免的低一个,然后在你的拦截器中设置标题......

@AlreadyGzipped

@NameBinding
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AlreadyGzipped {}

WriterInterceptor. 注意@Priority. GZIPEncodingInterceptor用途_Priorities.ENTITY_CODER

@Provider
@AlreadyGzipped
@Priority(Priorities.ENTITY_CODER + 1000)
public class AlreadyGzippedWriterInterceptor implements WriterInterceptor {
    @Context HttpHeaders headers;

    @Override
    public void aroundWriteTo(WriterInterceptorContext wic) throws IOException, 
                                                      WebApplicationException {
        String header = headers.getHeaderString("Accept-Encoding");
        if (null != header && header.equalsIgnoreCase("gzip")) {
            wic.getHeaders().putSingle("Content-Encoding", "gzip");
        }
        wic.proceed();
    }  
}

测试资源

@Path("resource")
public class AlreadyGzippedResoure {

    @GET
    @AlreadyGzipped
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response getAlreadGzipped() throws Exception {
        InputStream is = getClass().getResourceAsStream("/stackoverflow.png.gz");
        return Response.ok(is).build();
    }
}

测试

public class Main {
    public static void main(String[] args) throws Exception {
        Client client = ClientBuilder.newClient();
        String url = "http://localhost:8080/api/resource";

        Response response = client.target(url).request().acceptEncoding("gzip").get();
        Image image = ImageIO.read(response.readEntity(InputStream.class));
        JOptionPane.showMessageDialog(null,new JLabel(new ImageIcon(image)));
    }
}

结果

在此处输入图像描述

于 2015-04-17T14:26:19.663 回答