目录
[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)
[Day11-05 - 营业额统计_代码开发_2](#Day11-05 - 营业额统计_代码开发_2)
问题:给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)营业额统计通过查询"已完成"订单金额合计实现;3)用户统计通过StringUtils.join()方法处理数据;4)订单统计需注意时间段汇总;5)销量排名统计需关联查询订单表与订单详情表,并使用stream().map()转换数据格式。文档详细记录了各模块的需求分析、代码开发
Day11 数据统计与可视化核心知识点总结
本次课程围绕Apache ECharts 可视化与后端数据统计展开,通过营业额统计、用户统计、订单统计、销量排名统计四个核心业务场景,完整实现了「数据查询 → 格式转换 → 前端图表展示」的全流程,同时串联了 Spring Boot 与 MyBatis 的核心技术应用。
一、Apache ECharts 基础与入门
- 核心概念
Apache ECharts 是一款开源的 JavaScript 可视化库,用于快速构建折线图、柱状图、饼图等各类图表,适配 PC 与移动端,支持海量数据渲染与交互效果。
- 入门核心步骤
引入 ECharts CDN 或本地资源,在 HTML 中创建容器(<div>)并设置宽高;
初始化 ECharts 实例:let myChart = echarts.init(document.getElementById('容器ID'));
配置 option 对象,定义图表的 X 轴、Y 轴、系列数据、样式与交互;
调用 myChart.setOption(option) 渲染图表。
- 前后端数据交互逻辑
后端返回逗号分隔的字符串(如日期、数值列表),前端通过 split(',') 转换为数组,直接赋值给 option.xAxis.data 和 option.series[0].data,实现图表数据动态渲染。
二、核心业务统计场景实现
- 营业额统计
(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)需求与设计
统计指定时间区间内的每日总用户数与新增用户数,以折线图展示用户增长趋势。总用户数为截止当日的累计用户数,新增用户数为当日注册用户数。
(2)关键技术点
用户状态区分:通过 create_time 筛选新增用户,通过 COUNT(id) 统计总用户数;
Stream 流处理:使用 stream().map() 提取用户统计结果中的日期、总用户数、新增用户数,转换为列表后拼接为字符串;
VO 封装:通过 UserReportVO 封装返回数据,使用建造者模式(Builder Pattern)简化对象创建,避免繁琐的 setter 调用。
- 订单统计
(1)需求与设计
统计指定时间区间内的每日订单总数与有效订单数,以柱状图展示订单分布。有效订单定义为已完成或已取消的订单。
(2)关键技术点
订单状态筛选:在 SQL 中通过 status IN (已完成状态, 已取消状态) 筛选有效订单;
分组统计:按日期分组,分别统计订单总数与有效订单数;
数据对齐:确保每日的总订单数与有效订单数一一对应,避免数据错位。
- 销量排名统计
(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 返回给前端。
三、核心技术原理与工具
- 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() 方法组合日期与时间。
- Stream 流处理
核心作用:简化集合操作,实现「提取 → 转换 → 收集」的流水线处理;
常用方法:map()(元素映射)、collect(Collectors.toList())(收集为列表);
优势:代码简洁、可读性高,避免传统 for 循环的冗余代码。
- MyBatis 参数传递
Map 传参:灵活传递多条件参数,XML 中通过 #{key} 直接引用 Map 键值,无需额外配置;
DTO/VO 传参:结构化传递数据,适合固定参数场景,可读性更高;
@Param 注解:多参数场景下显式指定参数名称,避免参数绑定歧义。
- 建造者模式(Builder Pattern)
核心作用:简化对象创建,避免大量 setter 方法调用;
实现方式:通过 builder() 初始化构建器,链式调用属性设置方法,最后通过 build() 生成完整对象;
优势:代码优雅、可读性强,适合多属性对象的创建。
- StringUtils 工具类
核心方法:join(集合, 分隔符),将集合元素拼接为指定分隔符的字符串;
应用场景:将后端列表数据转换为前端图表所需的逗号分隔字符串,简化前后端数据交互。
四、业务流程总结
所有统计场景均遵循统一的开发流程:
需求分析:明确统计维度(时间、状态、对象)与展示形式(图表类型);
数据库查询:编写 SQL 实现数据聚合与筛选,通过 MyBatis Mapper 接口调用;
数据处理:使用 Stream 流提取目标数据,转换为列表后拼接为字符串;
结果封装:通过 VO 对象封装返回数据,使用建造者模式简化对象创建;
前端展示:接收后端字符串数据,转换为数组后配置 ECharts 选项,渲染图表。
五、核心价值与拓展
本次课程不仅实现了四个核心业务统计场景,更串联了 Spring Boot、MyBatis、Java 8 新特性与前端可视化的核心技术,形成了完整的「后端数据处理 + 前端可视化」技术栈。通过本次学习,能够快速解决企业级应用中的数据统计与可视化需求,同时为后续微服务架构下的分布式统计、实时数据可视化等复杂场景打下基础。









