【发布时间】:2010-12-24 04:33:59
【问题描述】:
我想知道是否有一种 简单 的方式来使用 Java Servlet 提供 GZipped 内容。我已经启动并运行了该应用程序,因此所需的修改应该太繁重了。
我可以在 doPost/doGet 方法的末尾访问响应对象,所以我正在寻找类似的东西
response.setGzip(true);
不必那么简单,但它会是理想的。
非常感谢
【问题讨论】:
我想知道是否有一种 简单 的方式来使用 Java Servlet 提供 GZipped 内容。我已经启动并运行了该应用程序,因此所需的修改应该太繁重了。
我可以在 doPost/doGet 方法的末尾访问响应对象,所以我正在寻找类似的东西
response.setGzip(true);
不必那么简单,但它会是理想的。
非常感谢
【问题讨论】:
基本上有两种方式:
conf/server.xml 中的Connector 的compression 属性设置为on。response.getOutputStream() 包装在new GzipOutputStream() 中并改为写入。第一种方式会影响整个 webapp,但这真的不应该受到伤害,它几乎是零努力,并且对性能有很大帮助。而且,更重要的是,与第二种方式相反,如果客户端在使用之前支持 Gzip,它实际上会检查请求标头。当您无头地选择第二种方式时,大约 10% 的万维网用户将无法访问您的 Web 应用程序。这真的不是单线任务。
您可以找到here 的高级示例FileServlet,它支持每个 Gzip 并根据请求标头进行检查。您可能会从中获得新的见解。
【讨论】:
查看 GzipOutputStream 类。像这样的:
response.setContentType(...)
GzipOutputStream os = new GzipOutputStream(response.getOutputStream);
//write to os
Writer writer = new PrintWriter(os);
然后像平常一样使用 writer。
【讨论】:
这是我在学习 servlet 时使用的。也许没有用,但工作! 将下面的代码放入 public class GZIPEncodingServlet extends 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 :(");
}
}
【讨论】:
如果您真的、真的不想再摆弄 Java 代码,您还可以考虑在您的 servlet 容器前挂接一个 Apache 服务器。
如果您有大量静态内容,这实际上可以提高您的性能,因为 Apache 处理静态页面比任何 servlet 容器都要快一些。因此,您可以将其配置为仅将 servlet 请求委托给 localhost 上的 servlet 容器。
Apache 有方便的内置选项来压缩输出。我不记得如何设置它们,但它既简单又多才多艺。它与浏览器协商它们可以处理什么,等等。如有疑问,Apache 通常会比任何 Java 容器在压缩方法上更加精明和最新。
【讨论】:
如果您在 Tomcat 上,连接器可以为您进行压缩。这是我的配置,
<Connector port="8000"
compression="on"
compressionMinSize="1024"
compressableMimeType="text/html,text/xml"
...
/>
如果你在 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);
我认为它足够干净。如果您发现可以改进的地方,请告诉我。谢谢大家的回答!
【讨论】: