ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Java后端+ECharts:疫情数据可视化大屏系统实战全解析

Java后端+ECharts:疫情数据可视化大屏系统实战全解析 简介这是一套基于Java与ECharts构建的疫情数据可视化分析系统源码主要面向具有一定编程基础、希望深入掌握数据采集与可视化展示流程的开发者。项目采用Spring Boot框架搭建后端服务配合MyBatis访问MySQL数据库同时利用爬虫定时获取公开疫情数据再通过ECharts以折线图、柱状图、地图等多种形式直观呈现累计确诊、治愈、死亡等核心指标。整个资源包共包含一百零六个文件包括二十八个Java后端类、十三个JavaScript交互脚本、十三份XML配置及MyBatis映射文件、十份CSS样式表、八份properties系统配置以及建库SQL脚本、项目说明文档和启动命令等压缩后整体大小约十兆字节。此外包内还附带授权文件、图标资源和若干示例图片方便开发者快速还原运行环境并理解项目结构。这套系统已有1275人学习浏览无论是用于课程设计、毕业设计还是个人技能提升都可以提供完整的可运行参考帮助读者从数据抓取、持久化存储到前端图表渲染一脉相承地完成整套系统。1. Java 疫情分析系统到底在做什么ECharts 这个库才是灵魂如果你在求职简历上写“基于 Java 的疫情数据可视化系统”面试官大概率会追问一句“图表是你自己画的还是用 ECharts 套的”诚实答案是Java 只负责当数据搬运工真正让看板亮眼的是百度开源的 ECharts 这个 JavaScript 图表库。这个压缩包标题里把“Java”“ECharts”“数据可视化”三个词焊在一起本质上就是一个经典的全栈演示项目后端用 Java 和数据库管理疫情数据前端用 ECharts 渲染折线图、柱状图、饼图和地图最后拼成一个能交互的疫情监控大屏。它能解决什么问题对正在学 Java 后端的人来说这是少有的能把 SSM/Spring Boot、MySQL、JSON、Ajax、前端图表一条线串起来的课题对需要交课程设计、毕设或企业内训 demo 的人来说这是一份能直接跑起来、能截图写进文档的完整源码。它适合的人群很明确Java 基础语法过关、但没做过前后端联通项目的人以及被导师要求“做个可视化”却不知道从哪下手的应届生。整个系统不复杂但技术链完整正好用来建立“后端怎么把数据送到前端”的完整心智。源码包不管来自哪个作者这类项目的骨架高度一致下面的展开就是按这份骨架来的。2. 拆开源码包从目录结构看懂这套系统的数据流拿到“Java基于ECharts的数据可视化疫情分析系统源码.zip”先别急着点 IDE 运行。第一件事是把压缩包解开对着目录结构把数据流画出来。绝大多数同类项目都是标准 Maven 工程目录长得差不多但每个文件夹承担什么职责决定了你后面改功能时该动哪。2.1 目录结构里藏着三层架构Controller 只管转 JSONECharts 只管画图常见做法是把项目分为三块src/main/java放后端代码src/main/resources放配置文件和静态资源src/main/webapp放前端页面。Java 代码里一般能看到controller、service、mapper、entity四个包对应经典三层架构。举个例子一个典型的包名是com.epidemic.controller里面是EpidemicDataController之类的类service里写业务逻辑mapper如果用 MyBatis或dao如果用 JdbcTemplate写数据库访问。前端呢webapp/static下通常放着js/echarts.min.js、js/jquery.min.js、css/style.css和几个 HTML 页面比如index.html、province.html、trend.html。注意ECharts 是纯前端库它不需要 Java 参与——Java 后端只负责把数据库里的疫情数据查出来转成 JSON 字符串通过 HTTP 接口返回HTML 页面里的 JavaScript 拿到 JSON 后用 ECharts 渲染。这套结构最值得学习的就是“后端与前端完全解耦”Controller 里返回ResponseBody或RestController的 JSON 结果不掺任何图表代码ECharts 的 option 全部写在 HTML 或 JS 文件里。这就是为什么项目标题敢把“Java”“ECharts”并列——两者通过 JSON 对话。看源码时按这个顺序读最省力先看pom.xml确认用了哪些依赖Spring Boot 还是 SSM、MySQL 驱动还是 MyBatis再看application.properties或db.properties里数据库连接配置然后打开 Controller看它暴露了哪些 REST 接口最后打开前端 HTML找到$.ajax或fetch请求的 URL跟 Controller 里的RequestMapping对上。这一圈走完你就能说清楚用户打开页面后发生了什么页面加载 → JS 发异步请求 → Java 查库 → 返回 JSON → ECharts 根据 JSON 画图。2.2 ECharts 的引入方式压缩包里的 echarts.min.js 决定你能否离线运行这类源码包一般会把 echarts.min.js 直接放在js目录下而不是让你从 CDN 引用。原因很简单课程设计要离线演示答辩现场的教室网络经常连不上外网。所以拿到包后先检查static/js/下有没有这个文件如果没有去官网下载对应版本放进去。为什么强调版本ECharts 5 和 ECharts 4 在 API 上有细微差别比如 5 系列对地图的引入方式变了、主题注册方式不同如果源码是 4 写的你强行换 5 可能会报Cannot read property registerMap of undefined之类的错。常见做法是压缩包里自带哪个版本就用哪个版本。如果你需要手动引入用 unpkg 的 esm 版或直接下载完整版!-- 放在 HTML 的 head 或 body 末尾必须优先于你自己的 echarts 初始化脚本 -- script srcjs/echarts.min.js/script这行代码的讲究在于ECharts 会挂载一个全局echarts对象你的业务脚本必须在它之后加载否则调用echarts.init时会报echarts is not defined。另外如果页面里同时用了 jQuery 和 ECharts两者互不依赖各自引入即可不需要考虑冲突。源码包的 HTML 里通常会同时出现这两个script标签先用 jQuery 的$.getJSON请求数据再用 ECharts 渲染。2.3 数据库表设计是这套系统的地基日期、省份、确诊、疑似、治愈、死亡疫情分析系统既然叫“分析”就离不开时间维度和地域维度。标准表结构是一张主表epidemic_daily字段大致为id主键、province省份、date日期、confirmed累计确诊、suspected疑似、cured治愈、dead死亡再加一个createtime用于记录入库时间。部分项目会把全球数据、国内数据拆成两张表或者把“新增确诊”单独做一列方便画每日新增曲线。源码包里一般会附sql目录或db目录里面有建表语句和导入数据这是整个系统唯一的“数据源”。我用 MySQL 5.7 时的一般建表语句长这样CREATE TABLE epidemic_daily ( id INT PRIMARY KEY AUTO_INCREMENT, province VARCHAR(50) NOT NULL, stat_date DATE NOT NULL, confirmed INT DEFAULT 0, suspected INT DEFAULT 0, cured INT DEFAULT 0, dead INT DEFAULT 0, update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_province_date (province, stat_date) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;注意UNIQUE KEY uk_province_date (province, stat_date)这一行。它保证了同一省份同一天只能有一条记录避免因为重复跑数据脚本导致图上的数字翻倍。这是很容易被忽略的细节如果源数据是 CSV 导入你可能重复执行了两次 INSERT折线图上的累计确诊在某个日期突然跳变不是数据错了是行重复了。加上唯一索引后配合INSERT ... ON DUPLICATE KEY UPDATE可以把幂等性补上INSERT INTO epidemic_daily (province, stat_date, confirmed, suspected, cured, dead) VALUES (湖北, 2024-03-01, 68100, 0, 63600, 3200) ON DUPLICATE KEY UPDATE confirmed VALUES(confirmed), cured VALUES(cured);除了主表部分源码还会配一张province_info表存省份代码、拼音、坐标范围用于 ECharts 地图。如果后端返回的 JSON 里需要“省份名”和“数值”两个字段Controller 大概率是SELECT province, confirmed FROM epidemic_daily WHERE stat_datexxx。所以读 SQL 时你会发现这套系统的后端逻辑比想象中简单——本质就是几张表按日期、省份分组聚合。2.4 pom.xml 里的依赖组合Spring Boot 2 MyBatis MySQL 是主流答案源码包用 Maven 管理依赖时pom.xml里最显眼的三个坐标是spring-boot-starter-web、mybatis-spring-boot-starter、mysql-connector-java。如果是 Spring Boot 2.x还会带spring-boot-starter-jdbc或spring-boot-starter-data-jpa。MyBatis 在这类系统里很常见因为疫情数据的查询多为固定的按日期/省份查询写 SQL 比 JPA 的自动 CRUD 更直观。少数项目会用 JdbcTemplate代码更少适合表结构极简的情况。一个典型的pom.xml片段parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version /parent dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.2/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency /dependencies这里要留意的版本坑Spring Boot 3.x 要求 Java 17 起步而很多课程设计的源码是基于 Java 8 写的。如果你本机是 JDK 8硬跑 Spring Boot 3 的项目会在编译期报错。拿到源码先看pom.xml的 parent 版本再对照自己java -version的结果。ECharts 版本和 Java 版本是两套独立的兼容体系别混淆。如果源码是 Spring Boot 2.7JDK 8 完全够用如果是 Spring Boot 3那必须用 JDK 17。3. 把源码跑起来的完整步骤从数据库初始化到浏览器出现图表动手运行之前你要意识到这套系统不是一个“一键启动”的玩具。它依赖 MySQL、依赖初始化数据、依赖后端端口和前端静态资源的路径。每一步的顺序错了都会看到不同的报错。我一般按“导库 → 改配置 → 启动后端 → 开前端页面”的顺序走。3.1 第一步导入 SQL 并核对数据量别让图表空白源码包里通常有一个epidemic.sql或init.sql。打开它先扫一眼有没有CREATE DATABASE表名是什么。如果脚本里没有建库语句你要先手动建库CREATE DATABASE epidemic CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE epidemic; SOURCE /your/path/epidemic.sql;导完之后别急着关命令行。执行几条 SELECT 验证数据真实存在SELECT COUNT(*) FROM epidemic_daily; SELECT stat_date, COUNT(DISTINCT province) FROM epidemic_daily GROUP BY stat_date;这两条查询是后续排查的照妖镜。如果COUNT(*)是 0图表一定空白问题在数据导入而非前端代码如果按日期分组后每个日期的省份数量不同那后端查“最新一天”数据时可能漏掉某些省份。很多源码里的 SQL 文件是从真实疫情接口抓的数据日期范围集中在 2020 年 1 月至 6 月这没关系图表展示的是趋势不是实时数据。不过如果你想让系统看起来更新需要自己造一批 2024 或 2025 年的模拟数据注意把所有涉及日期的查询条件一起改掉否则图上会出现“最新日期”和“旧日期”断层的难堪局面。3.2 第二步修改 application.properties 的数据库连接四项这一步是新手翻车率最高的地方。源码作者用的是自己的账号密码你拿过来必须改成你的本地环境。改错任何一个字符后端启动时不报错但一请求接口就抛Access denied或者Unknown database。spring.datasource.urljdbc:mysql://localhost:3306/epidemic?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai spring.datasource.usernameroot spring.datasource.password123456 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver解释一下characterEncodingutf8保证从数据库查出来的中文传到前端不乱码serverTimezoneAsia/Shanghai是 MySQL 8 的强制要求不写会报The server time zone value的错。如果你的 MySQL 是 5.7可以把useSSLfalse加上但不是必须。username和password改成你本机 MySQL 的账号——如果你不记得密码用mysql -u root -p试一下能进就是对的。还需要看mybatis.mapper-locations配置。如果源码把 Mapper XML 放在src/main/resources/mapper下但配置里写的是classpath:mapper/*.xml且路径对不上启动时会报Invalid bound statement (not found)。这种玄学问题最磨人先检查这个配置。3.3 第三步启动 Spring Boot 后先测接口再开页面在 IDE 里直接运行带SpringBootApplication的主类或者用 Maven 命令启动mvn spring-boot:run启动成功的标志是Tomcat started on port(s): 8080。这时先别打开页面先用浏览器或 curl 测一个接口curl http://localhost:8080/api/epidemic/trend如果返回一段 JSON里面有日期和数值字段说明后端链路是通的。如果返回 404检查 Controller 的RequestMapping和前端 AJAX 的 URL 是否一致如果返回 500看后台日志——最常见的错误是 SQL 查到不存在的列比如前端要confirmedSQL 里写成了confirm。确认接口正常后打开http://localhost:8080/index.html。如果页面空白按 F12 打开开发者工具看 Console报404说明静态资源路径不对报echarts is not defined说明 echarts.min.js 没加载成功。这两种情况分别检查spring.web.resources.static-locations配置和 HTML 里script的 src 路径。3.4 第四步ECharts 图表只渲染半截或空白的定位方法图表出来了但数据是空的这是最常见也最让人抓狂的现象因为页面不报错。定位路径只有一条打开 F12 → Network → XHR刷新页面找一个名为trend或province的请求看看 Response 是不是[]或{code:500}。如果是[]说明 SQL 查询结果为空问题在数据库或 SQL 条件如果是正常数据问题在 JS 代码对字段名的处理。举个例子后端返回的 JSON 字段叫stat_date前端 JS 写的却是date// 错误写法字段名对不上图表拿不到数据 trendData.forEach(function(item) { dates.push(item.date); values.push(item.confirmed); }); // 正确写法按后端返回的实际字段名取 dates.push(item.stat_date);这种坑就是“后端数据没问题、前端也不报错但图表就是空”的经典来源。特别是用 MyBatis 时如果application.properties里没开启map-underscore-to-camel-casetrue数据库字段stat_date映射到实体类时可能是stat_date而不是statDate你直接用item.statDate取就是 undefined。最稳妥的办法是先console.log(JSON.stringify(data))把后端返回的原始 JSON 打印出来再照着字段名写 JS。这套血泪经验适用于所有 Java ECharts 项目不只是疫情系统。4. 最快能落地的三个 ECharts 图表拆解配置与 Java 数据交互系统跑通之后你要理解图表本身是怎么组织数据的。ECharts 的配置全在一个 JavaScript 对象option里Java 后端只需要提供xAxis.data和series.data。三种图表覆盖了疫情分析最常见的需求全国趋势看折线各省对比看柱状结构占比看饼图。4.1 折线图累计确诊与治愈的趋势对照折线图放在首页最合适因为它能一眼看出疫情的爆发期、平台期、消退期。ECharts 的折线图type: line配上smooth: true就会变成光滑曲线视觉上更专业。var trendChart echarts.init(document.getElementById(trendChart)); var option { tooltip: { trigger: axis }, legend: { data: [累计确诊, 治愈] }, xAxis: { type: category, data: dates }, yAxis: { type: value, name: 人数 }, series: [ { name: 累计确诊, type: line, smooth: true, data: confirmedData }, { name: 治愈, type: line, smooth: true, data: curedData } ] }; trendChart.setOption(option);这段代码里dates、confirmedData、curedData三个数组来自异步请求的回调。Java 后端对应接口的写法是GetMapping(/api/epidemic/trend) public MapString, Object trend() { ListMapString, Object list epidemicService.selectTrend(); MapString, Object result new HashMap(); // 把 list 里的日期、确诊、治愈分别抽出来放进数组 ListString dates new ArrayList(); ListInteger confirmed new ArrayList(); for (MapString, Object row : list) { dates.add(row.get(stat_date).toString()); confirmed.add((Integer) row.get(confirmed)); } result.put(dates, dates); result.put(confirmed, confirmed); return result; }这里有个参数细节如果stat_date是java.sql.Date直接 toString 会得到2024-03-01ECharts 的 category 轴正好接受字符串日期。但如果后面要展示“3月1日”这种短格式需要在前端做一次格式化别在后端改格式否则排序会乱。后端返回 JSON 时Map里有Integer和String混用Jackson 序列化后是{dates: [2024-03-01], confirmed: [68100]}前端拿到的数据结构必须和你 JS 里写的循环对应上。4.2 柱状图各省份累计确诊 Top10 的排序逻辑柱状图常用于横向对比比如“哪些省份最严重”。这类图表要求 SQL 里有排序和分组SELECT province, confirmed FROM epidemic_daily WHERE stat_date (SELECT MAX(stat_date) FROM epidemic_daily) ORDER BY confirmed DESC LIMIT 10;这里嵌套子查询取“最新一天”的数据避免把历史每一天的都查出来导致柱状图难以阅读。前端配置很简单barOption { xAxis: { type: value }, // 横向柱状图把 value 放在 xAxis yAxis: { type: category, data: provinces, // 省份名 inverse: true // 让最多的省份显示在最上面 }, series: [{ type: bar, data: numbers, label: { show: true, position: right } }] }; barChart.setOption(barOption);inverse: true是一个易被忽略的参数。SQL 里ORDER BY confirmed DESC查出来的第一条是最大值但 ECharts 的 category 轴默认从下往上排列第一个数据会出现在底部。如果不加inverse: true你看到的图会变成“最大的在下面”完全反直觉。想保持 SQL 不用改就在前端加这一行想用主动思维控制就在 SQL 里ORDER BY confirmed ASC让第一条是最小值ECharts 从下往上画视觉上同样是最大的在顶部。两种做法等价但团队协作时要统一否则换个人维护就乱了。如果你想把柱状图顶部显示具体数值就开label.show true位置选top或right。很多热搜词里提到的“y轴的标签如何在每个柱子上面显示”就是问这个——label.position设成right对应横向柱设成top对应纵向柱没有第三种玄学。4.3 饼图与地图占比展示和疫情热力分布的边界情况饼图适合展示“累计确诊的省份占比”比如前五名省份占全国多少。ECharts 饼图没有 x 轴和 y 轴数据格式是{name: 湖北, value: 68100}的结构后端返回的就是ListMap前端在 AJAX 回调里原样塞进series.data即可。pieOption { tooltip: { trigger: item, formatter: {b}: {c} ({d}%) }, series: [{ type: pie, radius: [40%, 70%], // 环形饼图 data: pieData }] }; pieChart.setOption(pieOption);这里要提一句大数据量的坑如果省份有 30 多个饼图会变成“针尖图”小省份的占比扇形几乎看不清。常见做法是只取 Top5其余归为“其他”这个逻辑可以放在 SQL 里用UNION写也可以放在 Java 代码里算。更省事的做法是改成使用 ECharts 的地图——但地图需要额外的中国地图 GeoJSON 文件和echarts.registerMap注册源码包不一定自带需要联网下载。如果没有地图文件就别硬做地图用柱状图替代效果一样。饼图中间加文字也是高频需求很多热搜词提“echarts pie 中间的字”。这个不是饼图的 title而是graphic元素或title组件定位在饼图中心title: { text: 累计确诊, subtext: String(total), left: center, top: 40% }注意top: 40%是个经验值因为环形图中心区域高度受radius影响不同屏幕比例下文字位置会偏。最稳妥的方案是用graphic配合计算出的中心坐标但新手阶段用 title 居中已经够看不必过度优化。4.4 时间轴联动把日期滑块变成动态大屏的加分项疫情分析有个特殊需求随时间变化看趋势。折线图天然支持时间轴但如果你想让首页的地图或柱状图跟随日期切换需要在 ECharts 里加timeline组件或者在页面放一个input typerange每次滑动触发一次 AJAX 请求。我一般建议后端接口设计成带日期参数GetMapping(/api/epidemic/province) public ListMapString, Object province(RequestParam(date) String date) { return epidemicService.selectByDate(date); }前端用 jQuery 绑定滑块事件$(#dateSlider).on(input, function() { var date $(this).val(); $.getJSON(/api/epidemic/province, {date: date}, function(res) { myChart.setOption({ series: [{ data: res }] }); }); });这样做的好处是后端无状态前端控制交互逻辑简单。坏处是每次滑动都打一个 HTTP 请求如果数据量大或网络慢会有明显的延迟。课程设计演示时可以预先把所有日期的数据一次性加载到前端用timeline滑动切换但那样代码复杂度会上升容易在答辩现场翻车。优先采用滑块请求的方案稳定优先这就是实战和炫技的区别。5. ECharts 与 Java 数据交互的五个避坑记录现象、原因、解决把上面的链路走通不难难在遇到问题时能快速定位。这部分记录我实际调试同类项目时踩过的五个高频坑每一条都可以在本地复现希望你能直接记住而不是到时候再去翻黄山文档。坑一图表显示“NAN”或控制台报ECharts is not defined页面白屏。现象是打开 HTML 后没有任何图表F12 报Uncaught ReferenceError: echarts is not defined。原因几乎都是echarts.min.js这个 script 标签放在了初始化脚本的后面或者路径写错返回 404。解决方法是把script srcjs/echarts.min.js放到所有业务 JS 之前并确认浏览器 Network 里这个文件的状态码是 200。顺带检查一下如果是用 Thymeleaf 模板引擎src路径要写th:src{/js/echarts.min.js}否则会多出一层项目名前缀导致 404。坑二折线图数据点全部为 0但数据库里有数。现象是图能渲染出来曲线趴在 0 的位置。原因定位在后端 SQL 或 Java 类型转换比如 MySQL 里confirmed字段是BIGINT实体类却用Integer接收超出范围后会被转成 0 或抛出异常更常见的是 SQL 里查的是sum(confirmed)如果该日期没有数据聚合函数返回nullJava 拿到null放进int数组变成 0。解决方法是先curl接口看 JSON 里对应字段是不是null是 null 的话在 SQL 中用IFNULL(SUM(confirmed), 0)兜底或者在 Java 中统一用Integer并判空。坑三柱状图的数据顺序和图例对不上。现象是图里第一个 Bar 对应的是 SQL 里的最后一行。原因就是前面提过的 category 轴方向问题解决方法是加inverse: true或者在后端把 SQL 改成ORDER BY confirmed ASC。如果做到这里还是对不上排查一下 SQL 里是否有GROUP BY province ORDER BY confirmed DESC LIMIT 10同时存在LIMIT和ORDER BY的执行顺序跟你想的可能不一致。坑四饼图数据全部挤在一起且每个饼块颜色都接近。现象是饼图只有两三种颜色大户省份和小户省份难以分辨。原因是 ECharts 默认调色板只有 8 种颜色超过 8 类数据会自动循环调色如果数据有 30 类颜色就重复了。解决方案有两种一是用color属性传入一个更长的调色板数组二是在数据层面做 Top10 “其他”合并后者对疫情大屏更有意义——没人关心第 20 名省份的精确占比。这里不需要写 Java 代码但在service层做合并比在前端做更合理因为后端返回的 JSON 就应该已经是“适合展示”的结构。坑五地图组件报registerMap is not defined。现象是用了type: map的 series 后就报错。原因是你没有引入中国地图的 GeoJSON 数据或者引用的版本与 ECharts 5 不再兼容。ECharts 5 之后地图数据需要单独下载china.js然后在 ECharts 之后引入script srcjs/china.js/script并在 JS 里执行echarts.registerMap(china, chinaJson)。如果源码包里只有一个 echarts.min.js、没有 china.js那就不要用地图图表换成柱状图或饼图别在答辩前才补地图数据。这些坑有一个共同的主线前后端的数据契约——JSON 的字段名、类型、顺序、null 值——是整套系统最脆弱的连接点。Java 后端写的每一个Map.put前端 JS 都会直接读取后端多一个空格、少一个下划线前端就是 undefined。所以调试时养成习惯先看 Network 里原始响应再写前端取值逻辑。6. 进阶验证手段把爬虫抓到的接口数据导入你的系统验证整条链路系统跑通、图表正常之后你是不是觉得“这就是个静态数据的展示器”下一个值得做的是把定时抓取的数据灌进去让你的系统变成“有源活水”。这个操作不需要改前端重点是写好 Java 的定时任务和 SQL 的幂等插入。最常见的进阶做法是使用 Spring 的Scheduled注解每天凌晨自动调用外部数据接口比如各省卫健委公开的 JSON API解析后写入epidemic_daily表Component public class EpidemicDataSyncTask { Autowired private EpidemicMapper epidMapper; Scheduled(cron 0 0 1 * * ?) public void sync() { // 1. 调用外部接口拿到 JSON 字符串 String json restTemplate.getForObject(https://example-api/province, String.class); // 2. 用 Jackson 解析成 ListProvinceData ListProvinceData list objectMapper.readValue(json, new TypeReference() {}); // 3. 逐条 upsert 到数据库 for (ProvinceData d : list) { epidMapper.upsert(d); } } }这段代码里的三个步骤每个都有讲究。第一步的 URL 是假造的真实场景要替换成目标接口的完整地址同时考虑接口返回的字段名和你的实体类是否一致第二步的TypeReference是为了把 JSON 数组反序列化成泛型 List第三步的upsert对应我们在第 2 章写的ON DUPLICATE KEY UPDATE保证同一天同一省份的数据只更新不新增。验证这个功能是否正常最直接的方法是改系统时间或手动触发一次 sync 方法然后对比数据库里的update_time字段。如果更新的行数为 0大概率是stat_date格式不一致比如外部接口返回2024/03/01而你的实体类字段是Date类型转换失败会抛异常并把整个任务拦停。所以建议在sync方法里逐条处理并捕获异常打印出是哪条数据出了问题不要因为一条脏数据让整个任务挂掉。写到这里我想起一个真实的教训我做类似系统时偷懒没加唯一索引数据同步脚本跑了三遍前端累计确诊曲线直接变成锯齿状还以为是 ECharts 渲染的问题最后查库才发现重复行占了三分之一。打那以后我养成了一个习惯——任何数据导入型功能第一件事就是给自然键日期省份加唯一索引。这个习惯花不了几分钟但能替你省下以后排查数据的无数个夜晚。如果你现在正打算照着这套思路做一个疫情分析大屏先把数据幂等性想清楚再动手写图表顺序别反。希望帮到你。本文还有配套的精品资源点击获取
返回列表