视频加载失败

苍穹外卖 Day05:数据统计、定时任务与 JWT 拦截器

980 字
5 分钟
苍穹外卖 Day05:数据统计、定时任务与 JWT 拦截器

内容分三块:数据统计模块(报表 + 工作台)、基于 @Scheduled 的订单超时清理定时任务、用户端 JWT 拦截器;前一天遗留的「/user/** 无拦截器」问题在此闭环。

报表统计(ReportController)#

ReportController 映射 /admin/report,实现集中在 ReportServiceImpl。

营业额统计 getTurnoverStatistics(begin,end):

  • LocalDate 从 begin 递增到 end 收集 dateList:while(!begin.equals(end)) begin = begin.plusDays(1)
  • 每天用 LocalDateTime.of(date, LocalTime.MIN/MAX) 取日界,组装 StatisticsQueryDTO(begin/end/status=COMPLETED)调 orderMapper.sumByMap 做 SUM(amount),null 兜底 0.0
  • 返回 TurnoverReportVO,dateList / turnoverList 都用 StringUtils.join(list, ",") 拼成逗号串

用户统计 getUserStatistics:每天两查——totalUser 只设 end 条件(create_time < end 的累计总数),newUser 同时设 begin 和 end(当天新增);结果装进 UserReportVO(dateList/totalUserList/newUserList 逗号串)。

订单统计 getOrderStatistics(接口别名 /ordersStatistics):每天统计 orderCount(status 为 null)与 validOrderCount(COMPLETED),reduce 汇总 totalOrderCount / totalValidOrderCount,计算完成率时做除零保护;输出 OrderReportVO(总量/有效/完成率)。

销量 Top10 getTop10:orderMapper.getSalesTop10(begin,end) 返回 GoodsSalesDTO(name, number) 列表,拆成 nameList / numberList 逗号串装入 SalesTop10ReportVO。

Excel 导出 export(POI 模板填充):

  • 取近 30 天(now-30 ~ now-1),调 workspaceService.getBusinessData 拿概览数据
  • 读模板 template/运营数据报表模板.xlsx 得到 XSSFWorkbook,按 sheet.getRow(i).getCell(j) 逐行填入:时间范围/营业额/有效订单/完成率/客单价/新增用户,Top10 从第 16 行起填排名/名称/销量
  • 设置下载响应头:response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),文件名经 URLEncoder.encode("运营数据报表.xlsx", UTF_8) 编码防乱码,最终用 ServletOutputStream 写出

工作台数据(WorkspaceServiceImpl)#

  • getBusinessData(begin,end):总订单数(countByMap 不带 status)→ 营业额(sumByMap,status=COMPLETED)→ 有效订单数 → 完成率 = 有效/总 → 客单价 = 营业额/有效订单 → 新增用户走 UserMapper.countByMap
  • getOrderOverView:同一个查询 DTO 换 status 复用 countByMap,依次统计待接单(2)/待派送(3)/已完成(5)/已取消(6)/全部(null)
  • getDishOverView / getSetmealOverView:status=ENABLE/DISABLE 分别用 dishMapper/setmealMapper 的 countByMap 统计起售/停售数量

定时任务处理超时订单#

SkyApplication 加 @EnableScheduling 开启调度。

  • OrderTask.processTimeoutOrder:@Scheduled(cron = "0 * * * * ?") 每分钟执行,查询 now-15min 之前仍处于 PENDING_PAYMENT 的订单(getByStatusAndOrderTimeLT,@Select 注解版),遍历置 CANCELLED 并写入 cancelTime、cancelReason(“订单超时未支付,系统自动取消”)→ orderMapper.update
  • OrderTask.processDeliveryOrder:@Scheduled(cron = "0 0 1 * * ?") 每天凌晨 1 点执行,把派送中超 1 小时的 DELIVERY_IN_PROGRESS 订单置 COMPLETED
  • Mytask.executeTask:每 5 秒一次的练习示例,cron = "0/5 * * * * ?"

cron 表达式共六段:秒 分 时 日 月 周;日与周互斥,不需要的那段用 ? 占位。

用户端 JWT 拦截器#

  • JwtTokenUserInterceptor.preHandle:非 Controller 请求直接放行 → 从 header 取 userTokenName 对应的 token → JwtUtil.parseJWT(userSecretKey, token) 解析 → 从 claims 取出 USER_ID 执行 BaseContext.setCurrentId;校验失败时 response.setStatus(401) 并返回 false
  • WebMvcConfiguration.addInterceptors 注册双拦截器:/admin/** 拦截(排除 /admin/employee/login);/user/** 拦截(排除 /user/user/login、/user/shop/status)

统计 SQL 与通用查询 DTO#

  • StatisticsQueryDTO 以 begin/end/status/categoryId 作类型化查询条件,替代课程原版的 Map map,类型安全增强
  • OrderMapper.xml 三条统计 SQL:
    • sumByMap:select sum(amount) from orders 配 <where> 内 <if> 判断 begin/end/status,动态聚合营业额
    • countByMap:select count(id) from orders 同样的动态条件计数,订单统计与工作台复用
    • getSalesTop10:select od.name, sum(od.number) number from order_detail od, orders o where od.order_id=o.id and o.status=5 [时间过滤] group by od.name order by number desc limit 0,10
  • UserMapper.xml / DishMapper.xml / SetmealMapper.xml 各自提供 countByMap 动态计数

可优化点#

  • 报表的营业额/用户/订单统计都按天循环查询,30 天区间即 30+ 次 SQL;数据量小时无碍,量大可改用 GROUP BY 一次聚合。
  • getTop10 与 export 内存在两段相同的 getSalesTop10 查询逻辑,可抽公用方法。
  • RedisConfiguration.redisTemplate 仍为原始类型,沿用前一天的建议改为 RedisTemplate<String,Object>。

代码锚点#

知识点代码位置
按天遍历生成日期序列ReportServiceImpl.getTurnoverStatistics(while+plusDays)
动态条件统计 SQL(sumByMap/countByMap)OrderMapper.xml sumByMap/countByMap
新增用户 vs 累计用户查询差异getUserStatistics(totalUser 只设 end / newUser 设 begin+end)
订单完成率/客单价计算与除零保护getOrderStatistics、WorkspaceServiceImpl.getBusinessData
联表聚合销量 Top10OrderMapper.xml getSalesTop10(GROUP BY + ORDER BY DESC + LIMIT)
多状态复用 countByMap 概览WorkspaceServiceImpl.getOrderOverView
POI 模板填充导出 ExcelReportServiceImpl.export + ReportController.export
@EnableScheduling + @Scheduled cronSkyApplication + OrderTask
超时订单自动取消(状态机)OrderTask.processTimeoutOrder
用户端 JWT 校验 + 放行逻辑JwtTokenUserInterceptor + WebMvcConfiguration

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!

打赏
苍穹外卖 Day05:数据统计、定时任务与 JWT 拦截器
https://ryuki.icu/posts/sky-takeout-day05/
作者
RK
发布于
2026-08-23
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
RK
Long may the sunshine
公告
Long may the sunshine
分类
标签
最新动态
站点天气
天气加载中…
站点统计
文章
27
分类
6
标签
59
总字数
39,139
篝火已燃
0 天
最后活动
0 天前
每日一签