场景:
客户端发送给服务端的数据过长,由于带宽受限及浏览速度的因素,需要压缩数据进行传输。
本文使用的压缩算法是Gzip,客户端压缩了以后再传输给服务端。
不是C到S,HTTP协议的两端也可以。
贴一下压缩的工具类CompressUtils
package com.yolanda.myspringboot.compress;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* @Author:Yolanda
* @Date: 2020/5/7 14:30
*/
public class CompressUtils {
private static final String GZIP_ENCODE_UTF_8 = "UTF-8";
private static final String GZIP_ENCODE_ISO_8859_1 = "ISO-8859-1";
private static final int BYTE_NUM = 256;
/**
*
* compress:压缩数据方法 <br/>
* @param str
* String
* @return
* String
* @throws IOException
* IOException
*/
public static String compress(String str) throws IOException {
return new String(compressData(str, GZIP_ENCODE_UTF_8), GZIP_ENCODE_ISO_8859_1);
}
// public static byte[] compress(String str) throws IOException {
// return compressData(str, GZIP_ENCODE_UTF_8);
// }
/**
*
* decompressToStr:解压缩数据方法 <br/>
* @param byteStr
* String
* @return
* String
*/
public static String decompressToStr(String byteStr) {
byte[] bytes;
try {
bytes = byteStr.getBytes(GZIP_ENCODE_ISO_8859_1);
return decompressDataToStr(bytes, GZIP_ENCODE_UTF_8);
} catch (UnsupportedEncodingException e) {
System.out.println("解压缩数据转码失败:" + e.getMessage());
}
return null;
}
/**
*
* compressData:压缩数据具体处理方法 <br/>
* @param str
* String
* @param encoding
* String
* @return
* byte[]
*/
public static byte[] compressData(String str, String encoding) {
if (str == null || str.length() == 0) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip;
try {
gzip = new GZIPOutputStream(out);
gzip.write(str.getBytes(encoding));
gzip.close();
} catch (IOException e) {
System.out.println("压缩数据失败:" + e.getMessage());
}
return out.toByteArray();
}
/**
*
* decompressDataToStr:解压缩数据具体处理方法 <br/>
* @param bytes
* byte[]
* @param encoding
* String
* @return
* String
*/
public static String decompressDataToStr(byte[] bytes, String encoding) {
if (bytes == null || bytes.length == 0) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
try {
GZIPInputStream ungzip = new GZIPInputStream(in);
byte[] buffer = new byte[BYTE_NUM];
int n;
while ((n = ungzip.read(buffer)) >= 0) {
out.write(buffer, 0, n);
}
return out.toString(encoding);
} catch (IOException e) {
System.out.println("解压缩数据失败:" + e.getMessage());
}
return null;
}
}
这里需要注意的是,这个工具类如果不是发给服务端的,用这个注释掉的压缩方法没有问题
// public static byte[] compress(String str) throws IOException {
// return compressData(str, GZIP_ENCODE_UTF_8);
// }
如果是要传输的就不能用UTF-8,要用ISO-8859-1编码方式。如果用UTF-8编码方式传输,服务端拿到的数据是空值。
上述的工具类CompressUtils ,两端都要写哦,一端用压缩方法,另一端用解压缩方法。
我再贴一下写的简单测试类吧,看一下压缩的效果。
Main.java
package com.yolanda.mycompressclient.compress;
import java.io.IOException;
/**
* @Author:Yolanda
* @Date: 2020/5/7 15:01
*/
public class Main {
public static void main(String [] args){
String test="test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890";
System.out.println("压缩前长度" + test.length());
try{
String afterCompressStr = CompressUtils.compress(test);
System.out.println("压缩后长度" + afterCompressStr.length());
}catch (IOException e){
System.out.println(e.getMessage());
}
}
}
控制台输出结果
用springboot写了简单的客户端和服务端做测试。
(用springboot写是因为方便简单,朋友你也可以用别的框架写)
也贴一下代码,主要是测试客户端压缩了数据能成功发给服务端,服务端可以成功解压出客户端发送过来的数据。
服务端很简单
HelloController类
package com.yolanda.myspringboot;
import com.yolanda.myspringboot.compress.CompressUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author:Yolanda
* @Date: 2020/5/7 13:41
*/
@RestController
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello(String data){
return "Hello, Yolanda!我在服务端接收到了你发送过来的数据,解压后是:"
+ CompressUtils.decompressToStr(data);
}
}
这里在application.properties配置文件里把服务端的端口设置成8081(因为后面客户端默认的8080)
server.port=8081
客户端稍微复杂一丢丢
因为要发HTTP请求,所以用了springboot的http工具
springboot里面发http请求也,太太太太简单了吧
pom文件里写入依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
新建一个HttpClient接口类
package com.yolanda.mycompressclient.http;
import org.springframework.http.HttpMethod;
import org.springframework.util.MultiValueMap;
/**
* @Author:Yolanda
* @Date: 2020/5/7 18:10
*/
public interface HttpClient {
public String client(String url, HttpMethod method, MultiValueMap<String,String> params);
}
然后新建一个HttpClientImpl类去实现它
package com.yolanda.mycompressclient.http.impl;
import com.yolanda.mycompressclient.http.HttpClient;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
/**
* @Author:Yolanda
* @Date: 2020/5/7 18:11
*/
@Service
public class HttpClientImpl implements HttpClient {
public String client(String url, HttpMethod method, MultiValueMap<String,String> params){
RestTemplate template = new RestTemplate();
return template.postForObject(url, params, String.class);
}
}
在Controller层里来测试压缩吧
package com.yolanda.mycompressclient.controller;
import com.yolanda.mycompressclient.compress.CompressUtils;
import com.yolanda.mycompressclient.http.HttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
/**
* @Author:Yolanda
* @Date: 2020/5/7 18:05
*/
@Controller
public class TestController {
@Autowired
HttpClient httpClient;
@RequestMapping(value = "/compress")
@ResponseBody
public String hello(){
String url = "http://localhost:8081/hello";
HttpMethod method = HttpMethod.GET;
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
String test="test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890";
String afterCompressStr = "";
try {
afterCompressStr = CompressUtils.compress(test);
}catch (IOException e){
System.out.println(e.getMessage());
}
params.add("data", afterCompressStr);
String response = httpClient.client(url, method, params);
System.out.println(response);
return response;
}
}
服务端和客户端一起跑起来
浏览器输入http://localhost:8080/compress
(这是客户端的)
收到了来自客户端的返回。