使用Java Servlets提供Gzip压缩内容

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

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

response.setGzip(true); 

它不一定非常容易,但它会是理想的。

非常感谢

本文提供了ServletFilter的完整(和简要)源代码,可以动态自动压缩。

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

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

基本上有两种方式:

  • 在appserver中配置它。 在例如Tomcat中,您只需要将conf/server.xml Connectorcompression属性设置为on
  • response.getOutputStream()包装在new GzipOutputStream()并改为写入。

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

您可以在这里找到一个FileServlet的高级示例,它支持每个Gzip,并根据请求标头进行检查。 您可能会从中获得新的见解。

看看GzipOutputStream类。 像这样的东西:

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

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

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

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

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

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

  

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

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

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

 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); 

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