简介:基于安卓Android Studio的智慧医疗医院预约挂号App毕业设计项目,涵盖安卓服务器端与客户端,面向计算机专业毕业设计、课程设计及移动开发入门者,可作为选题参考和二次开发蓝本。项目完整实现病人注册登录、流行病学调查表填写、核酸检查预约与记录查询、新冠疫苗预约、门诊预约、医保卡绑定及就诊卡创建等业务链路,能系统掌握原生安卓开发与SQLite数据库的集成应用。压缩包共115个文件,约4.87MB,以40个XML界面布局、14个Java业务类、图片资源、Gradle构建配置及项目报告docx为主,从界面到业务逻辑分层清晰,便于按模块查阅与修改。目前已有503人学习下载,源码注释与文档可有效降低上手门槛,适合快速搭建医院预约挂号原型,并在此基础上扩展预约提醒、健康档案等功能。
1. 智慧医疗医院预约挂号App:这份毕业设计源码到底能拿去做什么
又到了毕业设计“开题三分钟、改代码三星期”的季节。预约挂号这个题目每年都有大把人选,但大部分同学卡在同一个地方:App界面能打开,服务器端却连不上;或者代码能跑通,答辩时被问一句“你的数据是怎么从客户端到服务器的”,就支支吾吾说不清。这份基于安卓AndroidStudio开发的智慧医疗医院预约挂号App源码包,把客户端和服务器端都完整给你了,你拿到的不是半个Demo,而是一条从用户注册、科室浏览、医生列表、在线预约到后台管理的完整业务链路。它适合两类人:一类是拿它做毕业设计、需要快速跑通并讲清原理的学生;另一类是接外包或者做原型验证的开发者,想找一套结构清楚、能直接改的安卓预约类项目做基底。接下来我会把技术栈、部署步骤、核心逻辑和最容易翻车的位置全部拆开讲,你照着走一遍,就能判断这份源码值不值得花时间。
2. 技术栈与整体架构:客户端、服务器端和数据库是怎么分工的
2.1 为什么是“Android客户端 + Java服务端 + MySQL”的组合
这套资源里明确写着“包括安卓服务器端和安卓客户端”。从项目形态看,这是典型的单体架构学生项目:Android原生App负责展示与交互,服务器端负责业务逻辑和数据持久化,两者通过HTTP协议交换JSON数据。服务端常见的实现方式是Java Web方向,也就是Servlet/JSP那一套,或者Spring Boot / SSM框架。具体到这份源码,不管它用的是哪种方式,你打开项目目录后只要能找到Servlet或者Controller层,就能快速定位业务入口。
选这个组合的好处很直白:第一,它完全贴合Android Studio的开发习惯,你不需要额外搭前后端分离的Node环境;第二,Java Web服务端和Android客户端同为Java语言体系,实体类、JSON解析逻辑可以在两端复用,改起来成本低;第三,答辩时数据流链路清晰,评审老师问“从点击按钮到数据库写入经历了什么”,你能用一条线讲到底。
如果你打开源码发现服务端是JSP+Servlet,不要嫌它老。恰恰是这种老组合最适合毕业设计场景:部署简单、依赖少、逻辑直白,跑通了不容易出幺蛾子。Spring Boot虽然开发快,但Tomcat版本、Maven依赖、端口冲突这些问题反而会让新手多踩几个坑。
2.2 安卓客户端与服务端的模块目录结构
拿到源码包后,解压出来通常是两个独立工程:一个Android项目(客户端),一个Java Web项目(服务器端)。我建议你先把两边的主要目录扫一遍,建立整体地图。
客户端部分的常见结构如下表所示:
| 包名/目录 | 职责 | 典型类/文件 |
|---|---|---|
| activity | 界面控制层,一个页面一个Activity | LoginActivity、RegisterActivity、DoctorListActivity、AppointmentActivity |
| adapter | 列表项适配,把数据填充到ListView/RecyclerView | DoctorAdapter、AppointmentAdapter |
| entity / bean | 实体类,对应服务器端返回的JSON结构 | User、Doctor、Appointment |
| utils / util | 工具类,包含网络请求、共享参数读写 | HttpUtils、JsonUtils |
| network / okhttp | 网络层封装,负责HTTP调用和数据回调 | NetClient、ApiService |
服务器端的结构则更偏向经典Java Web分层:
| 包名/目录 | 职责 | 典型类/文件 |
|---|---|---|
| servlet / controller | 接收客户端请求,解析参数,返回JSON | UserServlet、DoctorServlet、AppointmentServlet |
| service | 业务逻辑层,处理预约规则、状态流转 | AppointmentService、UserService |
| dao / mapper | 数据库访问层,执行SQL语句 | UserDao、DoctorDao、AppointmentDao |
| util | 数据库连接、JSON转换工具 | DBUtil、JsonUtil |
你先对照这个表把源码里的类归归类,不需要逐行读,只需要知道“某个功能去找哪个包”。这样后面改需求的时候,你不会在几百个文件里迷路。
2.3 一次预约挂号请求的完整链路
跑通项目之前,你必须先理解数据是怎么流动的。我以“用户提交预约挂号”这个动作为例,把全链路拆给你看,这也基本是答辩必问的一条线。
用户在Android客户端选择医生、点击“预约”后,发生的完整过程是这样的:
客户端把预约信息(用户ID、医生ID、预约日期、时段)组装成JSON,通过HTTP POST发送给服务器端接口;服务器端Servlet接收到请求后,先从JSON里解析出参数,校验用户是否登录、号源是否充足,然后调用DAO层把预约记录写入MySQL数据库;数据库插入成功后,服务器端把“预约成功”的状态和预约单号封装成JSON返回给客户端;客户端收到结果后解析JSON,刷新“我的预约”列表。
对应到代码层面,客户端网络请求的核心代码长这样:
// 客户端:使用HttpURLConnection发送POST请求 public static String postJson(String urlStr, String jsonBody) { HttpURLConnection conn = null; try { URL url = new URL(urlStr); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setConnectTimeout(5000); // 连接超时5秒 conn.setReadTimeout(5000); // 读取超时5秒 conn.setDoOutput(true); // 允许输出请求体 conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); // 写入JSON数据 OutputStream os = conn.getOutputStream(); os.write(jsonBody.getBytes("UTF-8")); os.flush(); os.close(); // 读取服务器响应 if (conn.getResponseCode() == 200) { InputStream is = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line); } reader.close(); return sb.toString(); } } catch (Exception e) { e.printStackTrace(); } finally { if (conn != null) conn.disconnect(); } return null; }这段代码里的关键点:setConnectTimeout(5000)和setReadTimeout(5000)是超时保护,避免网络异常时App卡死;Content-Type头必须设置为application/json,否则服务器端解析不了中文参数;getResponseCode()返回200才读数据,这是最基础的HTTP状态判断。很多同学照着抄网络请求代码却连不上服务器,十有八九是Content-Type没设置对,或者请求和响应的编码不一致。
3. 把项目跑起来:环境准备与部署实操
3.1 环境清单与版本选择建议
跑这套项目之前,先把环境对齐,省得后面反复折腾。以下是经过验证的推荐组合:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | JDK 8 或 JDK 11 | 老项目用JDK 8最稳,部分新Android Studio版本默认JDK 17也兼容 |
| Android Studio | 4.0 以上均可 | 新版Studio打开老项目时会提示升级Gradle,选“不升级”更安全 |
| Android SDK | minSdk 21,targetSdk 28或30 | 太高的targetSdk会触发明文HTTP限制,后面避坑章细说 |
| MySQL | 5.7 或 8.0 | 5.7兼容性最好,8.0需要调整驱动包 |
| Tomcat | 8.5 或 9.0 | 支持Servlet 3.0以上即可,版本太高反而容易出问题 |
| 查看工具 | Navicat 或 MySQL命令行 | 用于导入数据库脚本和验证数据 |
这里说一句:不要为了追求新版本而用最新版Android Studio直接打开老工程,Gradle插件版本不匹配会让你卡在同步阶段出不来。如果手头只有新版Studio,建议在build.gradle里把gradle版本固定到项目原来带的版本。
3.2 从AndroidStudio导入安卓客户端
客户端导入是最常见的第一道坎。打开Android Studio,选择“Open an existing project”,定位到源码包里的Android客户端目录,等待Gradle同步完成。
同步过程中,如果出现依赖下载失败,多半是网络问题。我一般会检查项目的build.gradle文件里仓库地址是否配了jcenter()或mavenCentral(),如果原项目用了jcenter()而它已经关停,就把仓库地址替换成:
repositories { google() mavenCentral() }这里要注意:jcenter()虽然已经被标记为只读,但很多老项目依然在使用。如果你把仓库地址改成google()和mavenCentral()后仍然报找不到依赖,可以尝试在gradle.properties里加上android.enableJetifier=true和android.enableAapt2=false,能解决一部分老依赖的兼容问题。
同步完成后,先别急着点运行。打开AndroidManifest.xml,检查以下两项:
<uses-permission android:name="android.permission.INTERNET" /> <application android:usesCleartextTraffic="true">第一行是网络权限,缺了它App直接没有网络能力;第二行是允许明文HTTP流量,Android 9(API 28)以上默认禁止HTTP明文传输,不加这一行你连服务器时会报错。这两项是新手最容易漏掉的配置。
3.3 部署数据库与启动服务器端
服务器端的部署分为两步:导入数据库脚本、启动Tomcat。
打开MySQL命令行或者Navicat,执行数据库脚本:
mysql -u root -p < hospital_db.sql执行完后,用show databases;确认数据库是否创建成功,再用use hospital; show tables;查看表结构。如果导入报错,最常见的原因是数据库编码问题,或者SQL脚本里带着DROP TABLE语句但数据库不存在同名的库。此时手动执行CREATE DATABASE hospital DEFAULT CHARACTER SET utf8;再导入即可。
启动Tomcat前,先改数据库连接配置。在服务端项目的DBUtil.java或jdbc.properties文件里找到连接串:
private static final String URL = "jdbc:mysql://localhost:3306/hospital?useUnicode=true&characterEncoding=utf8"; private static final String USER = "root"; private static final String PASSWORD = "123456";这里的characterEncoding=utf8是防中文乱码的关键,漏掉的话你入库的中文全是问号。密码改成你自己MySQL的密码。改完配置,把服务端项目打包成WAR包放到Tomcat的webapps目录下,启动Tomcat后访问http://localhost:8080/项目名/,如果能打开欢迎页就说明服务端已经就绪。
3.4 联调:让安卓App连上服务器端
服务端跑起来后,客户端还得知道去哪里找服务端。打开客户端项目里的网络配置类,找到BaseUrl的定义:常见的写法是public static final String BASE_URL = "http://10.0.2.2:8080/hospital/"。
这里10.0.2.2是Android模拟器访问宿主机(你的电脑)的特殊地址,表示“宿主机的localhost”。如果你用的是真机调试,这个地址必须改成你电脑在局域网的IP,用命令行输入ipconfig或ifconfig查到后替换,否则真机永远连不上服务端。改完之后,先在模拟器里点一个登录按钮试试,能请求通再往下走。
4. 核心功能拆解:预约挂号流程与数据库设计
4.1 核心API接口清单与参数说明
整个系统的功能边界由服务器端接口决定。以下是一份典型的预约挂号系统接口清单,你对照源码里的Servlet类看,就能快速掌握全貌:
| 接口路径 | 请求方式 | 关键参数 | 返回内容 |
|---|---|---|---|
| UserServlet?action=register | POST | username、password、phone | 注册结果JSON |
| UserServlet?action=login | POST | username、password | 用户信息 + token |
| DoctorServlet?action=list | GET | departmentId | 医生列表JSON数组 |
| AppointmentServlet?action=add | POST | userId、doctorId、date、time | 预约单号 + 状态 |
| AppointmentServlet?action=mine | GET | userId | 我的预约列表 |
| AppointmentServlet?action=cancel | POST | appointmentId | 取消结果 |
这里有一个细节值得注意:action参数是Java Web项目中常见的分发方式,一个Servlet类处理多个操作,通过action值来区分。如果你是第一次读这种代码,不要慌,直接找到Servlet里的if ("login".equals(action))这种判断语句,顺着读就行。
4.2 数据库表设计的核心逻辑
预约挂号系统的数据库设计,核心围绕“用户、医生、号源、订单”四个维度展开。典型的核心表结构如下:
| 表名 | 核心字段 | 说明 |
|---|---|---|
| user | id、username、password、phone | 用户注册信息;密码一般存MD5,项目阶段明文也可以接受 |
| department | id、name、intro | 科室表,内科、外科、儿科 |
| doctor | id、name、department_id、title、intro | 医生表,通过department_id关联科室 |
| schedule | id、doctor_id、work_date、remaining | 排班表,记录某天号源余量 |
| appointment | id、user_id、doctor_id、date、time、state | 预约订单表,state用于标记状态 |
其中appointment表的state字段是整个业务逻辑的核心,我建议你用整数表示状态:0待就诊、1已完成、2已取消。这样在“我的预约”页签列表查询时,直接用WHERE user_id=? AND state!=2就能过滤掉已取消的记录。有的学生项目会把state存成字符串“已预约”“已完成”,也能跑,但查询和统计的便利性就差很多了。
4.3 客户端网络层封装与JSON解析
客户端与服务端的通信基础是JSON解析。在Android客户端里,你通常会看到Gson或org.json两种解析方式。推荐用Gson,它能把服务器端返回的JSON字符串直接映射成实体对象,代码简洁且不容易出错。
// 客户端:使用Gson解析医生列表JSON public List<Doctor> parseDoctorList(String jsonString) { Gson gson = new Gson(); // 服务器返回格式:{"code":200,"data":[{...}, {...}]} JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject(); JsonArray dataArray = root.getAsJsonArray("data"); List<Doctor> list = new ArrayList<>(); Type type = new TypeToken<List<Doctor>>() {}.getType(); list = gson.fromJson(dataArray, type); return list; }需要注意:服务器端返回的JSON字段名必须和实体类字段名保持一致,否则Gson映射出来的对象全是null。如果服务器端返回的是user_name而实体类里是username,就需要加上@SerializedName注解来对齐。这是一个非常隐蔽的坑,你排查的时候先对比字段名,比什么都快。
4.4 分时段预约的实现细节
这套项目如果做到了“分时段放号”,比如上午号、下午号,那schedule表和appointment表的设计会有微妙变化。schedule表里需要区分时间段,比如time_type字段(1上午、2下午),或者直接用时间字符串。预约时先判断该医生在某天某个时间段是否有余号,有余号才允许创建预约记录,同时把remaining减1。
这部分的业务逻辑在服务端的AppointmentService类中,核心判断代码大概是:
// 服务端:预约前校验号源余量 public synchronized boolean bookAppointment(int scheduleId, int userId) { Schedule schedule = scheduleDao.findById(scheduleId); if (schedule.getRemaining() <= 0) { return false; // 号源已约满 } schedule.setRemaining(schedule.getRemaining() - 1); scheduleDao.update(schedule); appointmentDao.insert(userId, scheduleId); return true; }这里有一个值得答辩时提的点:方法上加了synchronized关键字,防止两个人同时抢最后一个号导致超卖。能主动说出这个并发控制意识,比写几百行功能代码更让老师眼前一亮。你甚至可以顺着这个点,在答辩时多说一句“如果要上生产环境,应该引入数据库行级锁或Redis原子操作来做更严格的号源控制”,加分效果明显。
5. 避坑指南:毕设项目最常见的五类翻车现场
5.1 模拟器连不上服务器端:Confusion 三兄弟
现象:App启动后点击登录,直接提示“网络连接失败”或者卡住不动,Logcat里报ConnectException: failed to connect to localhost/127.0.0.1 port 8080。
原因:你把BaseUrl配成了http://localhost:8080或http://127.0.0.1:8080。Android模拟器里的localhost指向模拟器自己,而不是你的电脑,所以这个连接永远不可能建立成功。
解决:把BaseUrl改成http://10.0.2.2:8080/项目名/。模拟器里10.0.2.2被特殊映射为宿主机的回环地址,这是Android模拟器写死的一个约定。如果你用真机,就改成电脑的局域网IP。这是项目联调第一坑,几乎每个跑这套代码的人都会遇到。
5.2 数据库中中文全部变成问号
现象:通过App注册用户时,用户名和手机号里的中文存进MySQL后全部变成???,英文和数字正常。
原因:数据库连接URL没有指定characterEncoding=utf8,导致JDBC驱动用默认的ISO-8859-1编码去写入中文字符。也可能是数据库表本身是latin1字符集,编码不对。
解决:在DBUtil.java的连接串末尾加上?useUnicode=true&characterEncoding=utf8;同时确认数据库建库时指定了DEFAULT CHARACTER SET utf8。如果表已经建好了,执行ALTER TABLE user CONVERT TO CHARACTER SET utf8;可以修复已有表的编码。改完之后重启Tomcat,新数据就不会再乱码。
5.3 Gradle同步失败:SDK版本和插件版本打架
现象:导入客户端项目后,Gradle同步报错Failed to resolve: com.android.tools.build:gradle:3.x.x或者SDK Build Tools revision xx.x.x is not installed。
原因:老项目引用的Gradle插件版本下载不到,或者本地Android SDK缺少对应版本的Build Tools。新版Android Studio不一定自动下载旧版SDKBuild Tools。
解决:打开项目的build.gradle,把classpath 'com.android.tools.build:gradle:旧版本号'改成当前Android Studio能识别的版本,比如4.2.x或7.x;然后打开SDK Manager,勾选安装项目要求的Build Tools版本。改版本号后,再改gradle-wrapper.properties里的distributionUrl,换成对应的Gradle版本,比如Android Gradle Plugin 4.2对应Gradle 6.7.1。
5.4 Android 9以上HTTP明文流量被系统拦了
现象:真机调试时显示CLEARTEXT communication to xxx not permitted by network security policy,App请求直接失败,但模拟器上同样代码却能通。
原因:Android 9(API 28)开始,系统默认禁止应用使用未加密的HTTP明文流量。你的服务端是Tomcat的HTTP接口,没有走HTTPS,所以被系统安全策略直接拦截。模拟器上有时不报错是因为模拟器系统版本可能低于API 28。
解决:在AndroidManifest.xml的<application>标签上添加android:usesCleartextTraffic="true"。这个属性是全局放开明文流量,毕业设计和本地开发完全够用。如果到了上线生产环境,再考虑把服务端换成HTTPS,并去掉这个属性。
5.5 真机USB调试显示“未找到设备”
现象:手机连接电脑后,adb devices列表是空的,Android Studio运行按钮里也看不到设备。
原因:手机没有开启“开发者选项”和“USB调试”,或者USB线是纯充电线不支持数据传输,再或者电脑缺少对应的USB驱动。
解决:在手机上连续点击“版本号”七次开启开发者模式,进入“开发者选项”打开“USB调试”;换一根手机原装数据线(能传文件的那种);Windows平台需要安装手机对应品牌的USB驱动。如果这些都做了还不行,在命令行执行adb kill-server和adb start-server重启ADB服务,大部分情况下能解决。
6. 二次开发方向:把预约挂号App改造成通用业务模板
6.1 从医疗预约到通用预约模板的抽象方法
如果做完毕业设计答辩还想继续深挖,或者想接外包时复用这套代码,我建议你做一次抽象改造,让它从“医院预约挂号”变成通用预约系统。
改造的核心是数据模型。当前department表管的是“内科、外科”这些医疗科室,doctor表管的是医生,appointment表管的是预约订单。你可以把这几个表抽象成通用模型:category表对应业务分类(服务项目、资源类型),resource表对应可预约的资源(医生、会议室、工位、疫苗批次),order表对应预约订单。这样改造之后,这套系统可以用来做体检预约、疫苗预约、会议室预订、实验室设备预约,甚至上门维修工单管理,业务扩展性直接拉开一个层次。
具体落地时,服务端的Servlet层改动很小,因为HTTP接口的请求和响应逻辑是通用的;核心改的是数据库表和客户端的文本标签。我习惯把科室列表页改成“分类/服务”列表,把医生列表页改成“资源/时段”列表,然后配合简单的界面文案替换,一套新业务就出来了。
6.2 验证系统完整性的演示清单
拿到这套源码后,我建议你按下面这个清单做一次完整验证,每一个操作都对应到数据库的变化,这样演示时心里有底:
| 演示步骤 | 操作 | 预期结果 | 数据库变化 |
|---|---|---|---|
| 1 | 注册新用户 | 提示注册成功,自动跳转登录页 | user表新增一条记录 |
| 2 | 登录 | 跳转首页,显示用户名 | 无数据变化 |
| 3 | 选择科室 | 显示该科室下的医生列表 | 无数据变化 |
| 4 | 点击医生预约 | 选择日期时间段,确认预约 | schedule表remaining减1,appointment表新增记录 |
| 5 | 查看我的预约 | 显示刚预约的记录,状态为待就诊 | 无数据变化 |
| 6 | 取消预约 | 状态变为已取消,医生态度不可见 | appointment表state改为2,schedule表remaining加1 |
| 7 | 再次查看我的预约 | 已取消的记录消失 | 无数据变化 |
这套验证流程走完,整个项目的主要功能和数据流转你就全部掌握了一遍。答辩时老师如果让你现场演示,你按这个顺序操作,每一步都能说出背后的数据变化,说服力比干讲PPT强很多。
6.3 内容安全自查、编码规范与资源再打包建议
这套系统既然涉及用户手机号,你需要注意几个容易被忽略的点:首先是接口层防止SQL注入,用PreparedStatement参数化查询替代字符串拼接SQL。我见过不少毕设代码里直接写"SELECT * FROM user WHERE username='" + username + "'",这是典型的安全漏洞。其次是密码存储,至少用MD5加盐处理,不能明文入库。答辩时主动提这两个点,能明显拉开和其他同学的差距。
如果后续要基于这套代码做二次开发,我建议你先花一天时间把客户端和服务端的网络请求统一管理起来:客户端封装统一的ApiClient,服务端封装统一的BaseServlet处理编码和JSON转换。可以再加个ResponseEntity统一包装返回结构,把code、message、data三个字段固定下来。这样以后每次新增功能,代码风格都能保持一致,不会再出现一个项目里三种网络请求写法的混乱局面。
我自己每次拿到这类毕业设计源码包,第一件事永远是先找数据库脚本和网络地址配置文件,把这两个东西搞定之后再读业务代码。在那之前不要动任何逻辑——环境跑不通,其他全是黑匣子。等你按照这套流程把项目完整走通一遍,再回头看这份源码,你会发现从App登录到预约落库的每一个环节都清清楚楚,“基于安卓AndroidStudio开发的智慧医疗医院预约挂号App”就不再只是一堆源代码,而是一个你随时能改、能讲、能扩展的实战底座。希望帮到你。
本文还有配套的精品资源,点击获取