最近公司项目在做跨国数据同步,采用的方式是使用http请求进行数据同步,因为发送的请求body中内容可能比较多,所以在发送请求时对请求body进行了压缩,在获取到请求时再对body进行解压。
请求压缩
压缩与解压工具类
public class GZIPUtils {
public static final String GZIP_ENCODE_UTF_8 = "UTF-8";
public static byte[] compress(String str) {
if (str == null || str.length() == 0) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip;
try {
gzip = new GZIPOutputStream(out);
gzip.write(str.getBytes(GZIP_ENCODE_UTF_8));
gzip.close();
} catch ( Exception e) {
e.printStackTrace();
}
return out.toByteArray();
}
}
发送请求
public class HttpClientUtils {
public static void main(String[] args) throw Exception{
String body = "{\"name\":\"zhangsan\"}";
HttpClient httpClient = HttpClients.createDefault();
HttpPost post = new HttpPost(“http://localhost:8080/test”);
post.setHeader("Content-Type", "application/json;charset=utf-8");
post.setHeader("Accept", "application/json");
post.setHeader("Content-Encoding", "gzip");
byte[] gzipEncrypt = GZIPUtils.compress(body);
post.setEntity(new InputStreamEntity(new ByteArrayInputStream(gzipEncrypt),gzipEncrypt.length));
HttpResponse httpResponse = httpClient.execute(post);
int code = httpResponse.getStatusLine().getStatusCode();
HttpEntity response = httpResponse.getEntity();
System.out.println("请求状态码:" + code);
System.out.println("请求返回结果:" + EntityUtils.toString(response));
}
}
接受请求(GZIPFilter )
@WebFilter(filterName = "GZIPFilter", urlPatterns = "*")
public class GZIPFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(new GZIPRequestWrapper((HttpServletRequest) request),response);
}
@Override
public void destroy() {}
}
GZIPRequestWrapper
public class GZIPRequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
private static final Logger LOGGER = LoggerFactory.getLogger(GZIPRequestWrapper.class);
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); //将body的流通过GZIPInputStream解压
// 因为请求body中的流已经被读完了,所以这里需要将流重新写回去,不然在Controller接收RequestBody时就因为流被读完获取不到数据
ServletInputStream newStream = new ServletInputStream() {
@Override
public int read() throws IOException {
return gzipInputStream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener arg0) {
// TODO Auto-generated method stub
}
};
return newStream;
} catch (Exception e) {
LOGGER.debug("ungzip fail", e);
}
}
return stream;
}
}
这样就可以实现请求body内容的压缩与解压了