
1. 疫情管理系统技术架构解析这套基于Java SpringBootVue3MyBatis的疫情管理系统采用了经典的三层架构设计前后端完全分离的开发模式。后端使用SpringBoot 2.7.x作为核心框架配合MyBatis 3.5.x实现数据持久层操作数据库选用MySQL 8.0社区版。前端则采用Vue3组合式API开发通过axios与后端进行RESTful API交互。技术选型上特别考虑了疫情管理场景的特殊需求SpringBoot的自动配置特性快速搭建微服务架构Vue3的Composition API更适合复杂业务逻辑组织MyBatis的灵活SQL编写能力应对多变的数据统计需求MySQL事务支持确保疫情数据操作的原子性实际开发中发现SpringBoot 2.7.x与Vue3的兼容性最好建议不要盲目追求最新版本。我们团队曾尝试SpringBoot 3.x但遇到了一些依赖冲突问题。2. 开发环境搭建与项目初始化2.1 后端工程配置使用IntelliJ IDEA创建SpringBoot项目时关键依赖选择dependencies !-- Web支持 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MyBatis整合 -- dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.2.2/version /dependency !-- MySQL驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- 其他必要依赖 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependenciesapplication.yml典型配置示例server: port: 8080 servlet: context-path: /api spring: datasource: url: jdbc:mysql://localhost:3306/epidemic?useSSLfalseserverTimezoneUTC username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true2.2 前端工程搭建使用Vite初始化Vue3项目npm create vitelatest epidemic-frontend --template vue核心依赖安装npm install axios vue-router4 pinia element-plusaxios全局配置示例src/utils/request.jsimport axios from axios const service axios.create({ baseURL: http://localhost:8080/api, timeout: 5000 }) // 请求拦截器 service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }) // 响应拦截器 service.interceptors.response.use( response { return response.data }, error { return Promise.reject(error) } ) export default service3. 核心功能模块实现3.1 疫情数据管理模块后端Controller示例使用MyBatis注解方式RestController RequestMapping(/epidemic) public class EpidemicDataController { Autowired private EpidemicDataMapper epidemicDataMapper; GetMapping(/list) public Result list(RequestParam MapString, Object params) { PageHelper.startPage(params); ListEpidemicData list epidemicDataMapper.selectByCondition(params); PageInfoEpidemicData pageInfo new PageInfo(list); return Result.success(pageInfo); } PostMapping(/add) public Result add(RequestBody EpidemicData data) { data.setCreateTime(new Date()); epidemicDataMapper.insertSelective(data); return Result.success(); } }对应的MyBatis Mapper XML配置select idselectByCondition resultMapBaseResultMap parameterTypemap SELECT * FROM epidemic_data where if testareaCode ! null AND area_code #{areaCode} /if if teststartDate ! null and endDate ! null AND record_date BETWEEN #{startDate} AND #{endDate} /if /where ORDER BY record_date DESC /select3.2 可视化大屏实现使用Vue3ECharts实现疫情数据可视化template div classdashboard-container el-row :gutter20 el-col :span12 div classchart-container div reftrendChart stylewidth:100%;height:400px;/div /div /el-col el-col :span12 div classchart-container div refdistributionChart stylewidth:100%;height:400px;/div /div /el-col /el-row /div /template script setup import { ref, onMounted } from vue import * as echarts from echarts import { getEpidemicTrend } from /api/epidemic const trendChart ref(null) const distributionChart ref(null) onMounted(async () { const res await getEpidemicTrend() initTrendChart(res.data) initDistributionChart(res.data) }) function initTrendChart(data) { const chart echarts.init(trendChart.value) const option { title: { text: 疫情趋势分析 }, tooltip: { trigger: axis }, legend: { data: [确诊, 疑似, 治愈, 死亡] }, xAxis: { type: category, data: data.dates }, yAxis: { type: value }, series: [ { name: 确诊, type: line, data: data.confirmed }, { name: 疑似, type: line, data: data.suspected }, { name: 治愈, type: line, data: data.cured }, { name: 死亡, type: line, data: data.death } ] } chart.setOption(option) } /script4. 数据库设计与优化4.1 核心表结构设计CREATE TABLE epidemic_data ( id bigint NOT NULL AUTO_INCREMENT, area_code varchar(20) NOT NULL COMMENT 地区编码, confirmed int DEFAULT 0 COMMENT 确诊人数, suspected int DEFAULT 0 COMMENT 疑似人数, cured int DEFAULT 0 COMMENT 治愈人数, death int DEFAULT 0 COMMENT 死亡人数, record_date date NOT NULL COMMENT 记录日期, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY idx_area_date (area_code,record_date) USING BTREE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci; CREATE TABLE user ( id bigint NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL, password varchar(100) NOT NULL, real_name varchar(50) DEFAULT NULL, phone varchar(20) DEFAULT NULL, role varchar(20) DEFAULT user COMMENT 角色admin/user, status tinyint DEFAULT 1 COMMENT 状态0-禁用 1-正常, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY idx_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci;4.2 查询性能优化实践索引优化为高频查询条件建立组合索引避免在索引列上使用函数或运算MyBatis二级缓存配置cache evictionLRU flushInterval60000 size512 readOnlytrue/分页查询优化PageHelper.startPage(pageNum, pageSize); ListEpidemicData list epidemicDataMapper.selectByCondition(params); PageInfoEpidemicData pageInfo new PageInfo(list);5. 系统安全与权限控制5.1 JWT认证实现SpringSecurity配置类示例Configuration EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers(/user/login).anonymous() .antMatchers(/epidemic/**).authenticated() .anyRequest().permitAll() .and() .addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); } Bean public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() { return new JwtAuthenticationTokenFilter(); } }JWT过滤器核心逻辑public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String token request.getHeader(Authorization); if (!StringUtils.hasText(token) || !token.startsWith(Bearer )) { chain.doFilter(request, response); return; } token token.substring(7); try { Claims claims Jwts.parser() .setSigningKey(your-secret-key) .parseClaimsJws(token) .getBody(); String username claims.getSubject(); UserDetails userDetails userDetailsService.loadUserByUsername(username); UsernamePasswordAuthenticationToken authentication new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); } catch (Exception e) { // token验证失败处理 } chain.doFilter(request, response); } }5.2 前端路由权限控制使用Vue Router的导航守卫实现router.beforeEach((to, from, next) { const token localStorage.getItem(token) const whiteList [/login] if (token) { if (to.path /login) { next({ path: / }) } else { const hasRoles store.getters.roles store.getters.roles.length 0 if (hasRoles) { next() } else { try { const { roles } await store.dispatch(user/getInfo) const accessRoutes await store.dispatch(permission/generateRoutes, roles) accessRoutes.forEach(route { router.addRoute(route) }) next({ ...to, replace: true }) } catch (error) { await store.dispatch(user/resetToken) next(/login?redirect${to.path}) } } } } else { if (whiteList.includes(to.path)) { next() } else { next(/login?redirect${to.path}) } } })6. 项目部署与运维6.1 后端打包与部署使用SpringBoot Maven插件打包mvn clean package -DskipTestsDockerfile示例FROM openjdk:11-jre-slim VOLUME /tmp COPY target/epidemic-system.jar app.jar ENTRYPOINT [java,-jar,/app.jar]6.2 前端部署配置Vite生产环境构建npm run buildNginx配置示例server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://backend:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }6.3 性能监控与调优SpringBoot Actuator集成dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-actuator/artifactId /dependencyapplication.yml监控端点配置management: endpoints: web: exposure: include: health,info,metrics,prometheus endpoint: health: show-details: always7. 开发经验与避坑指南MyBatis踩坑记录当使用PageHelper分页时确保紧跟startPage方法后就是查询语句中间不能有其他数据库操作实体类属性名与数据库字段名映射问题建议统一使用下划线转驼峰配置批量插入数据时使用foreach标签要特别注意SQL长度限制Vue3组合式API最佳实践将相关逻辑抽离到自定义hook中提高代码复用性使用script setup语法时注意响应式数据的声明方式合理使用watch和watchEffect处理副作用跨域问题解决方案开发环境配置Vite代理生产环境使用Nginx反向代理避免使用CrossOrigin注解导致的安全隐患MySQL性能优化技巧大数据量分页使用延迟关联优化定期使用ANALYZE TABLE更新统计信息合理设置innodb_buffer_pool_size参数前后端联调经验使用Swagger或Knife4j维护API文档定义统一的响应体结构错误码规范设计这套疫情管理系统在实际部署中经受住了日均10万访问量的考验特别是在使用Element Plus表格组件展示大量数据时通过虚拟滚动技术解决了性能瓶颈问题。对于需要处理更复杂疫情数据分析的场景可以考虑引入Elasticsearch作为二级存储提升查询效率。