苍穹外卖--day11

目录

[Day11-01-Apache ECharts_介绍](#Day11-01-Apache ECharts_介绍)

[Day11-02-Apache ECharts_入门案例](#Day11-02-Apache ECharts_入门案例)

[Day11-03 - 营业额统计_需求分析和设计](#Day11-03 - 营业额统计_需求分析和设计)

[Day11-04 - 营业额统计_代码开发_1](#Day11-04 - 营业额统计_代码开发_1)

问题:注解@DateTimeFormat是干什么的?

[Day11-05 - 营业额统计_代码开发_2](#Day11-05 - 营业额统计_代码开发_2)

问题:图中.min什么意思?

问题:给mapper层传map参数,mapper层为什么能直接使用?

[Day11-06 - 营业额统计_代码开发_3](#Day11-06 - 营业额统计_代码开发_3)

[Day11-07 - 营业额统计_代码开发_4](#Day11-07 - 营业额统计_代码开发_4)

问题:营业额是怎么统计的?(代码)

[Day11-08 - 营业额统计_功能测试](#Day11-08 - 营业额统计_功能测试)

[Day11-09 - 用户统计_需求分析和设计](#Day11-09 - 用户统计_需求分析和设计)

[Day11-10 - 用户统计_代码开发_1](#Day11-10 - 用户统计_代码开发_1)

[Day11-11 - 用户统计_代码开发_2](#Day11-11 - 用户统计_代码开发_2)

[Day11-12 - 用户统计_代码开发_3](#Day11-12 - 用户统计_代码开发_3)

[Day11-13 - 用户统计_功能测试](#Day11-13 - 用户统计_功能测试)

[Day11-14 - 订单统计_需求分析和设计](#Day11-14 - 订单统计_需求分析和设计)

关键:

[Day11-15 - 订单统计_代码开发_1](#Day11-15 - 订单统计_代码开发_1)

[Day11-16 - 订单统计_代码开发_2](#Day11-16 - 订单统计_代码开发_2)

[Day11-17 - 订单统计_功能测试](#Day11-17 - 订单统计_功能测试)

[Day11-18 - 销量排名统计_需求分析和设计](#Day11-18 - 销量排名统计_需求分析和设计)

关键:

[Day11-19 - 销量排名统计_代码开发_1](#Day11-19 - 销量排名统计_代码开发_1)

[Day11-20 - 销量排名统计_代码开发_2](#Day11-20 - 销量排名统计_代码开发_2)

问题:为什么需要将获取的数据变成字符串类型的以及怎么转换的?

[Day11-21 - 销量排名统计_功能测试](#Day11-21 - 销量排名统计_功能测试)

总结


Day11-01-Apache ECharts_介绍

Day11-02-Apache ECharts_入门案例

Day11-03 - 营业额统计_需求分析和设计

Day11-04 - 营业额统计_代码开发_1

问题:注解@DateTimeFormat是干什么的?

规定日期的格式

Day11-05 - 营业额统计_代码开发_2

问题:图中.min什么意思?

问题:给mapper层传map参数,mapper层为什么能直接使用?

Day11-06 - 营业额统计_代码开发_3

Day11-07 - 营业额统计_代码开发_4

问题:营业额是怎么统计的?(代码)

先得确定前端传来的开始日期和结束日期

然后使用List<DateTime> 来封装从开始到结束的每一天的集合

复制代码
List<LocalDate> dateList = new ArrayList<>();

dateList.add(begin);

while (!begin.equals(end)) {
    //日期计算,计算指定日期的后一天对应的日期
    begin = begin.plusDays(1);
    dateList.add(begin);
}

然后存放每天的营业额(需要从数据库中查询),这时候使用LocalTime.min/max来统计一整天的营业额,设置map给mapper层传参

复制代码
//存放每天的营业额
List<Double> turnoverList = new ArrayList<>();
for (LocalDate date : dateList) {
    //查询date日期对应的营业额数据,营业额是指:状态为“已完成”的订单金额合计
    LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
    LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);

    // select sum(amount) from orders where order_time > beginTime and order_time < endTime and status = 5
    Map map = new HashMap();
    map.put("begin", beginTime);
    map.put("end", endTime);
    map.put("status", Orders.COMPLETED);
    Double turnover = orderMapper.sumByMap(map);
    turnover = turnover == null ? 0.0 : turnover;
    turnoverList.add(turnover);
}

Day11-08 - 营业额统计_功能测试

Day11-09 - 用户统计_需求分析和设计

Day11-10 - 用户统计_代码开发_1

Day11-11 - 用户统计_代码开发_2

问题:下面代码什么意思?

复制代码
//封装结果数据
return UserReportVO
        .builder()
        .dateList(StringUtils.join(dateList, ","))
        .totalUserList(StringUtils.join(totalUserList, ","))
        .newUserList(StringUtils.join(newUserList, ","))
        .build();

Day11-12 - 用户统计_代码开发_3

Day11-13 - 用户统计_功能测试

Day11-14 - 订单统计_需求分析和设计

关键:

下图的订单总数/有效订单/订单完成率都是整段时间的,就拿下图来说是4-1到4-14的

Day11-15 - 订单统计_代码开发_1

Day11-16 - 订单统计_代码开发_2

Day11-17 - 订单统计_功能测试

Day11-18 - 销量排名统计_需求分析和设计

关键:

因为看数量,还需要合并(可能有多个例如炒饼) group by

不止查一个订单表,因为我们需要统计的是其状态已经完成的,取消等其他的不算,所以还需要去查订单详情表 (关联查询,id==id)

Day11-19 - 销量排名统计_代码开发_1

Day11-20 - 销量排名统计_代码开发_2

问题:为什么需要将获取的数据变成字符串类型的以及怎么转换的?

  • stream().map():遍历列表,把每个 GoodsSalesDTO 对象里的 name/number 取出来,形成新的列表。
  • 举例:salesTop10 里有 {name:"可乐", number:100}{name:"汉堡", number:80},提取后:
    • names["可乐", "汉堡"]
    • numbers[100, 80]

Day11-21 - 销量排名统计_功能测试

总结

摘要:本文档记录了Apache ECharts数据可视化工具的学习过程,重点讲解了营业额统计、用户统计、订单统计和销量排名统计四个模块的开发。主要内容包括:1)使用@DateTimeFormat注解处理日期格式;2)营业额统计通过查询&quot;已完成&quot;订单金额合计实现;3)用户统计通过StringUtils.join()方法处理数据;4)订单统计需注意时间段汇总;5)销量排名统计需关联查询订单表与订单详情表,并使用stream().map()转换数据格式。文档详细记录了各模块的需求分析、代码开发

Day11 数据统计与可视化核心知识点总结

本次课程围绕Apache ECharts 可视化与后端数据统计展开,通过营业额统计、用户统计、订单统计、销量排名统计四个核心业务场景,完整实现了「数据查询 → 格式转换 → 前端图表展示」的全流程,同时串联了 Spring Boot 与 MyBatis 的核心技术应用。

一、Apache ECharts 基础与入门

  1. 核心概念

Apache ECharts 是一款开源的 JavaScript 可视化库,用于快速构建折线图、柱状图、饼图等各类图表,适配 PC 与移动端,支持海量数据渲染与交互效果。

  1. 入门核心步骤

引入 ECharts CDN 或本地资源,在 HTML 中创建容器(<div>)并设置宽高;

初始化 ECharts 实例:let myChart = echarts.init(document.getElementById('容器ID'));

配置 option 对象,定义图表的 X 轴、Y 轴、系列数据、样式与交互;

调用 myChart.setOption(option) 渲染图表。

  1. 前后端数据交互逻辑

后端返回逗号分隔的字符串(如日期、数值列表),前端通过 split(',') 转换为数组,直接赋值给 option.xAxis.data 和 option.series[0].data,实现图表数据动态渲染。

二、核心业务统计场景实现

  1. 营业额统计

(1)需求与设计

统计指定时间区间内的每日营业额,以折线图展示趋势。营业额定义为 ** 已完成订单(状态为 COMPLETED)** 的金额总和。

(2)关键技术点

时间范围处理:使用 LocalDateTime.of(LocalDate, LocalTime.MIN/MAX) 生成当天的起始(00:00:00)与结束(23:59:59.999999999)时间,确保查询覆盖完整一天;

MyBatis 多条件查询:通过 Map 封装 beginTime、endTime、status 参数,在 XML 中使用 #{key} 直接引用 Map 键值,实现灵活的条件筛选;

数据聚合:SQL 中使用 SUM(amount) 计算每日营业额,GROUP BY DATE(order_time) 按日期分组;

数据格式转换:将 List<LocalDate>、List<Double> 转换为逗号分隔字符串,适配前端 ECharts 格式。

  1. 用户统计

(1)需求与设计

统计指定时间区间内的每日总用户数与新增用户数,以折线图展示用户增长趋势。总用户数为截止当日的累计用户数,新增用户数为当日注册用户数。

(2)关键技术点

用户状态区分:通过 create_time 筛选新增用户,通过 COUNT(id) 统计总用户数;

Stream 流处理:使用 stream().map() 提取用户统计结果中的日期、总用户数、新增用户数,转换为列表后拼接为字符串;

VO 封装:通过 UserReportVO 封装返回数据,使用建造者模式(Builder Pattern)简化对象创建,避免繁琐的 setter 调用。

  1. 订单统计

(1)需求与设计

统计指定时间区间内的每日订单总数与有效订单数,以柱状图展示订单分布。有效订单定义为已完成或已取消的订单。

(2)关键技术点

订单状态筛选:在 SQL 中通过 status IN (已完成状态, 已取消状态) 筛选有效订单;

分组统计:按日期分组,分别统计订单总数与有效订单数;

数据对齐:确保每日的总订单数与有效订单数一一对应,避免数据错位。

  1. 销量排名统计

(1)需求与设计

统计指定时间区间内的销量 Top10 商品,以柱状图展示商品销量对比。

(2)关键技术点

TopN 查询:SQL 中使用 ORDER BY number DESC LIMIT 10 获取销量前 10 的商品;

DTO 数据传输:通过 GoodsSalesDTO 封装商品名称与销量,避免直接暴露数据库实体;

Stream 流提取:使用 stream().map(GoodsSalesDTO::getName) 提取商品名称列表,stream().map(GoodsSalesDTO::getNumber) 提取销量列表;

字符串拼接:通过 StringUtils.join(列表, ",") 将列表转换为逗号分隔字符串,封装到 SalesTop10ReportVO 返回给前端。

三、核心技术原理与工具

  1. Java 8 时间 API

LocalDate:表示日期(如 2026-03-12);

LocalTime:表示时间(如 12:30:00),MIN 代表 00:00:00,MAX 代表 23:59:59.999999999;

LocalDateTime:表示日期时间(如 2026-03-12T12:30:00),通过 of() 方法组合日期与时间。

  1. Stream 流处理

核心作用:简化集合操作,实现「提取 → 转换 → 收集」的流水线处理;

常用方法:map()(元素映射)、collect(Collectors.toList())(收集为列表);

优势:代码简洁、可读性高,避免传统 for 循环的冗余代码。

  1. MyBatis 参数传递

Map 传参:灵活传递多条件参数,XML 中通过 #{key} 直接引用 Map 键值,无需额外配置;

DTO/VO 传参:结构化传递数据,适合固定参数场景,可读性更高;

@Param 注解:多参数场景下显式指定参数名称,避免参数绑定歧义。

  1. 建造者模式(Builder Pattern)

核心作用:简化对象创建,避免大量 setter 方法调用;

实现方式:通过 builder() 初始化构建器,链式调用属性设置方法,最后通过 build() 生成完整对象;

优势:代码优雅、可读性强,适合多属性对象的创建。

  1. StringUtils 工具类

核心方法:join(集合, 分隔符),将集合元素拼接为指定分隔符的字符串;

应用场景:将后端列表数据转换为前端图表所需的逗号分隔字符串,简化前后端数据交互。

四、业务流程总结

所有统计场景均遵循统一的开发流程:

需求分析:明确统计维度(时间、状态、对象)与展示形式(图表类型);

数据库查询:编写 SQL 实现数据聚合与筛选,通过 MyBatis Mapper 接口调用;

数据处理:使用 Stream 流提取目标数据,转换为列表后拼接为字符串;

结果封装:通过 VO 对象封装返回数据,使用建造者模式简化对象创建;

前端展示:接收后端字符串数据,转换为数组后配置 ECharts 选项,渲染图表。

五、核心价值与拓展

本次课程不仅实现了四个核心业务统计场景,更串联了 Spring Boot、MyBatis、Java 8 新特性与前端可视化的核心技术,形成了完整的「后端数据处理 + 前端可视化」技术栈。通过本次学习,能够快速解决企业级应用中的数据统计与可视化需求,同时为后续微服务架构下的分布式统计、实时数据可视化等复杂场景打下基础。

相关推荐
weixin199701080161 小时前
搜好货商品详情页前端性能优化实战
java·前端·python
LaughingZhu2 小时前
Product Hunt 每日热榜 | 2026-03-12
大数据·数据库·人工智能·经验分享·搜索引擎
XiYang-DING2 小时前
【Java SE】Java代码块详解
java·开发语言·python
白云如幻2 小时前
【JDBC】面向对象的思路编写JDBC程序
java·数据库
摇滚侠2 小时前
Java SpringBoot 项目,项目启动后执行的方法,有哪些方式实现
java·开发语言·spring boot
艾莉丝努力练剑2 小时前
【Linux进程间通信:共享内存】为什么共享内存的 key 值由用户设置
java·linux·运维·服务器·开发语言·数据库·mysql
星辰_mya2 小时前
并发容器全家桶:选择正确的“交通工具”
java·开发语言·面试
w1225h2 小时前
Tomcat10下载安装教程
java
NikoAI编程2 小时前
AI实战第一课:从项目配置到功能开发的完整流程
java·ai编程