JAVA - 实现服务端gzip数据的解析
作者:hangge | 2016-09-23 09:00
样例中客户端先将 json 数据通过 gzip 压缩后发送给服务端。服务端收到数据后先解压缩,再解析数据。最后将解析的数据又返回给客户端。客户端把返回的数据打印出来(如下图)。数据等正确输出说明整个压缩解压的流程是没问题的。

有网友问了,如果我的服务端是用 JAVA 写的,该怎么办。本文我就介绍下 JAVA 如何解压 gzip 数据。
一、创建处理gzip的过滤器
要实现 gzip 解压,我们先要创建个过滤器(servlet Filter),用来对所有的 request 请求进行处理。这样不管我们服务端使用哪种web框架都可以很好地适配。
1,GzipRequestWrapper.java
继承自 HttpServletRequestWrapper,其作用就是判断这个 request 的内容是否使用 gzip 压缩了。如果是压缩的,则对其进行解压。
package filter;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class GzipRequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
public GzipRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public ServletInputStream getInputStream() throws IOException {
ServletInputStream stream = request.getInputStream();
String contentEncoding = request.getHeader("Content-Encoding");
// 如果对内容进行了压缩,则解压
if (null != contentEncoding && contentEncoding.indexOf("gzip") != -1) {
try {
final GZIPInputStream gzipInputStream = new GZIPInputStream(
stream);
ServletInputStream newStream = new ServletInputStream() {
@Override
public int read() throws IOException {
return gzipInputStream.read();
}
};
return newStream;
} catch (Exception e) {
System.out.print("ungzip content fail." + e);
}
}
return stream;
}
}
2,GzipFilter.java
过滤器类。作用是将请求交由上面的 GzipRequestWrapper 来处理。
package filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
* 如果请求消息中包含gzip压缩数据,则进行解压
*/
public class GzipFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(new GzipRequestWrapper((HttpServletRequest) request), response);
}
public void destroy() {
}
}
3,web.xml配置
上面过滤器相关类创建完毕后,我们还需要在 web.xml 对其进行配置。这样过滤器才能生效。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>GzipFilter</filter-name>
<filter-class>filter.GzipFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
</web-app>
JAVA 作为服务端的话,客户端可以将数据提交到 jsp 页面、sevelet 或是 action 中。这里我用 jsp 作为演示,其他两个同理。毕竟过滤器配好以后这个解压处理是通用的。
1,客户端
这个同前文一样,完全没动。只不过将请求地址改成了 jsp 页面地址。
let params:[String : Any] = [
"name": "hangge.com",
"books": ["Swift","Objective-C","PHP"],
"bar": [
"baz": "qux"
]
]
let url = "http://192.168.1.112:8080/test/post.jsp"
Alamofire.request(url, method: .post, parameters: params, encoding: JSONGzipEncoding.default)
.responseString { response in
print(response.result.value!)
}
2,服务端(post.jsp)
我们将收到的数据转成字符串,并输出到页面上(实际上就是返回给客户端)。
<%@ page language="java" import="java.io.*" pageEncoding="utf-8"%>
<%
byte[] bytes = new byte[1024 * 1024];
InputStream is = request.getInputStream();
int nRead = 1;
int nTotalRead = 0;
while (nRead > 0) {
nRead = is.read(bytes, nTotalRead, bytes.length - nTotalRead);
if (nRead > 0)
nTotalRead = nTotalRead + nRead;
}
String str = new String(bytes, 0, nTotalRead, "utf-8");
out.print("服务端收到数据:"+str);
%>
3,客户端将返回数据打印出来
可以看到数据正确打印出来,说明服务端 gzip 数据解压是成功的。

全部评论(0)