近期开发一个功能时,发现后端返回的数据量太大,前端解析也很慢,严重影响了用户体验,然后有了这次调优过程。

先说下环境:

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内。比之前快了很多,目前用的就是这种解决方法。

上一张图:

数据大屏java后端实现_restful