Day28 - 工作台与 Apache POI 导出报表
一、工作台
1.1 功能概述
工作台模块为管理端首页提供概览数据,包含四个接口:
| 接口 | 路径 | 返回内容 |
|---|---|---|
| 今日数据查询 | /admin/workspace/businessData |
营业额、有效订单数、完成率、客单价、新增用户数 |
| 订单管理数据 | /admin/workspace/overviewOrders |
各状态订单数量(待接单、待派送、已完成、已取消、全部) |
| 菜品总览 | /admin/workspace/overviewDishes |
启售数量、停售数量 |
| 套餐总览 | /admin/workspace/overviewSetmeals |
启售数量、停售数量 |
1.2 实现方式
工作台代码以”代码导入”方式引入,共三个核心类:
WorkSpaceController:接收请求,今日数据查询时自动计算当天的开始和结束时间WorkspaceService/WorkspaceServiceImpl:调用各 Mapper 获取统计数据
1 | // Controller 中自动计算当天时间范围 |
1.3 工作台依赖的 Mapper 方法
工作台大量调用 day11 引入的通用 sumByMap(Map) 和 countByMap(Map) 方法。由于我 day11 的报表实现与讲义不同(自己用了 turnoverStatistics、ordersStatistics 等专用方法),这些通用方法在代码仓库中缺失,需要补全后工作台才能正常编译。
补全的方法分布:
| Mapper | 方法 | 作用 |
|---|---|---|
OrderMapper |
Double sumByMap(Map map) |
按动态条件(status + 时间范围)求营业额 |
OrderMapper |
Integer countByMap(Map map) |
按动态条件统计订单数量 |
UserMapper |
Integer countByMap(Map map) |
按动态条件统计用户数量 |
DishMapper |
Integer countByMap(Map map) |
按动态条件(status + categoryId)统计菜品数量 |
SetmealMapper |
Integer countByMap(Map map) |
按动态条件统计套餐数量 |
这些方法全部使用 <where> + <if> 动态 SQL,Service 层通过往 Map 里放不同的 key 来灵活控制查询条件,一个 Mapper 方法应对多种查询场景。例如 getOrderOverView 中对同一个 countByMap 传 5 次不同的 status,分别查出各状态订单数。
二、Apache POI
2.1 概述
Apache POI 是一个处理 Microsoft Office 文件格式的开源 Java 库,一般用于读写 Excel 文件。常见应用场景包括导出交易明细、业务报表、批量导入数据等。
项目通过 Maven 引入两个依赖:
1 | <dependency> |
2.2 核心 API
POI 操作 Excel 的核心类都在 org.apache.poi.xssf.usermodel 包下,层级关系为 工作簿 → Sheet 页 → 行 → 单元格:
| 类 | 对应 Excel 概念 | 常用方法 |
|---|---|---|
XSSFWorkbook |
Excel 文件(工作簿) | new XSSFWorkbook(inputStream) 基于模板创建;getSheet("Sheet1") 获取 Sheet;write(out) 写入输出流;close() 关闭 |
XSSFSheet |
Sheet 页 | getRow(i) 获取指定行;createRow(0) 创建行 |
XSSFRow |
行 | getCell(j) 获取单元格;createCell(j) 创建单元格;setCellValue(value) 设置值 |
XSSFCell |
单元格 | getStringCellValue() 获取文本值 |
注意:行号和列号均从 0 开始计数。
getRow(3)获取的是第 4 行,getCell(2)获取的是第 3 列。
三、导出运营数据报表
3.1 需求与接口设计
导出最近 30 天的运营数据为 Excel 文件。接口特点:
GET 请求,不需要任何请求参数(后端计算近 30 天范围)
无返回数据,本质是文件下载——通过输出流将 Excel 写到客户端浏览器
需要提前设计好 Excel 模板文件,放到
resources/template/目录下
3.2 实现步骤
1 | 1. 设计 Excel 模板文件(含表头、格式) |
3.3 关键代码
Controller 层
1 |
|
返回类型为 void,不返回 JSON,直接操作 HttpServletResponse 的输出流。
Service 层核心实现
1 | public void exportExcel(HttpServletResponse response) { |
3.4 两个关键点
获取模板输入流——通过 ClassLoader 从 classpath 读取模板文件,而非磁盘绝对路径:
1 | InputStream in = this.getClass().getClassLoader() |
前提是模板文件已放在 src/main/resources/template/ 目录下,编译后会出现在 classpath 中。
获取输出流——通过 HttpServletResponse 获取浏览器的输出流:
1 | ServletOutputStream out = response.getOutputStream(); |
不需要设置响应头,浏览器会直接弹出文件下载。
3.5 模板文件的结构
模板 运营数据报表模板.xlsx 是提前设计好的 Excel 文件,包含固定的表头和格式。数据写入时需要严格对应行列号:
| 行号(0 基) | 内容 |
|---|---|
| 1 | 日期范围(第2列) |
| 3 | 概览:营业额(第3列)、完成率(第5列)、新增用户(第7列) |
| 4 | 概览:有效订单(第3列)、客单价(第5列) |
| 7 ~ 36 | 30 天明细:日期、营业额、有效订单、完成率、客单价、新增用户 |
今日总结
| 模块 | 核心要点 |
|---|---|
| 工作台 | 管理端首页概览,4 个接口分别查今日营业数据、各状态订单数、菜品/套餐启售停售数 |
| 通用 Mapper 方法 | sumByMap(Map) / countByMap(Map) 用动态 SQL 灵活组合条件,工作台和导出报表都依赖它们;由于 day11 自实现方式不同,需补全这些方法 |
| Apache POI | Java 操作 Excel 的库,核心类层级:XSSFWorkbook → XSSFSheet → XSSFRow → XSSFCell,行列号从 0 开始 |
| 导出报表 | GET 请求无参数无返回值,本质是文件下载;步骤为设计模板 → 查询数据 → 写入 Excel → 输出流下载 |
| 模板输入流 | this.getClass().getClassLoader().getResourceAsStream("template/xxx.xlsx") 从 classpath 读取模板 |
| 浏览器输出流 | response.getOutputStream() 获取输出流,excel.write(out) 写入后关闭资源 |