背景 公司项目有个需求, 前端上传excel文件, 后端读取数据、处理数据、返回错误数据, 最简单的方式同步处理, 客户端上传文件后一直阻塞等待响应, 但用户体验无疑很差, 处理数据可能十分耗时, 没人愿意傻等, 由于项目暂未使用ActiveMQ等消息队列中间件, 而redis的lpush和rpop很适合作为一种轻量级的消息队列实现, 所以用它完成此次功能开发
一、本文涉及知识点
-
excel文件读写--阿里easyexcel sdk
-
文件上传、下载--腾讯云对象存储
-
远程服务调用--restTemplate
-
生产者、消费者--redisTemplate leftPush和rightPop操作
-
异步处理数据--Executors线程池
-
读取网络文件流--HttpClient
-
自定义注解实现用户身份认证--JWT token认证, 拦截器拦截标注有@LoginRequired注解的请求入口
当然, Java实现咯 涉及的知识点比较多, 每一个知识点都可以作为专题进行学习分析, 本文将完整实现呈现出来, 后期拆分与小伙伴分享学习
二、项目目录结构
编辑
添加图片注释,不超过 140 字(可选)
项目结构
说明: 数据库DAO层放到另一个模块了, 不是本文重点
三、主要maven依赖
easyexcel
添加图片注释,不超过 140 字(可选)
JWT
编辑切换为居中
添加图片注释,不超过 140 字(可选)
redis
编辑切换为居中
添加图片注释,不超过 140 字(可选)
腾讯cos
编辑切换为居中
添加图片注释,不超过 140 字(可选)
四、流程
-
用户上传文件
-
将文件存储到腾讯cos
-
将上传后的文件id及上传记录保存到数据库
-
redis生产一条导入消息, 即保存文件id到redis
-
请求结束, 返回"处理中"状态
-
redis消费消息
-
读取cos文件, 异步处理数据
-
将错误数据以excel形式上传至cos, 以供用户下载, 并更新处理状态为"处理完成"
-
客户端轮询查询处理状态, 并可以下载错误文件
-
结束
五、实现效果
-
上传文件 上传文件
-
数据库导入记录 数据库导入记录
-
导入的数据 导入的数据
-
下载错误文件 下载错误文件
-
错误数据提示 错误数据提示
-
查询导入记录 查询导入记录
六、代码实现
1、导入excel控制层
@LoginRequired @RequestMapping(value = "doImport", method = RequestMethod.POST) public JsonResponse doImport(@RequestParam("file") MultipartFile file, HttpServletRequest request) { PLUser user = getUser(request); return orderImportService.doImport(file, user.getId()); }
2、service层
@Override public JsonResponse doImport(MultipartFile file, Integer userId) { if (null == file || file.isEmpty()) { throw new ServiceException("文件不能为空"); } String filename = file.getOriginalFilename(); if (!checkFileSuffix(filename)) { throw new ServiceException("当前仅支持xlsx格式的excel"); } // 存储文件