使用 Java Servlet 提供 Gzip 压缩的内容
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1862908/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Serve Gzipped content with Java Servlets
提问by Pablo Fernandez
I was wondering if there was an easyway to serve GZipped content with Java Servlets. I already have the app up and running so the modifications needed should be too heavy.
我想知道是否有一种简单的方法可以使用 Java Servlet 提供 GZipped 内容。我已经启动并运行了该应用程序,因此所需的修改应该太繁重了。
I have access to the response object just at the end of the doPost/doGet method, so I'm looking for something like
我可以在 doPost/doGet 方法的末尾访问响应对象,所以我正在寻找类似的东西
response.setGzip(true);
It doesn't have to be that easybut it would be ideal.
它不必那么容易,但它会是理想的。
Thanks a lot
非常感谢
回答by Paul Wagland
Depending on your container, the container will most likely do this for you. It may do it automatically, or you might need to manually configure it to do it for you. The advantage of this method is zero code changes. And, again, depending on container, you can conditionally enable/disable the compression based on where the request comes from or source browser.
根据您的容器,容器很可能会为您执行此操作。它可能会自动完成,或者您可能需要手动配置它来为您完成。这种方法的优点是代码更改为零。而且,同样,根据容器,您可以根据请求来自何处或源浏览器有条件地启用/禁用压缩。
For Tomcat, have a look at the compression attribute on the HTTP config pages (v5.5, v6.0).
回答by maximdim
Look at GzipOutputStream class. Something like this:
查看 GzipOutputStream 类。像这样的东西:
response.setContentType(...)
GzipOutputStream os = new GzipOutputStream(response.getOutputStream);
//write to os
Writer writer = new PrintWriter(os);
Then use writer like you do usually.
然后像往常一样使用 writer。
回答by BalusC
There are basically 2 ways:
基本上有2种方式:
- Configure it in the appserver. In for example Tomcat you just need to set the
compressionattribute of theConnectorinconf/server.xmltoon. - Wrap the
response.getOutputStream()in anew GzipOutputStream()and write to it instead.
- 在应用程序服务器中配置它。例如在 Tomcat 中,您只需要将in的
compression属性设置为。Connectorconf/server.xmlon - 将
response.getOutputStream()a包裹起来new GzipOutputStream()并写入它。
The first way affects the whole webapp, but this really shouldn't hurt, it's almost zero effort and a big favour for performance. And, more importantingly, as opposed to the second way it actually checks the request headers if the client supportsGzip before using it. When you go for the 2nd way headlessly, then about 10% of the world wide web users wouldn't be able to access your webapplication. This is really not an oneliner task.
第一种方式影响整个 webapp,但这真的不应该受到伤害,它几乎是零努力并且对性能有很大的帮助。而且,更重要的是,与第二种方式相反,如果客户端在使用 Gzip 之前支持它,它实际上会检查请求标头。如果您无头地采用第二种方式,那么大约 10% 的万维网用户将无法访问您的 Web 应用程序。这真的不是单线任务。
You can find herean advanced example of a FileServletwhich supports under each Gzip and checks that based on the request headers. You may get new insights out of it.
您可以在此处找到一个高级示例,FileServlet它支持每个 Gzip 并根据请求标头进行检查。你可能会从中获得新的见解。
回答by ZZ Coder
If you are on Tomcat, the connector can do compression for you. This is my configuration,
如果您使用的是 Tomcat,则连接器可以为您进行压缩。这是我的配置
<Connector port="8000"
compression="on"
compressionMinSize="1024"
compressableMimeType="text/html,text/xml"
...
/>
If you run Apache httpd in front of Tomcat, you should use mod_gzip, which does a much better job.
如果您在 Tomcat 前面运行 Apache httpd,您应该使用 mod_gzip,它会做得更好。
回答by Pablo Fernandez
Just wanted to let you know what I ended doing.
只是想让你知道我最后做了什么。
I made a wrapper of the request class that looks like this:
我制作了一个请求类的包装器,如下所示:
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;
}
}
And then on my BaseAction, which is basically a TemplateMethod for other "Actions" I wrap the response like this:
然后在我的BaseAction,它基本上是其他“操作”的 TemplateMethod ,我像这样包装响应:
if(supportsCompression(request)){
response.setHeader("Content-Encoding", "gzip");
response = GzippedResponse.wrap(response);
}
action.macroExecute(request,response);
I think its clean enough. If you find something that can be improved, please let me know. Thanks everybody for the answers!
我认为它足够干净。如果您发现可以改进的地方,请告诉我。谢谢大家的回答!
回答by Carl Smotricz
If you really, really don't want to fiddle with the Java code any more, you could also consider hooking an Apache server in front of your servlet container.
如果您真的,真的不想再摆弄 Java 代码,您还可以考虑在 servlet 容器前挂接一个 Apache 服务器。
If you have a lot of static content, this could actually improve performance for you, as the Apache will be a bit faster for static pages than any servlet container. So you'd configure it to only delegate servlet requests to your servlet container on localhost.
如果您有很多静态内容,这实际上可以提高您的性能,因为 Apache 的静态页面比任何 servlet 容器都要快一些。因此,您可以将其配置为仅将 servlet 请求委托给 localhost 上的 servlet 容器。
Apache has handy built-in options for compressing output. I don't remember how to set them, but it's easy and versatile. It negotiates with browsers about what they can handle, and so on. In case of doubt, Apache will generally be more savvy and up-to-date on compression methods than any Java container.
Apache 具有用于压缩输出的方便的内置选项。我不记得如何设置它们,但它很简单而且用途广泛。它与浏览器就它们可以处理的内容进行协商,等等。如有疑问,Apache 在压缩方法方面通常比任何 Java 容器都更精明和最新。
回答by Oleg Litvinenko
This's what I used while learning about servlets. Maybe not usefully, but working!!! Laid below code into public class GZIPEncodingServlet extends HttpServlet {...}
这是我在学习 servlet 时使用的。也许没有用,但工作!将下面的代码放入公共类 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 :(");
}
}

