背景说明
运营小姐姐每半个月都会找我拉一份数据文件,表头是固定的,就那么几列。里面的逻辑就是关联多张表,分别取到相应的字段写入Excel导出来给到小姐姐就结束了。
一开始呢,是每次小姐姐来找我的时候,我咧,就手动给她拉一份。一般上午和我说,午饭的时候我发给她。
大概在三四十万的量,跑脚本也要跑一会会,还有就是那些表是分开在两个库里面的,一个 MongoDB ,一个 MySQL 。除了一个需要匹配的字段是从 MySQL 里取出来的,其它字段都是从 MongoDB 里拿的。
先是在 MongoDB 里面执行 js 脚本。跑的时间比较久。跑完要人工手动导出来,再导入到 MySQL 里面,sql 的执行就简单了,手动关联下表,取到目标字段,这份数据报表就可以导出来交差了。
但是呢,这么有规律的事情应该是让机器去执行。
自动化功能
做这份报表自动化功能涉及两个接口,一个接口( dataSync )让定时任务调用的,一个接口( download )是给小姐姐下载使用的。每个月的 1 号和 16 号凌晨执行定时任务进行数据的同步。白天的时候小姐姐直接用浏览器就可以下载数据文件了。 dataSync 接口做的事情其实没什么好多介绍的。就是用项目语言将前面提到的那些 js 脚本和 sql 脚本转成功能模块。要注意的是这里涉及到两种数据库,所以需要配置多数据源。
下载文件
文件下载用的是 EasyExcel 。直接用 HttpServletResponse response 就可以直接通过浏览器链接下载了。
@GetMapping("/dataList/download")
public void download(HttpServletResponse response) throws IOException {
try {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("数据-" + LocalDate.now(), "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
List<Entity> dataList = repository.findAll();
logger.info("data size = {}", dataList.size());
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short)12);
headWriteCellStyle.setWriteFont(headWriteFont);
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
contentWriteCellStyle.setFillPatternType(FillPatternType.NO_FILL);
HorizontalCellStyleStrategy horizontalCellStyleStrategy =
new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
EasyExcel.write(response.getOutputStream(), Entity.class).autoCloseStream(Boolean.FALSE).sheet(LocalDate.now().toString()).registerWriteHandler(horizontalCellStyleStrategy)
.doWrite(dataList);
} catch (Exception e) {
logger.error("下载 失败 ERROR MSG => ", e);
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, String> map = new HashMap<String, String>();
map.put("status", "failure");
map.put("message", "下载文件失败" + e.getMessage());
response.getWriter().println(JSON.toJSONString(map));
}
}
```