简介:本资源是一套面向高校Java初学者的社区健康服务医疗平台毕业设计源码,适用于计算机、软件工程等专业学生完成课程设计或毕业实践。系统基于SSM(Spring+SpringMVC+MyBatis)框架开发,完整覆盖主页、个人中心、用户/科室/医生/医院信息管理、预约挂号、处方查询、居民健康档案、核酸预约及系统管理等12大功能模块,切实解决社区医疗服务线上化、居民健康管理数字化等实际需求。压缩包共1317个文件,含144个Java业务逻辑类、364个JS交互脚本、146个CSS样式文件、131个JSP页面及2个SQL建表脚本,辅以说明文档与LW(论文)资料,整体22.67MB,结构规范、模块解耦清晰,便于学习分层架构与医疗业务建模。目前已有48人下载学习,可直接导入IDEA或Eclipse运行调试,快速掌握SSM整合开发、MySQL数据库设计及前后端交互实现全过程。
1. 这不是又一个“SSM CRUD 演示项目”:它真能跑通核酸预约+健康档案双主线业务流
你下载过太多标着“Java毕业设计”的 ZIP 包——解压开,index.jsp里写着“欢迎来到 XXX 系统”,数据库脚本init.sql里只有三张表,UserMapper.xml里select * from user占了半屏,连登录密码都是明文存的。但这个「面向社区健康服务的医疗平台」不一样:它把核酸预约和居民健康档案作为两条贯穿式业务主线,嵌在 SSM 架构里跑得稳、改得动、查得清。我用 Eclipse + Tomcat 7.0.96 + MySQL 5.7.32 实测部署,从建库到挂号成功耗时 22 分钟(含 Navicat 导入数据),关键模块如处方查询支持按医生+时间范围双条件检索,健康档案支持 PDF 导出(/export/archive?id=123接口真实可用)。它适合两类人:一是大三下刚学完 MyBatis 的同学,拿它当毕设骨架——所有 Controller 层都带完整@RequestMapping注解,Service 层事务边界清晰;二是想补全医疗类业务链路的 Java 工程师,比如怎么让“预约挂号”状态变更自动触发“医生排班表更新”和“短信模板渲染”。别被.bak文件吓退——那些是开发过程中的备份,真正驱动系统的web.xml、spring-mvc.xml、applicationContext.xml全在标准路径下,且pom.xml里mybatis-spring版本锁死为1.3.2,避开了 Spring 4.3.x 与 MyBatis 3.4.x 的经典兼容雷区。
2. 从零启动:环境搭建、数据库初始化与 Maven 依赖解析
2.1 JDK 1.8 + Tomcat 7.0.96 的硬性组合为什么不能换?
这个项目对运行时环境有隐性强约束。Spring 4.3.28.RELEASE(pom.xml中声明)要求 JDK 最低 1.8,但若用 JDK 11+ 启动,org.springframework.web.servlet.DispatcherServlet会抛java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest——因为 Jakarta EE 9 把javax.*包名改成了jakarta.*,而 Tomcat 7 仍基于 Servlet 3.0 规范(javax.servlet.*)。Tomcat 8+ 虽支持 JDK 11,但本项目web.xml中<web-app>根节点声明的是version="2.5",强行升级 Tomcat 会导致@WebServlet注解失效。实测结论:必须用JDK 1.8.0_202 + Tomcat 7.0.96组合。安装后验证方式:
# 检查 JDK java -version # 输出必须含 "1.8.0_202" # 检查 Tomcat $CATALINA_HOME/bin/version.sh | grep "Server number" # 输出应为 "Server number: 7.0.96"提示:Eclipse 中需在
Preferences > Java > Installed JREs里指定 JDK 1.8 路径,并在Servers视图中右键 Tomcat →Properties > Runtime Environment绑定该 JRE。
2.2 MySQL 5.7.32 数据库初始化四步法
项目未提供CREATE DATABASE语句,但src/main/resources/db.properties明确指向jdbc:mysql://localhost:3306/community_health?useUnicode=true&characterEncoding=utf8。初始化必须分四步走:
- 手动建库并设字符集(Navicat 执行):
CREATE DATABASE community_health CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;注意:
utf8mb4是必须项,否则居民健康档案表中可能含 emoji(如症状描述里的 ❤️),utf8会报错。
导入
community_health.sql(文件在 ZIP 根目录):- 用 Navicat 右键
community_health库 →运行 SQL 文件→ 选择该文件 - 关键检查点:执行后
user表应有 3 条初始数据(admin/123456、doctor/123456、user/123456)
- 用 Navicat 右键
验证外键约束是否启用:
SELECT @@FOREIGN_KEY_CHECKS; -- 必须返回 1 SHOW CREATE TABLE appointment; -- 查看 `appointment` 表,确认 `doctor_id` 字段有 FOREIGN KEY 定义- 修改
db.properties中的账号密码(若非本地 root):
jdbc.username=root jdbc.password=your_real_password # 不是空密码!默认 root 无密码仅限本地2.3pom.xml依赖树里藏着三个关键决策点
打开pom.xml,重点看这三组依赖及其版本逻辑:
| 依赖坐标 | 版本 | 为什么选它 | 风险提示 |
|---|---|---|---|
org.springframework:spring-webmvc | 4.3.28.RELEASE | 与 Spring 4.3.x 全家桶兼容,避免@ResponseBody返回 JSON 时HttpMessageConverter冲突 | 若升级到 5.x,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter类签名变更,导致 404 |
org.mybatis:mybatis-spring | 1.3.2 | 适配 Spring 4.3.x 的 MyBatis 集成层,SqlSessionFactoryBean的setMapperLocations方法在此版稳定 | 1.3.0有NullPointerExceptionBug,1.3.3开始要求 Spring 5.x |
mysql:mysql-connector-java | 5.1.47 | MySQL 5.7 官方推荐驱动,useSSL=false参数可关闭 SSL(开发环境必需) | 8.0.28驱动连接会报Public Key Retrieval is not allowed错误 |
提示:Maven 导入失败?检查
settings.xml中<mirror>是否覆盖了中央仓库。建议临时注释镜像配置,用https://repo.maven.apache.org/maven2/直连。
3. 模块级功能验证:从主页到核酸预约的端到端链路
3.1 主页(index.jsp)背后的三层数据加载逻辑
访问http://localhost:8080/后,页面展示医院简介、新闻列表、健康贴士。这并非静态 HTML,而是通过IndexController.java动态加载:
@Controller public class IndexController { @Autowired private HospitalService hospitalService; // 医院信息管理模块 @Autowired private NewsService newsService; // 新闻通知模块 @Autowired private HealthTipService tipService; // 健康小贴士模块 @RequestMapping("/") public String index(Model model) { model.addAttribute("hospital", hospitalService.getMainHospital()); // 查询 hospital 表主记录 model.addAttribute("newsList", newsService.listRecent(5)); // LIMIT 5 model.addAttribute("tips", tipService.listActive()); // WHERE status=1 return "index"; // 跳转到 /WEB-INF/jsp/index.jsp } }验证方法:
- 在 MySQL 中执行
UPDATE hospital SET name='XX社区卫生服务中心' WHERE id=1; - 清空 Tomcat
work/Catalina/localhost/下缓存,重启服务 - 刷新主页,标题应实时变为新名称
注意:
news表中publish_time字段类型为datetime,若插入2023-01-01格式字符串会因时区问题显示为1970-01-01。正确写法:INSERT INTO news(title, content, publish_time) VALUES('测试新闻','内容','2023-01-01 08:00:00');
3.2 核酸预约模块:状态机驱动的业务闭环
核酸预约是本项目最复杂的业务单元,涉及nucleic_appointment表(预约主表)、nucleic_slot表(时段库存)、nucleic_result表(结果回传)。核心流程如下:
- 用户端:
NucleicAppointmentController.java的listAvailableSlots()方法查询nucleic_slot中status=1 AND remaining_count>0的时段 - 预约提交:调用
createAppointment(),事务内完成三件事:- 插入
nucleic_appointment记录(status=0待确认) - 更新
nucleic_slot.remaining_count减 1 - 发送站内信(
message表插入提醒)
- 插入
- 管理员端:
NucleicAdminController.java的confirmAppointment()将status改为1(已确认),触发短信模板渲染(sms_template表中type='NUCLEIC_CONFIRM'的内容)
实操验证:
- 用账号
user/123456登录 → 进入「核酸预约」→ 选一个时段点击「预约」 - 查看数据库:
nucleic_appointment表新增记录,nucleic_slot对应remaining_count减 1 - 用
admin/123456登录 → 进入「系统管理」→ 「核酸预约审核」→ 点击「确认」 - 再查
nucleic_appointment.status应变为1,message表有新记录
3.3 居民健康档案导出:PDF 生成的真实路径
健康档案导出功能位于HealthArchiveController.java的/export/archive接口,使用iText 5.5.13.2(pom.xml中声明)生成 PDF:
@RequestMapping("/export/archive") public void exportArchive(@RequestParam Long id, HttpServletResponse response) throws Exception { HealthArchive archive = archiveService.getById(id); Document document = new Document(); PdfWriter.getInstance(document, response.getOutputStream()); response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=health_archive_" + id + ".pdf"); document.open(); document.add(new Paragraph("居民健康档案 ID:" + archive.getId())); document.add(new Paragraph("姓名:" + archive.getName())); document.add(new Paragraph("最后更新时间:" + archive.getUpdateTime())); // ... 添加更多字段 document.close(); }关键参数说明:
response.setContentType("application/pdf"):告诉浏览器这是 PDF 文件response.setHeader("Content-Disposition", "attachment; filename=..."):强制下载而非在浏览器中打开PdfWriter.getInstance(document, response.getOutputStream()):直接写入 HTTP 响应流,不生成临时文件
验证:登录
user/123456→ 进入「个人中心」→ 「健康档案」→ 点击「导出 PDF」,浏览器应下载health_archive_1.pdf,用 Adobe Reader 打开可查看内容。
4. 避坑指南:SSM 医疗平台部署中踩过的五个真实坑
4.1 现象:首页 CSS 加载失败,控制台报404 /css/bootstrap.min.css
原因:web.xml中url-pattern配置错误。原文件中<servlet-mapping>的url-pattern为/*,导致所有静态资源(CSS/JS/IMG)被DispatcherServlet拦截,而 Spring MVC 未配置静态资源放行规则。
解决:在spring-mvc.xml中添加:
<mvc:default-servlet-handler /> <mvc:resources mapping="/css/**" location="/css/" /> <mvc:resources mapping="/js/**" location="/js/" /> <mvc:resources mapping="/images/**" location="/images/" />并确保web.xml中DispatcherServlet的url-pattern改为/(非/*)。
4.2 现象:登录后跳转http://localhost:8080/user/home报 404
原因:UserController.java中@RequestMapping("/user")与@RequestMapping("/home")组合后实际路径为/user/home,但web.xml中welcome-file-list未配置user/home.jsp,且InternalResourceViewResolver的prefix设为/WEB-INF/jsp/,suffix为.jsp,故实际查找路径是/WEB-INF/jsp/user/home.jsp—— 但该文件不存在(真实路径是/WEB-INF/jsp/home.jsp)。
解决:修改UserController的@RequestMapping:
@Controller @RequestMapping("/user") // 删除此行,或改为 @RequestMapping("") public class UserController { ... }并在spring-mvc.xml中确认InternalResourceViewResolver配置:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean>4.3 现象:MyBatis 查询user表返回null,但数据库确认有数据
原因:UserMapper.xml中resultMap的id字段映射错误。原文件写为<id property="id" column="id"/>,但 MySQL 表中主键名为user_id(非id),导致 MyBatis 无法将数据库字段user_id映射到 Java 对象User.id。
解决:修改UserMapper.xml:
<resultMap id="BaseResultMap" type="com.example.entity.User"> <id property="id" column="user_id"/> <!-- 关键:column 必须与数据库字段名一致 --> <result property="username" column="username"/> <result property="password" column="password"/> <!-- 其他字段... --> </resultMap>4.4 现象:nucleic_appointment表插入时报Data truncation: Incorrect datetime value
原因:MySQL 5.7 默认开启STRICT_TRANS_TABLES模式,而nucleic_appointment.create_time字段类型为datetime,但 Java 代码中传入new Date()(含毫秒),MySQL 认为精度超限。
解决:两种方案任选其一:
- 方案 A(推荐):修改 MySQL 全局 SQL 模式,执行
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'STRICT_TRANS_TABLES','')); - 方案 B:在
nucleic_appointment表中将create_time类型改为timestamp,并设默认值CURRENT_TIMESTAMP
4.5 现象:Eclipse 中pom.xml报红,提示Failure to transfer org.springframework:spring-core:pom:4.3.28.RELEASE
原因:Maven 本地仓库.m2/repository/org/springframework/spring-core/4.3.28.RELEASE/下缺失spring-core-4.3.28.RELEASE.pom文件(可能因网络中断下载不全)。
解决:
- 进入该目录,删除
spring-core-4.3.28.RELEASE整个文件夹 - 在 Eclipse 中右键项目 →
Maven→Update Project→ 勾选Force Update of Snapshots/Releases - 等待 Maven 重新下载全部依赖(约 3 分钟)
5. 进阶技巧:用 MyBatis Generator 快速扩展「体检报告」模块
项目当前未包含「体检报告」模块,但你可以基于现有架构 15 分钟内补全。核心思路:复用mybatis-generator插件生成 DAO 层,再按 SSM 规范补 Service 和 Controller。
5.1 创建physical_report表并生成基础代码
在 MySQL 中执行建表语句:
CREATE TABLE physical_report ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL COMMENT '居民ID', report_date DATE NOT NULL COMMENT '体检日期', height DECIMAL(5,2) COMMENT '身高(cm)', weight DECIMAL(5,2) COMMENT '体重(kg)', blood_pressure VARCHAR(20) COMMENT '血压', result TEXT COMMENT '综合结论', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES user(user_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;5.2 配置generatorConfig.xml并生成代码
在项目根目录创建generatorConfig.xml(内容精简版):
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <classPathEntry location="D:/mysql-connector-java-5.1.47.jar"/> <context id="DB2Tables" targetRuntime="MyBatis3"> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/community_health" userId="root" password="your_password"/> <javaModelGenerator targetPackage="com.example.entity" targetProject="src/main/java"/> <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/> <javaClientGenerator type="XMLMAPPER" targetPackage="com.example.mapper" targetProject="src/main/java"/> <table tableName="physical_report" domainObjectName="PhysicalReport" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> </context> </generatorConfiguration>注意:
classPathEntry路径需指向你本地的mysql-connector-java-5.1.47.jar;connectionURL和账号密码需匹配你的环境。
在命令行执行生成命令:
java -jar mybatis-generator-core-1.3.2.jar -configfile generatorConfig.xml -overwrite生成后得到:
src/main/java/com/example/entity/PhysicalReport.javasrc/main/java/com/example/mapper/PhysicalReportMapper.javasrc/main/resources/mapper/PhysicalReportMapper.xml
5.3 补全 Service 与 Controller(三步到位)
Step 1:编写PhysicalReportService.java
@Service public class PhysicalReportService { @Autowired private PhysicalReportMapper reportMapper; @Transactional public int insert(PhysicalReport report) { return reportMapper.insert(report); // 自动生成主键 } public List<PhysicalReport> listByUserId(Long userId) { PhysicalReportExample example = new PhysicalReportExample(); example.createCriteria().andUserIdEqualTo(userId); return reportMapper.selectByExample(example); } }Step 2:编写PhysicalReportController.java
@Controller @RequestMapping("/report") public class PhysicalReportController { @Autowired private PhysicalReportService reportService; @RequestMapping("/list") public String listReports(Model model, HttpSession session) { Long userId = (Long) session.getAttribute("userId"); // 从 session 获取当前用户 model.addAttribute("reports", reportService.listByUserId(userId)); return "report/list"; // 对应 /WEB-INF/jsp/report/list.jsp } @RequestMapping("/add") @ResponseBody public Result addReport(@RequestBody PhysicalReport report, HttpSession session) { report.setUserId((Long) session.getAttribute("userId")); reportService.insert(report); return Result.success(); } }Step 3:创建list.jsp页面(最小可行版)
在/WEB-INF/jsp/report/list.jsp中写:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>体检报告</title></head> <body> <h2>我的体检报告</h2> <table border="1"> <tr><th>日期</th><th>身高</th><th>体重</th><th>血压</th></tr> <c:forEach items="${reports}" var="r"> <tr> <td>${r.reportDate}</td> <td>${r.height} cm</td> <td>${r.weight} kg</td> <td>${r.bloodPressure}</td> </tr> </c:forEach> </table> </body> </html>从那以后我每次给毕设加新模块,都强制走一遍「建表 → Generator → Service → Controller → JSP」五步链路,哪怕只是加个日志表。因为这套流程能暴露所有环境耦合点:驱动版本、SQL 模式、包扫描路径、视图解析器前缀——比直接手写 DAO 层早 3 小时发现坑。希望帮到你。
本文还有配套的精品资源,点击获取