Java记一次前后端大数据压缩过程
近期开发一个功能时,发现后端返回的数据量太大,前端解析也很慢,严重影响了用户体验,然后有了这次调优过程。先说下环境:jdk 1.8springboot,cloudvuepgsql测试工具:postmanChorme在网上也找了很多的方法,有点是后端压缩了,但是速度也不理想,有的是后端加密了,前端解不了等等原因。整个结论结果就是:后端使用Base64压缩,前端使用Base64解压,其中依靠编码转换方
近期开发一个功能时,发现后端返回的数据量太大,前端解析也很慢,严重影响了用户体验,然后有了这次调优过程。
先说下环境:
jdk 1.8
springboot ,cloud
vue
pgsql
测试工具:
postman
Chorme
在网上也找了很多的方法,有点是后端压缩了,但是速度也不理想,有的是后端加密了,前端解不了等等原因。
整个结论结果就是:
后端使用Base64压缩,前端使用Base64解压,其中依靠编码转换方法(unzip)。
没有时间的码友可以直接复制结果:
前端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Access-Control-Allow-Origin" content="*" />
<title>Title</title>
<script
src="http://libs.baidu.com/jquery/1.9.0/jquery.js">
</script>
<script
src="https://cdn.bootcss.com/pako/1.0.8/pako.min.js">
</script>
</head>
<body>
<p id="bar"></p>
<script>
let Utf8ArrayToStr = function(array) {
let out = "", i = 0, len = array.length,
char1, char2, char3, char4;
while(i < len) {
char1 = array[i++];
if (char1 >> 4 <= 7) {
out += String.fromCharCode(char1);
} else if (char1 >> 4 == 12 || char1 >> 4 == 13) {
char2 = array[i++];
out += String.fromCharCode(((char1 & 0x1F) << 6)
| (char2 & 0x3F));
} else if (char1 >> 4 == 14) {
char2 = array[i++];
char3 = array[i++];
char4 = ((char1 & 0x0F) << 12)
| ((char2 & 0x3F) << 6);
out += String.fromCharCode(char4
| ((char3 & 0x3F) << 0));
}
}
return out;
};
function unzip(b64Data) {
let strData = atob(b64Data);
let charData = strData.split('').map(function (x) {
return x.charCodeAt(0);
});
let binData = new Uint8Array(charData);
let data = pako.inflate(binData);
//strData = Utf8ArrayToStr(data)
largeuint8ArrToString(data,(item) =>{
console.log(item);
});
//let json = JSON.parse(strData);
//let children = json['children'];
//正则表达式 匹配全部"\" 需要加 /g
//let reg = /\\/g;
//使用replace方法将全部匹配正则表达式的转义符替换为空
//let replaceAfter = children.replace(reg,'');
return strData;
};
function largeuint8ArrToString(uint8arr, callback) {
var bb = new Blob([uint8arr]);
var f = new FileReader();
f.onload = function(e) {
callback(e.target.result);
};
f.readAsText(bb);
}
$(function () {
jQuery.support.cors = true;
let date = new Date();
let now = date.getTime();
console.log('开始时间===='+now);
$.ajax({
type: "get",
url: "http://xxxxxx/93",
success: function (data, status) {
if (status == "success") {
let result = unzip(data.data);
//let childrens = JSON.parse(result);
//console.log(childrens);
//let oDiv = document.getElementById("bar");
//oDiv.innerHTML =result;
let date1 = new Date();
let end = date1.getTime();
let endTime = end-now;
console.log('用时==='+endTime);
}
},
error: function (e,data) {
let oDiv = document.getElementById("bar");
oDiv.innerHTML =unzip(e.responseText) ;
},
complete: function () {
}
});
});
</script>
</body>
</html>
Java:
public class Base64Utils {
// 压缩字符串
public static String compressData(String data) throws UnsupportedEncodingException {
//要传输的字符串
try {
//压缩后写入字节流发送
ByteArrayOutputStream
box = new ByteArrayOutputStream();
DeflaterOutputStream
dos = new DeflaterOutputStream(box);
// 压缩并将压缩后的内容输出到字节输出流box中
dos.write(data.getBytes());
dos.close();
return getenBASE64inCodec(box.toByteArray());
} catch (Exception ex) {
ex.printStackTrace();
return "error";
}
}
//为了压缩后的内容能够在网络上传输,一般采用Base64编码
public static String getenBASE64inCodec(byte [] b) {
if (b == null) return null;
return new String(Base64.encodeBase64(b, false));
}
}
第一步:
首先数据库,因为数据的特殊,查询时间在1s左右,整个后端处理完,大概不到2s。
浏览器F12看方法执行等待时间超5s,下载数据10x s,下载104m(未压缩),前端再渲染出来超过了1分钟,加上网络因素有的可达到2min +。
第二步:
思路是,将大数据在项目启动时,放入Redis,省去客户点击时,从数据库取的时间,尝试时间与之前基本没变。后面采取了几种压缩方式,将内存压缩到了20+m,但是要不前端解不了,要不就是数据格式有问题,最后采取的是上面方式,将数据在项目启动时,放入Redis之前压缩加密,取时判断key是否存在,若存在,直接返回,而且将加密的字符串放入Redis,存取都更快。前前后后所用整个后端处理时间+前端处理时间控制在3-5s内。比之前快了很多,目前用的就是这种解决方法。
上一张图:
更多推荐
所有评论(0)