怎么写一个高性能的导出接口

业务背景

在系统中有这么一个场景,前台页面上有这么一些数据,其中检测结果是通过api调用生成的,每次检测都要调用检测接口。
在这里插入图片描述

现在有个新需求,要导出页面上的数据为excel,也就是如下的导出按钮:

在这里插入图片描述

问题分析

考虑到该页面数据并不是直接通过查询数据库得到,而是由前端输入相应数据后,调用后台检测结果接口生成,如果在调用导出接口时,再次调用后台检测接口,无疑会导致导出接口性能下降,所以笔者通过思考得到以下解决方案:

方案一:
由于数据量不大,前台可以将页面所有数据进行传输到后台,再由后台导出接口直接生成表格后返回;

方案二:
前台在调用后台检测结果接口生成页面后,页面的数据已经是完整的,此时根本无需后台再做数据库之类的操作,可以直接利用开源的生成Excel的工具,前台直接导出;

方案三:
前台在调用后台检测结果接口生成页面后,后台将检测结果存入到redis中,并将redis的key返回给前台,前台将该key存入一个全局变量中,在调用导出接口时,将该全局变量传给后台,后台根据key查找到该缓存数据,将该数据生成表格后返回。

方案对比

方案一可能存在的问题是:在数据量过大的情况下,前台传输数据太多,在传输过程中有丢失的风险;

方案二是由纯js实现的,由于没有试过,对其中存在的风险不予置评,具体实现可以参考这个

方案三中由于采用了缓存,可能出现的问题是:

如果单纯使用一个类似UUID来生成redis的key,不去考虑真实的业务场景,则调用数据生成接口中,前台多次发送相同的数据,却生成了不同的缓存,这显然是不符合业务逻辑的,也会给系统造成很多垃圾数据。

针对这个问题,我的解决方案是:

在调用生成数据接口时,可以考虑在key上加入用户id,再加上特定的“export”字符,以及前台传入的条件,这样大概率就是唯一的redis id,再给前台返回这个key。

由于该数据是临时的,所以必须设置一个过期时间,将过期时间设置为24小时。

最终解决方案

方案一:纯js导出,该方案不需要后台做任何处理,简单易用;具体实现可以参考这个

方案二:即上述方案三,利用redis来提高性能,伪代码如下


public GoodsTypeVO queryAndOperateData(GoodsTypeDTO goodsTypeDTO){
        // 1、queryData from database
        GoodsTypePO goodsTypePO = new GoodsTypePO();
        //2、 operate data
        //3、return data
        GoodsTypeVO goodsTypeVO = new GoodsTypeVO();
        String redisKey = userId + goodsTypeDTO.getGoodsTypeId();
        Int expireTime = 24if (redis.get(redisKey).isEmpty()){
            redis.set(goodsTypeVO,expireTime);
        }
        goodsTypeVO.setRedisKey(redisKey);
        return goodsTypeVO;
    }


    public OutputStream getExcel(String  redisKey){
        List data = redis.get(redisKey).isEmpty();
        if (StringUtils.isEmpty(redisKey)){
            return null;
        }else {
            //excel export
            return Excel.export(data);
        }
    }



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值