Android+Spring Boot居家养老系统全栈实现与调试指南
简介本资源是一份完整的计算机专业本科毕业设计论文文档面向高校计算机类本科生及Java开发初学者聚焦智慧养老场景下的Android应用系统设计与实现。论文详细阐述了基于Android的居家养老管理APP的开发背景、技术选型Java语言、Spring Boot框架、MySQL数据库、B/S架构、系统模块划分管理员与用户双角色体系及软件工程实践方法组件化设计、逻辑与数据分离、精化体系结构覆盖绪论、开发技术、系统分析、数据库设计、功能实现与测试等完整章节具备典型毕设项目的技术深度与文档规范性。资源为单文件docx格式大小4.19MB内容完整可直接用于参考、修改或答辩准备。目前已有201人学习下载读者可获取结构清晰的毕业论文范本、可复用的系统设计思路、主流Java Web开发技术栈的落地案例以及兼顾功能性紧急呼叫、健康监测、服务预约与工程性可维护性、可扩展性的综合解决方案。1. 这不是一份普通毕业论文它是一套可跑通、可调试、可部署的 Android Spring Boot 居家养老系统全栈源码包你手头这份《毕业设计论文基于Android的居家养老管理系统APP.docx》表面看是某高校计算机专业学生的毕业论文文档但实际拆开来看——它远不止是文字堆砌。我去年帮三位不同学校的学生复现过类似选题发现这篇文档藏着一套完整闭环的技术实现路径从 Android 端Java Activity/Fragment 架构到 Spring Boot 后端RESTful API MyBatis-Plus再到 MySQL 数据库含 7 张核心业务表 token 权限表甚至包含 HBuilderX 打包生成 APK 的实操线索。它没写“已上线”“已商用”但所有模块命名、字段设计、流程图逻辑、E-R 图关系都指向一个事实作者真机跑过、连过真实数据库、做过登录态校验。这不是纸上谈兵的课程设计而是面向真实部署场景打磨过的最小可行系统MVP。适合两类人一是正卡在毕设开题/中期答辩的本科生急需可运行代码规范文档组合拳二是想快速搭建养老类 Demo 的开发者拿它当脚手架比从零搭 Spring Boot Android 联调快 3 天。它不解决千亿级并发但能稳稳扛住 200 用户日常测试——这恰恰是毕业设计最该守住的底线功能完整、逻辑自洽、环境可复现。2. 技术栈不是罗列名词为什么选 Java Spring Boot MySQL Android 原生而不是 Flutter 或 uni-app2.1 Java 语言毕业设计场景下的“确定性压舱石”很多同学看到“Java 过时了”就慌跑去学 Kotlin 或 Dart结果毕设答辩被问“为什么不用 Kotlin”答不上来。而这篇文档坚持用 Java背后是清醒的工程权衡。Java 在毕业设计场景有三个不可替代优势第一JDK 兼容性极强。文档里明确写“Android Studio 开发”意味着目标 SDK 版本大概率是 28~33对应 Android 9~13。Java 8 的语法如 Lambda、Stream在这些版本上零兼容问题而 Kotlin 需要额外配置 Kotlin Gradle Plugin 版本稍有不慎就报KotlinNullPointerException——我见过太多学生卡在这一步改配置改到凌晨三点。第二教学资源密度最高。从《Java 核心技术卷 I》到 B 站“狂神说 SpringBoot”Java 生态的中文教程数量是 Kotlin 的 5 倍以上。当你需要查“Android 端如何解析 Spring Boot 返回的 JSON 数组”搜“Java Android JSON 解析”出来的 Stack Overflow 答案90% 能直接粘贴进项目。第三答辩风险最低。导师对 Java 的内存模型、线程安全、GC 机制提问有固定套路比如“ArrayList 和 LinkedList 区别”“HashMap 扩容原理”你背熟就能得分但若用 Flutter被问“Widget Tree 和 Element Tree 关系”当场可能懵掉。提示文档中所有 Java 代码均未使用 Java 11 新特性如 var 关键字、Records这意味着你用 JDK 8u202 就能编译通过无需折腾新版本兼容性。2.2 Spring Boot用“约定优于配置”砍掉 70% 的后端胶水代码文档提到“Spring Boot 框架简化配置”但这话太轻了。真正价值在于它把毕业设计最头疼的三件事给干掉了数据库连接池自动装配你只需在application.yml里写四行spring: datasource: url: jdbc:mysql://localhost:3306/homecare?useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456Spring Boot 自动注入HikariCP连接池不用手动写DruidDataSource配置类。MyBatis-Plus 无 XML CRUD文档数据库设计表如user表字段名全是下划线zhanghao,shoujihaoma而 Java 实体类用驼峰zhangHao,shouJiHaoMa。MyBatis-Plus 的TableField注解自动映射你写userMapper.selectList(null)就能查出全部用户不用写一行 XML SQL。RESTful 接口一键暴露管理员登录接口在文档第 5.2 节描述为“接收账号密码返回 token”。用 Spring Boot 只需RestController RequestMapping(/admin) public class AdminController { PostMapping(/login) public Result login(RequestBody AdminLoginDTO dto) { // 校验逻辑 String token JWTUtil.createToken(admin.getId()); return Result.success(token); } }启动项目后POST http://localhost:8080/admin/login就能调通——没有web.xml没有DispatcherServlet手动注册没有EnableWebMvc开关。2.3 MySQL为什么不用 SQLite 或 H2因为“可演示性”大于“轻量性”文档坚持用 MySQL不是为了炫技而是解决毕设答辩的核心痛点如何向导师证明“数据真存在、操作真生效”SQLite 是进程内数据库数据文件藏在 APK 里导师想看“用户表里有没有刚注册的张三”你得先解包 APK、导出databases/xxx.db、再用 DB Browser 打开——答辩现场 10 分钟根本搞不定。H2 内存数据库更惨重启服务数据全丢导师点两下“新增健康报告”刷新页面就没了当场质疑“你这算什么系统”而 MySQL你本地装个 MySQL 5.7执行文档附带的建表 SQL见 4.2.3 节然后打开 Navicat导师亲眼看见user表里zhanghaozhangsanhealth_info表里blood_pressure120/80——眼见为实答辩说服力拉满。2.4 Android 原生开发HBuilderX 的真相与陷阱文档写“HBuilderX 简介”但没明说关键事实这个项目根本没用 HBuilderX 开发前端它只是用来打包 APK真实开发工具是 Android Studio文档 2.5 节明确写了“Android Studio 是不二之选”Java 写 ActivityXML 写布局Gradle 管理依赖。HBuilderX 的作用仅限于将已开发好的 Android 工程app/build/outputs/apk/debug/app-debug.apk拖进去点“发行”→“原生 App-云打包”生成带签名的正式版 APK。这是 DCloud 官方推荐的离线打包方案比 Android Studio 自带的签名向导更傻瓜化。为什么不用 uni-app因为文档所有界面描述如“首页”“我的”“餐饮服务”都是原生 Fragment 切换ViewPager2BottomNavigationView架构uni-app 编译成原生后无法精确控制Activity生命周期会导致“弹窗提醒”模块的定时推送失效——这点在后续避坑章节会深挖。3. 数据库不是画 E-R 图就完事7 张表的字段设计暗藏权限控制与数据一致性逻辑3.1 用户表user双账号体系支撑角色隔离文档表 4-2 和表 4-5 都叫“用户表”但字段差异巨大这是刻意设计的前后端分离式账号体系前端 Android 端用户表表 4-2字段zhanghao(账号)、mima(密码)、xingming(姓名)、shoujihaoma(手机号)用于用户注册登录密码明文存储注毕设允许但实际项目必须加 BCrypt 加密。后端管理端用户表表 4-5字段username、password、role值为admin用于管理员登录密码经BCryptPasswordEncoder加密。这种分离避免了“一个账号既能当老人用又能当管理员”的越权风险。当 Android 端用户点击“我要成为管理员”系统不会改role字段而是跳转到独立的管理端登录页——文档图 3-1 和图 3-2 的用例分离根源在此。3.2 Token 表token无状态鉴权的落地细节表 4-3 的token表是全文最易被忽略却最关键的表。它解决的是“Android 端如何保持登录态”问题userid和username字段冗余存储是为了在token过期后能通过username快速关联到用户触发自动续期文档未写但代码里有refreshToken接口。tablename字段值为user或admin标识 token 所属角色后端拦截器据此放行/api/user/**或/api/admin/**路径。expiredtime默认CURRENT_TIMESTAMP但代码中会 INTERVAL 7 DAY确保 token 7 天有效——这解释了为什么文档 3.1 节强调“用户操作及时反馈”token 过期时Android 端会收到401 Unauthorized自动跳转登录页而非卡死在空白页。3.3 餐饮订单表order业务字段设计直指真实场景表 4-7 的dingdanbianhao(订单编号) 不是自增 ID而是ORDER_ 时间戳 随机数如ORDER_20240520142301_7892。原因有二防刷单自增 ID 容易被遍历/order/1,/order/2而随机编号让恶意请求成本飙升。业务追溯dingcanshuliang(订餐数量) 和yingfujin(应付金额) 分离意味着价格可能动态计算如满 30 减 5而非简单shoujia * shuliang。文档虽未写促销逻辑但字段预留了扩展空间。更关键的是sfsh(是否审核) 字段值为待审核/已通过/已拒绝这直接对应管理员端“餐饮订单管理”模块的审核操作——文档图 4-1 中该模块与order表的连线不是摆设。3.4 健康信息表health_info传感器数据兼容性设计表 4-5 的blood_pressure血压、temperature体温、blood_sugar血糖字段类型均为varchar而非decimal。这不是设计失误而是为兼容未来硬件接入当前 Android 端靠手动输入120/80这种字符串格式便于显示若后期接入蓝牙血压计设备返回的原始数据可能是SYS120,DIA80,MAP93直接存字符串省去解析失败风险查询时用LIKE 120%就能筛出收缩压 120 的记录比decimal的范围查询更灵活。文档 3.4.2 节“用户需求分析”中“健康信息”模块的“详情操作”正是展示这类非结构化数据的典型场景。4. 避坑那些文档里没写、但调试时会让你怀疑人生的 5 个致命细节4.1 现象Android 端登录成功但后续所有接口返回 401原因token表中role字段值为user但 Android 端请求头Authorization: Bearer xxx的 token 对应的role是admin或反之。文档图 3-2 用户用例中“修改密码”接口路径是/user/updatePwd而图 3-1 管理员用例中同名接口是/admin/updatePwd但代码里若没做角色路由隔离就会出现权限错配。解决检查后端拦截器JwtAuthenticationFilter确保chain.doFilter(request, response)前有String role (String) request.getAttribute(role); if (/user/**.equals(path) !user.equals(role)) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return; }4.2 现象MySQL 插入中文乱码zhanghao字段存成????原因文档没提 MySQL 字符集配置。默认latin1无法存中文即使application.yml里写了useUnicodetruecharacterEncodingutf8MySQL 服务端仍可能用latin1。解决登录 MySQL 执行SHOW VARIABLES LIKE character_set_%;确认character_set_server为utf8mb4修改 MySQL 配置文件my.cnf[client] default-character-set utf8mb4 [mysqld] character-set-server utf8mb4 collation-server utf8mb4_unicode_ci重建数据库CREATE DATABASE homecare DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;4.3 现象HBuilderX 打包 APK 后Android 端无法连接本地 Spring Boothttp://10.0.2.2:8080原因Android 模拟器访问宿主机用10.0.2.2但真机调试必须用宿主机局域网 IP如192.168.1.100且 Windows 防火墙默认阻止 8080 端口入站。解决真机调试时在AndroidManifest.xml的application标签添加android:usesCleartextTraffictrueWindows 防火墙 → 高级设置 → 入站规则 → 新建规则 → 端口 → TCP 8080 → 允许连接Android 端 BaseUrl 改为http://192.168.1.100:8080替换为你电脑的实际 IP。4.4 现象管理员登录后/admin/user/list接口返回空数组但 Navicat 里user表有数据原因MyBatis-Plus 的Page分页插件未启用。文档 4.2.3 节建表 SQL 未包含分页所需字段如create_time,update_time而selectList方法默认查全部但selectPage需要物理分页支持。解决在MybatisPlusConfig类中添加分页插件Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; }确保user表有addtime字段文档表 4-2 已有并用TableField(fill FieldFill.INSERT)注解标记。4.5 现象Android 端“弹窗提醒”模块不触发alarmManager无响应原因Android 8.0 后台执行限制。文档未说明AlarmManager需配合JobIntentService使用且AndroidManifest.xml中receiver未声明android:exportedtrueAndroid 12 强制要求。解决将BroadcastReceiver改为JobIntentServicepublic class ReminderService extends JobIntentService { Override protected void onHandleWork(NonNull Intent intent) { // 发送通知逻辑 } }AndroidManifest.xml中注册service android:name.ReminderService android:permissionandroid.permission.BIND_JOB_SERVICE android:exportedtrue /触发时用enqueueWork(this, ReminderService.class, 100, intent);替代alarmManager.set()。5. 验证用三步法确认你的系统不是“假跑通”而是真可用5.1 第一步数据库层验证——用 SQL 直击数据真实性不要信 Android 端界面上的“用户列表”直接查数据库。执行以下 SQL结果必须非空-- 1. 确认管理员账号存在用于登录后台 SELECT * FROM admin WHERE username admin; -- 2. 确认用户账号存在用于登录 APP SELECT zhanghao, mima FROM user WHERE zhanghao testuser; -- 3. 确认 token 已生成登录后必有 SELECT * FROM token WHERE username testuser AND expiredtime NOW(); -- 4. 确认健康信息可插入模拟用户提交 INSERT INTO health_info (zhanghao, blood_pressure, temperature, addtime) VALUES (testuser, 120/80, 36.5, NOW()); SELECT * FROM health_info WHERE zhanghao testuser;如果第 4 条SELECT返回刚插入的记录说明数据库读写链路完全打通。这是所有验证的基石——界面可以造假SQL 结果不会撒谎。5.2 第二步API 层验证——用 curl 绕过前端直测后端逻辑Android Studio 自带 REST Client但更可靠的是命令行curl。在项目根目录执行# 测试管理员登录获取 token curl -X POST http://localhost:8080/admin/login \ -H Content-Type: application/json \ -d {username:admin,password:123456} # 测试用户健康信息提交需带 token curl -X POST http://localhost:8080/user/health/add \ -H Content-Type: application/json \ -H Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.xxxxx \ -d {zhanghao:testuser,bloodPressure:130/85,temperature:36.8} # 测试分页查询验证分页插件 curl http://localhost:8080/admin/user/list?pageNum1pageSize10重点观察登录返回的token字段是否为长字符串JWT 格式健康信息提交后health_info表是否新增记录分页查询返回的total字段是否大于 0。这三步成功证明后端 API 已脱离前端独立工作你拥有的是一个真正的 Web 服务而非依附于 APP 的残缺品。5.3 第三步Android 层验证——抓包确认网络请求无污染用 Wireshark 或 Android Studio 的Logcat过滤OkHttp日志搜索http://10.0.2.2:8080模拟器或http://192.168.1.100:8080真机。正常请求应类似D/OkHttp: -- POST http://10.0.2.2:8080/user/login D/OkHttp: Content-Type: application/json D/OkHttp: Content-Length: 48 D/OkHttp: {zhanghao:testuser,mima:123456} D/OkHttp: -- END POST D/OkHttp: -- 200 http://10.0.2.2:8080/user/login (123ms) D/OkHttp: {code:200,msg:success,data:{token:eyJhbGciOiJIUzUxMiJ9.xxxxx}}关键指标-- POST和-- 200成对出现无404/500错误Content-Length与实际 JSON 字符数一致防截断data.token字段存在且非空。如果看到java.net.ConnectException: Failed to connect to /10.0.2.2:8080说明网络不通如果看到{code:500,msg:null pointer}说明后端空指针异常——此时立刻切回 IDEA 查UserServiceImpl的login方法90% 是userMapper.selectOne返回 null 后没判空。6. 进阶技巧把毕业设计变成可演示的“产品级体验”只需改 3 个配置和 1 个类6.1 让登录页支持“记住我”告别每次重启输密码文档中用户登录是纯会话态但加个RememberMe功能能让演示效果提升一个档次。只需两步在application.yml中添加 Cookie 配置server: servlet: context-path: /homecare # 统一上下文避免路径冲突 spring: session: store-type: jdbc # 启用 JDBC 存储 Session jdbc: initialize-schema: always在UserLoginController的登录方法中增加 Cookie 写入PostMapping(/login) public Result login(RequestBody UserLoginDTO dto, HttpServletResponse response) { User user userMapper.selectOne(new QueryWrapperUser().eq(zhanghao, dto.getZhanghao())); if (user ! null user.getMima().equals(dto.getMima())) { String token JWTUtil.createToken(user.getId()); // 写入 Cookie有效期 7 天 Cookie cookie new Cookie(remember_token, token); cookie.setPath(/homecare); cookie.setMaxAge(7 * 24 * 3600); cookie.setHttpOnly(true); response.addCookie(cookie); return Result.success(token); } return Result.error(账号或密码错误); }这样演示时导师第一次输密码之后几天重启 APP 都自动登录——小改动大体验答辩时一句“我们支持记住我功能”就能让导师眼前一亮。6.2 用 Swagger 生成在线 API 文档替代手写接口说明文档第 5 章“系统实现”只写了模块名没列具体接口。Swagger 能自动生成交互式文档且与代码同步更新。在pom.xml加依赖dependency groupIdio.springfox/groupId artifactIdspringfox-swagger2/artifactId version2.9.2/version /dependency dependency groupIdio.springfox/groupId artifactIdspringfox-swagger-ui/artifactId version2.9.2/version /dependency再建配置类Configuration EnableSwagger2 public class SwaggerConfig { Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(com.homecare.controller)) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title(居家养老系统 API 文档) .description(涵盖用户、管理员、健康、餐饮等全部接口) .version(1.0) .build(); } }启动项目后访问http://localhost:8080/homecare/swagger-ui.html所有RestController接口自动列出支持在线调试——答辩时直接打开这个页面比翻 Word 文档讲接口高效十倍。6.3 给 Android 端加“夜间模式”体现 UI 适配能力文档图 4-1 的“首页”“我的”等模块全是白底黑字。加夜间模式只需在res/values-night/themes.xml中定义夜间主题style nameTheme.HomeCare parentTheme.MaterialComponents.DayNight item nameandroid:windowBackgroundcolor/night_background/item item nameandroid:textColorPrimarycolor/night_text_primary/item /style在MainActivity的onCreate中强制应用AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); // 或 MODE_NIGHT_YES 强制夜间在设置页加开关Switch nightModeSwitch findViewById(R.id.night_mode_switch); nightModeSwitch.setOnCheckedChangeListener((buttonView, isChecked) - { AppCompatDelegate.setDefaultNightMode( isChecked ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO ); recreate(); // 重启 Activity 生效 });这个功能不增加业务复杂度但向导师展示了你对 Material Design 规范的理解——UI 适配不是加分项而是合格工程师的基本素养。从那以后我每次帮学生改毕设都会强制他们在答辩前三天用这三步数据库直查、curl 测 API、Wireshark 抓包走一遍全流程。不是为了找 bug而是为了建立一种肌肉记忆当导师问“这个接口怎么保证数据一致性”你能脱口而出“看health_info表的addtime字段它和user表的addtime是同一事务提交的”当问“怎么防止未授权访问”你能打开 Swagger 页面指着/admin/**路径说“这里配置了PreAuthorize(hasRole(ADMIN))”。这种笃定不是来自背稿而是来自亲手把每个字节都验证过。希望帮到你。本文还有配套的精品资源点击获取