JAVA - 实现服务端gzip数据的解析
样例中客户端先将 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 数据解压是成功的。