【问题标题】:response.setContentType() getting reset in Java Filter [duplicate]response.setContentType() 在 Java 过滤器中被重置 [重复]
【发布时间】:2014-09-10 20:11:56
【问题描述】:

我正在尝试在过滤器中将我的 gzip 压缩文件的内容类型设置为正确的 mime 类型,而不是 application/gzip。这是我的一些代码:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,  FilterChain filterChain) throws IOException, ServletException
{
    final HttpServletRequest request = (HttpServletRequest) servletRequest;
    final HttpServletResponse response = (HttpServletResponse) servletResponse;

    String reqUrl = request.getRequestURI();
    if (reqUrl.endsWith(gzExt))
    {
        response.setHeader("Content-Encoding", "gzip");
        response.setContentType("text/javascript");

        System.out.println("Set header " +reqUrl +", " + response.getContentType() );

        filterChain.doFilter(request, response);

        System.out.println("Header now: " + reqUrl + ", " + response.getContentType() );
        return;
    }
}

输出:

Set header /test.js.gz, text/javascript
Header now: /test.js.gz, application/x-gzip

在浏览器中,我看到content-encoding 正确设置为gzip,但content-type 仍为application/x-gzipfilterChain.doFilter() 似乎正在重置内容类型。

知道如何永久重置内容类型吗?

我没有任何其他过滤器。

【问题讨论】:

    标签: java servlets tomcat7


    【解决方案1】:

    我在this answer的帮助下解决了这个问题:

    private class ForcableContentTypeWrapper extends HttpServletResponseWrapper
    {
        public ForcableContentTypeWrapper(HttpServletResponse response)
        {
            super(response);
        }
    
        @Override
        public void setContentType(String type)
        {
        }
        public void forceContentType(String type)
        {
            super.setContentType(type);
        }
    }
    

    然后把我上面的代码改成:

        if (reqUrl.endsWith(gzExt))
        {
            ForcableContentTypeWrapper newResponse = new ForcableContentTypeWrapper(response);
            newResponse.setHeader("Content-Encoding", "gzip");
            newResponse.forceContentType("text/javascript");
            filterChain.doFilter(request, newResponse);
            return;
        }
    

    这不是一个很好的解决方法,但它确实有效。

    【讨论】:

    • 让我知道哪个答案值得赏金;)
    • @Omar 这取决于你,在我的具体情况下,我需要在运行时指定 mime 类型,我不想最后运行这个过滤器。所以我的解决方案对我有用,但对其他人来说,另一种解决方案可能会更好。
    • @Omar 但是,Alex 的回答不起作用,因为即使您将其移至最后一个过滤器,容器的默认 servlet 也会在过滤器之后运行并重置内容类型(至少在 Tomcat 的情况下) )
    • BalusC 的回答没有解决你的问题?
    • @Omar 在我的具体情况下,不,因为我提供不同类型的文件,例如 css、javascript、图像。所以必须在运行时指定 MIME 类型。
    【解决方案2】:

    首先,你应该总是打电话(或者有很好的理由不这样做)

     filterChain.doFilter(request, response);
    

    或在此之后声明的过滤器将不会被调用。

    接下来,将调用 filterChain.doFilter() 移动到方法的顶部,在 web.xml 中设置您的标题并将您的过滤器映射声明为最后一个。 这将按预期工作。

    【讨论】:

      猜你喜欢
      • 2015-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-18
      • 1970-01-01
      • 2017-08-12
      • 1970-01-01
      • 2012-02-27
      相关资源
      最近更新 更多