1. 项目背景与核心需求
2023年初春,我在指导老师的建议下开始构思毕业设计选题。当时全球公共卫生事件频发,各类疫情数据分散在各个平台,公众获取权威信息存在困难。这让我萌生了开发一个整合性疫情数据管理系统的想法——通过技术手段解决信息碎片化问题。
这个系统的核心诉求非常明确:需要实时聚合全球疫情关键指标(感染数、治愈数、死亡数),并以可视化形式直观展示变化趋势。作为计算机专业的学生,我选择用最熟悉的Java技术栈来实现,采用经典的SSM框架组合(Spring+SpringMVC+MyBatis)。这个选择主要基于三点考量:首先,SSM框架在高校教学中普及度高,资料丰富;其次,MyBatis对复杂SQL查询的支持能很好地满足数据统计需求;最后,Spring的生态完整,方便集成各类可视化组件。
2. 技术架构设计解析
2.1 整体架构设计
系统采用标准的B/S三层架构:
- 前端:Vue.js + ECharts
- 后端:SpringBoot 2.7 + MyBatis-Plus
- 数据库:MySQL 5.7
选择Vue.js而非纯jQuery主要考虑到两点:一是数据绑定机制可以简化图表更新逻辑,二是组件化开发便于功能复用。实测证明,在疫情数据频繁更新的场景下,Vue的响应式特性确实大幅减少了手动DOM操作的工作量。
2.2 关键技术选型
数据可视化方案对比:
| 方案 | 优点 | 缺点 | 最终选择 |
|---|---|---|---|
| ECharts | 中文文档完善,社区活跃 | 3D图表支持较弱 | ✓ |
| Highcharts | 商业项目验证成熟 | 免费版有水印 | ✗ |
| Chart.js | 轻量级 | 复杂图表支持有限 | ✗ |
选择ECharts的核心原因是其强大的时间轴功能和地图组件,非常适合展示疫情时空分布特征。在实现省级粒度数据展示时,通过引入自定义地图JSON文件,完美解决了国内行政区划展示需求。
3. 核心功能实现细节
3.1 数据采集模块
采用多线程爬虫方案获取权威数据源:
java复制public class DataCrawler {
private static final ExecutorService pool = Executors.newFixedThreadPool(3);
public void fetchData() {
CompletableFuture.runAsync(() -> {
// 对接国家卫健委API
HttpClient.execute(API_ENDPOINT);
}, pool);
// 其他数据源采集...
}
}
关键点:
- 使用HttpClient连接池管理网络请求
- 配置请求重试机制(3次指数退避)
- 数据校验采用正则表达式+阈值检查双重验证
3.2 数据库设计优化
主要表结构设计:
sql复制CREATE TABLE `epidemic_data` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`region_code` varchar(6) COLLATE utf8mb4_bin NOT NULL COMMENT '行政区划代码',
`confirmed` int(11) NOT NULL DEFAULT '0' COMMENT '累计确诊',
`cured` int(11) NOT NULL DEFAULT '0' COMMENT '累计治愈',
`death` int(11) NOT NULL DEFAULT '0' COMMENT '累计死亡',
`update_time` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_region_time` (`region_code`,`update_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
性能优化措施:
- 采用组合索引加速时间范围查询
- 使用Tinyint替代Boolean节省存储空间
- 对历史数据按月分表(table_202301)
3.3 缓存策略实现
采用多级缓存架构:
- 热点数据:Redis缓存(TTL 5分钟)
- 历史数据:本地Caffeine缓存(最大10000条)
- 元数据:Ehcache集群共享
Spring缓存配置示例:
java复制@CacheConfig(cacheNames = "epidemic")
@Service
public class DataServiceImpl {
@Cacheable(key = "#region+':'+#date.format('yyyyMMdd')")
public EpidemicVO getDailyData(String region, LocalDate date) {
// 数据库查询逻辑
}
}
4. 典型问题与解决方案
4.1 数据一致性问题
现象:
后台管理端和用户端展示的数据存在延迟
排查过程:
- 检查MySQL主从同步状态(正常)
- 验证Redis过期策略(配置正确)
- 发现前端缓存未及时清除
解决方案:
- 引入版本号机制,数据更新时生成全局version
- 前端请求携带lastVersion,服务端比较后决定是否返回新数据
- 增加WebSocket推送通知机制
4.2 高并发场景优化
压力测试发现当QPS>500时,数据库连接池很快耗尽。通过以下措施提升性能:
- 连接池配置优化:
properties复制spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=30000
- 引入二级缓存:
java复制@Caching(
cacheable = @Cacheable(value = "daily", key = "#root.methodName"),
put = @CachePut(value = "weekly", key = "#root.methodName")
)
public ReportVO generateReport() {
// 报表生成逻辑
}
- 异步化处理:
- 使用@Async注解处理非实时需求
- 复杂统计任务移交RabbitMQ消息队列
5. 可视化实现技巧
5.1 ECharts高级用法
实现动态疫情地图的关键代码:
javascript复制option = {
timeline: {
data: ['2023-01','2023-02'...],
autoPlay: true
},
baseOption: {
series: [{
type: 'map',
map: 'china',
roam: true
}]
},
options: [
{ series: [{data: janData}] },
{ series: [{data: febData}] }
]
};
效果增强技巧:
- 添加渐变色提升视觉层次
- 使用SVG渲染保证缩放清晰度
- 移动端适配采用rem单位
5.2 移动端适配方案
通过媒体查询实现响应式布局:
css复制@media (max-width: 768px) {
.chart-container {
width: 100vw;
height: 60vh;
}
.data-table {
font-size: 0.8rem;
}
}
配合Vue的响应式特性,在窗口尺寸变化时动态调整ECharts实例:
javascript复制window.addEventListener('resize', () => {
this.chart.resize();
});
6. 项目部署实践
6.1 生产环境配置
推荐服务器配置:
- CPU:4核以上
- 内存:8GB+
- 磁盘:SSD 100GB+
Nginx关键配置:
nginx复制location /api {
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
}
location / {
root /var/www/html;
try_files $uri $uri/ /index.html;
}
6.2 监控方案
- Spring Boot Actuator暴露健康检查端点
- Prometheus + Grafana监控JVM指标
- ELK日志收集系统
关键监控指标:
- 接口响应时间P99 < 500ms
- JVM内存使用率 < 70%
- 数据库连接池活跃数
7. 开发心得与建议
-
技术选型教训:
最初考虑使用MongoDB存储非结构化数据,但后来发现疫情数据的强一致性要求更适合关系型数据库。建议类似项目优先考虑MySQL,JSON类型字段已能满足灵活存储需求。 -
性能优化经验:
在实现省级数据下钻查询时,发现直接使用JOIN查询性能极差。最终解决方案是:
- 预先计算好各级汇总数据
- 使用空间换时间策略
- 建立物化视图定期刷新
- 给后来者的建议:
- 尽早建立自动化测试套件(特别是数据校验部分)
- 采用Swagger规范API文档
- 容器化部署(Docker Compose)能大幅降低环境配置成本
- 前端使用Web Worker处理大数据量图表渲染
这个项目让我深刻体会到,一个看似简单的数据展示系统,背后需要考虑的架构细节如此之多。特别是在数据准确性和实时性要求高的场景下,每个技术决策都需要反复权衡。最终系统实现了秒级数据更新延迟,支持500+并发用户稳定访问,圆满达到了毕业设计的要求。