使用Java Servlets提供Gzipped内容

时间:2009-12-07 21:10:59

标签: java servlets gzip

我想知道是否有一种 easy 方式来使用Java Servlets提供GZipped内容。我已经启动并运行了应用程序,因此所需的修改应该太重了。

我可以在doPost / doGet方法的末尾访问响应对象,所以我正在寻找像

这样的东西
response.setGzip(true);

它不一定是那么简单但它是理想的。

非常感谢

8 个答案:

答案 0 :(得分:10)

This article拥有ServletFilter的完整(简短)源代码,可以动态自动压缩。

答案 1 :(得分:4)

根据您的容器,容器很可能会为您执行此操作。它可以自动执行,或者您可能需要手动配置它来为您执行此操作。此方法的优点是零代码更改。而且,根据容器,您可以根据请求来源或源浏览器有条件地启用/禁用压缩。

对于Tomcat,请查看HTTP配置页面上的compression属性(v5.5v6.0)。

答案 2 :(得分:3)

查看GzipOutputStream类。像这样:

response.setContentType(...)
GzipOutputStream os = new GzipOutputStream(response.getOutputStream);
//write to os
Writer writer = new PrintWriter(os);

然后像往常一样使用作家。

答案 3 :(得分:3)

基本上有两种方式:

  • 在appserver中配置它。例如,在Tomcat中,您只需将compressionConnector的{​​{1}}属性设置为conf/server.xml
  • on换成response.getOutputStream()并改为写入。

第一种方式影响整个网络应用程序,但这确实不应该受到伤害,它几乎是零努力和对性能的大好处。而且,更重要的是,与第二种方式相反,如果客户端在使用之前支持 Gzip,它实际检查请求标头。当你无头地进入第二条路时,大约10%的万维网用户将无法访问你的网络应用程序。这实际上不是一项任务。

您可以找到here在每个Gzip下支持的new GzipOutputStream()的高级示例,并根据请求标头进行检查。你可能会从中获得新的见解。

答案 4 :(得分:1)

如果你真的,真的不想再乱用Java代码了,你也可以考虑在你的servlet容器前挂钩一个Apache服务器。

如果你有很多静态内容,这实际上可以提高你的性能,因为Apache对静态页面的速度比任何servlet容器快一点。因此,您将其配置为仅将servlet请求委托给localhost上的servlet容器。

Apache有一个方便的内置选项来压缩输出。我不记得如何设置它们,但它很简单,功能多样。它与浏览器协商他们可以处理的内容,等等。如果有疑问,Apache通常会比任何Java容器更精明和更新压缩方法。

答案 5 :(得分:1)

如果您使用的是Tomcat,则连接器可以为您进行压缩。这是我的配置,

<Connector port="8000"
 compression="on" 
 compressionMinSize="1024" 
 compressableMimeType="text/html,text/xml" 
 ...
/> 

如果你在Tomcat面前运行Apache httpd,你应该使用mod_gzip,这样可以做得更好。

答案 6 :(得分:1)

只是想让你知道我结束了什么。

我创建了一个请求类的包装器,如下所示:

public class GzippedResponse extends HttpServletResponseWrapper{

  private PrintWriter pw;

  private GzippedResponse(HttpServletResponse response){
    super(response);
    try{
      pw = new PrintWriter(new GZIPOutputStream(response.getOutputStream()));
    }catch(Exception e){
      throw new ApiInternalException("Failed to create a Gzipped Response", e);
    }
  }

  public static GzippedResponse wrap(HttpServletResponse response){
    return new GzippedResponse(response);
  }

  @Override
  public PrintWriter getWriter() throws IOException {
    return pw;
  }  
}

然后在我的BaseAction上,这基本上是其他“动作”的TemplateMethod,我将响应包装成这样:

if(supportsCompression(request)){
  response.setHeader("Content-Encoding", "gzip");
  response = GzippedResponse.wrap(response);
}
action.macroExecute(request,response);

我认为它够干净。如果您发现可以改进的东西,请告诉我。谢谢大家的答案!

答案 7 :(得分:0)

这是我在学习servlet时所使用的。也许没有用,但可以正常工作!!! 将以下代码放置到公共类GZIPEncodingServlet中,该类扩展了HttpServlet {...}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    if (req.getHeader("Accept-Encoding").contains("gzip")) {

        // 'try' block need for closing of stream, of course we can use 'close()' method for our 'PrintWriter' too
        try (PrintWriter printWriter = new PrintWriter(new GZIPOutputStream(resp.getOutputStream()))) {

            resp.setHeader("Content-Encoding", "gzip"); // Client must understood what we're sending him
            printWriter.write("Hello world from gzip encoded html"); // What is sending?
        }

    } else {
        resp.getWriter().write("Can't encode html to gzip :(");
    }

}