Java+GZIP实现后台数据压缩,pako前台解压

一、场景介绍

基于vue的项目中遇到这样一个问题:在做百度地图实现车辆实时轨迹跟踪时,客户端浏览器在发送请求获取服务端数据时,由于服务端的数据量过大(数据少则几千条,多则万级计算),在将服务端轨迹数据渲染到浏览器地图上时,耗时特别大,体验特别差(数据量越大,耗时就越大,少则十几秒)。

二、问题分析

  1. 由于该项目实时轨迹不能使用异步加载服务端数据,因为在获取数据库中数据,开启实时之前,需要将历史数据全部有序的渲染到浏览器地图上,如果使用异步,那么在数据还没有渲染完成,就进行其他的操作,会导致实时轨迹数据经纬度和时间出现差错,同时,如果进行其他操作的话,由于加载轨迹数据和其他操作(如拖动地图,缩放查看全图等)时并列进行,导致界面处于卡顿状态、出现假死、渲染空白滞留等问题,体验也是特别差。所以此处排除异步加载数据,选择同步。
  2. 在获取后台数据时,当数据量越大,耗时越长,问题在于请求服务端的数据后返回的数据包过大,我们可以尽最大限度来压缩数据包,缩短数据请求和渲染时间,从而优化性能。

三、功能实现

为了解决上面的问题,我们可以先在后端对数据进行压缩处理,然后将压缩后的数据发送给前台,前台接收到的数据是压缩后的,不能直接使用,需要先解压,然后在再使用。
此处,后端使用java语言,用Gzip对数据进行压缩,前台使用pako.js对数据进行解压,具体实现方法如下:
压缩前的部分原始数据截图:

后端GZip压缩java代码:

package com.welink.biz.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
*字符串压缩
**/
public class StringCompress{
  /**压缩字符串
  * @param str:正常的需要压缩的字符串
  * @return 压缩后的字符串
  **/
public static String compress(String str) { 
  if (str.length() <= 0) { 
    return str; 
  } 
  try{
    ByteArrayOutputStream bos = null;
    GZIPOutputStream os=null; //使用默认缓冲区大小创建新的输出流
    byte[] bs =null;
    try{
        bos = new ByteArrayOutputStream();
        os = new GZIPOutputStream(bos);
        os.write(str.getBytes()); //写入输出流
        os.close();
        bos.close();
        bs = bos.toByteArray();
        return new String(bs,"ISO-8859-1");
      }finally{
        bs = null;
        bos = null;
        os = null;
      }
    }catch(Exception ex){
      return str;
    }
  } 
}

压缩后的数据截图:

前台使用pako.js对数据进行解压,我们可以将pako.js直接引入到项目中。如果前端是基于vue的话,可以使用npm install pako进行安装,然后在需要使用的组件里引入即可。

前端使用Pako .js的JS解压:

const pako = require('pako');
punzipMsgSTR(str) {
  try {
    var restored = pako.ungzip(str, { to: "string" }); //解压
  } catch (err) {
    console.log(err);
  }
  return restored;
}

解压后的数据截图:

可以看出,解压后的数据是字符串形式的,而我们对数据进行处理时是需要json格式的,所以这数据不能直接拿来使用,需要将字符串数据转化成json格式的数据,所以,在此处写个函数来将字符串转换成json格式:

strToJson(str) {
    var json = eval("(" + str + ")");
    return json;
}

处理后的数据截图:

这时,数据解压完成,就可以对这个数据进行使用了。

前端完整代码如下:

punzipMsgSTR(str) {
  try {
    var restored = pako.ungzip(str, { to: "string" }); //解压
  } catch (err) {
    console.log(err);
  }
  return restored;
},
strToJson(str) {
  varjson=eval("("+str+")");
  returnjson;
},
onlive(){
  let _this = this;
  $.ajax({
    type: "post",
    url: "/api/biz/device/online",
    data: JSON.stringify({
      deviceId: _this.searchText,
      starttime: _this.lasttime
    }),
    contentType: "application/json",
    async: false,
    success: function(res) {
       var data = _this.strToJson(_this.punzipMsgSTR(res));
      /**
       *此处的data 就是已经处理过的数据,即解压过的数据,接下来就可以对该数据进行操作了。
       */
    }
  });
}

这样,从后端压缩,到前端解压就完成了,可以大大缩短数据请求和渲染时间,从而达到优化目的。此场景在现在物联网行业的使用是非常普遍的。

Java+GZIP实现后台数据压缩,pako前台解压

原创文章,作者:Ferrycoln,如若转载,请注明出处:https://ms200.cn/archives/442