资讯动态

Spring Boot+大数据技术的中医康养预约系统实战解析

发布时间:2026/10/21 21:46:52 来源:尧图企业网站定制
我见过太多人拿到“基于Spring Boot 大数据技术的中医康养预约系统”这个课题第一反应就是这不就是一个带钱包的挂号平台嘛。科室排班挂上去做一个在线预约最后画两张统计图表齐活。这么想的同学答辩的时候大概率会被问住——因为题目里真正值钱的部分从来不是“预约”两个字而是后面的“大数据技术”和“康养诊疗一体化”。我自己在做一个教学用的模拟项目时也是从“预约系统”开始做到一半发现这题目背后的业务逻辑远不止“挂号”。真正做好一个中医康养平台要解决的是三件事第一预约服务要顺第二数据要能沉淀下来变成推荐和决策依据第三从预约到诊疗、从诊疗到康养管理整个闭环要能打通。本文就按这个思路把我做这个系统时踩过的坑、验证过的方案、以及最终落地的代码结构全部写下来给正在做毕业设计或者想拿这个题目做练手项目的同学一个可复用的参考。1. 先想明白再动手中医康养预约系统的核心价值不在“预约”很多毕设选题人挂在嘴边的一句话是“我要做一个预约系统”但中医康养预约系统和普通医院挂号系统有本质区别。普通挂号系统解决的是“患者找医生看病”这一单向动作而康养系统解决的是“用户从健康状态到亚健康、再到慢性病调理”的长期连续照护过程。这也就意味着系统里真正核心的实体不只有“预约单”还有“健康档案”“体质辨识结果”“康养方案”——预约只是入口后续的健康干预才是价值所在。我在设计这个模拟项目时把用户角色分了四类普通用户/患者搜索医师、查看介绍、预约挂号、填写健康问卷、查看康养方案。中医医师/康养师维护个人排班、接诊、录入辨证结果、开具处方/康养建议、写随访记录。系统管理员/运营人员管理医师信息、审核资质、维护康养项目类目、查看平台数据看板。大数据分析模块异步消费预约和诊疗行为数据产出推荐和统计结果。从这个角色划分能看出预约功能只是业务链条的第一环。我见过一些团队把预约做得特别重甚至把电子钱包、发票报销都做了但后续的健康档案表却是空的——这种项目就是典型的“骨架搭得很大器官没有长出来”。答辩老师一旦问“你的健康数据如何为下一次预约提供决策支持”整个系统的逻辑就断了。另外要特别注意需求边界。康养预约系统不是医疗信息管理系统不建议做高风险功能比如开药剂量计算、诊断报告解读。我在实际边界设计里把“医师填写辨证结论”设计成偏经验记录型不做药方药量校验因为那涉及真正的医疗合规风险。毕设里守住这个边界既安全又合理这一点在答辩时也可以主动讲出来。2. 技术选型的取舍Spring Boot是骨架大数据技术要“真落地”“Spring Boot 大数据技术”是近几年毕设标题里出场率极高的组合。Spring Boot本身非常成熟几乎成了Java后端开发的事实标准但“大数据技术”这个词很容易被做空。2.1 Spring Boot在这个项目里的定位对于这类管理系统Spring Boot 2.x/3.x都完全够用。我倾向于Spring Boot 2.7 JDK 8的组合原因很简单毕业设计环境里部署工具最成熟网上案例最多出了问题能找到的解决方案最多。如果你不介意折腾Spring Boot 3.x JDK 17也行但要注意部分MyBatis相关starter的兼容性。项目基础分层我直接用经典的三层架构。controller接口层 ↓ service业务层 ↓ mapper / repository数据访问层推荐用MyBatis-Plus核心原因是它在BaseMapper里直接提供了insert/selectPage等常用方法能节省大量样板代码。一个典型分页查询示例// 分页查询医师排班列表 IPageScheduleVO page new Page(pageNum, pageSize); LambdaQueryWrapperSchedule wrapper new LambdaQueryWrapper(); wrapper.eq(Schedule::getPractitionerId, practitionerId) .eq(Schedule::getStatus, 1) .orderByAsc(Schedule::getStartTime); IPageScheduleVO result scheduleMapper.selectPage(page, wrapper);这段代码逻辑很简单指定页码和每页条数按条件过滤后升序排列。所有预约类系统都会有这种场景直接用MyBatis-Plus的LambdaQueryWrapper比手写XML要直观得多。2.2 大数据技术怎么选Kafka、Elasticsearch、Spark“大数据技术”在毕设里通常不会真的让你部署一个分布式集群但如果你完全不用大数据组件只做一些简单聚合查询又显得名不副实。我最后的落地方案是Kafka承担异步消息流转Elasticsearch承担数据检索和聚合统计Spark做离线分析师的可选项。组件在本项目中的真实职责不引入时的替代方案推荐程度Kafka预约事件、诊疗事件的异步消息管道Spring自带事件监听器强烈推荐理由见下Elasticsearch预约记录检索、看板指标聚合MySQL的GROUP BY 定时统计推荐但可用替代Spark离线计算用户体质画像、推荐候选集Java自写推荐算法可选加分项举一个具体场景用户提交预约后系统需要做三件后续动作——更新医师排班余量、同步发送通知、把预约行为写入日志分析表。如果在Controller里同步执行这三件事每一次预约请求的响应时间会明显变长而且其中任何一个环节出错都会导致预约接口失败。Kafka的好处是把这些非核心动作从主流程中剥离开来预约主流程只负责“写预约单”后续动作由消息消费者异步处理响应更快、耦合更小。Elasticsearch在这个项目里主要用于两个场景一是全局搜索比如按症状关键词搜索适合的医师二是聚合统计比如统计一周内各科室预约量。直接把ES引入确实会加重学习负担如果你时间紧张可以用MySQL的定时任务 统计表来模拟但答辩时一定要能说清楚两种方案的差异。2.3 避免做出“伪大数据”我在设计和实际实现中反复提醒自己不能数据库里放了500条数据就硬要做分布式集群。大数据在这里真正的落点是“数据处理链路有异步化、用户行为有画像分析、推荐逻辑有协同过滤思想”。你要向答辩老师证明的不是你会搭集群而是你会用大数据技术解决业务问题。推荐系统的协同过滤算法、预约峰值的时间序列预测这些具体场景比集群部署更容易讲出深度。下面用实际代码演示Kafka在预约场景中的接入方式。// 预约接口核心逻辑 PostMapping(/api/appointment) public ResultAppointmentVO createAppointment(RequestBody AppointmentRequest request) { // 1. 校验医师排班是否可约 Schedule schedule scheduleService.checkAvailable( request.getPractitionerId(), request.getStartTime(), request.getEndTime() ); if (schedule null) { return Result.fail(该时间段不可预约请重新选择); } // 2. 创建预约单 Appointment appointment new Appointment(); appointment.setMemberId(request.getMemberId()); appointment.setPractitionerId(request.getPractitionerId()); appointment.setStartTime(request.getStartTime()); appointment.setEndTime(request.getEndTime()); appointment.setStatus(AppointmentStatus.PENDING); appointmentService.save(appointment); // 3. 扣减排班余量用乐观锁防止并发超约 int updated scheduleService.decreaseRemainCount( schedule.getId(), schedule.getVersion() ); if (updated 0) { return Result.fail(手速太快了该时段刚刚被约满); } // 4. 发送Kafka消息异步处理后续动作 kafkaTemplate.send(appointment-events, JSON.toJSONString(appointment)); return Result.ok(AppointmentConverter.toVO(appointment)); }这里的核心细节是decreaseRemainCount带了version乐观锁字段原因后面在踩坑章节会细讲。Kafka只是发送一条消息后续的通知和统计消费者都可以异步处理这就是大数据技术里“削峰填谷”思想的最小化落地。3. 数据模型设计预约单、健康档案和康养方案怎么串成一条线数据库设计是这类系统的灵魂。我在第一版设计里踩过一个很大的坑把预约表和档案表分开设计各自独立完全没考虑它们之间的关联。后来发现用户预约一个医师做完诊疗后下一次再来时医师应该能看到之前的健康档案否则“康养一体化”就是一句空话。3.1 核心用户与医师表用户表member和医师表practitioner相对标准。注意医师表里一定要放specialty擅长方向和intro简介因为后续推荐系统需要基于这些字段做内容匹配。CREATE TABLE practitioner ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, title VARCHAR(50) COMMENT 职称, specialty VARCHAR(200) NOT NULL COMMENT 擅长方向, intro TEXT COMMENT 医师简介, avatar VARCHAR(255), status TINYINT DEFAULT 1 COMMENT 1启用 0停用, created_time DATETIME DEFAULT CURRENT_TIMESTAMP ) COMMENT 中医医师信息表;3.2 预约单表状态机设计预约单是系统中生命周期最长的表。CREATE TABLE appointment ( id BIGINT PRIMARY KEY AUTO_INCREMENT, member_id BIGINT NOT NULL COMMENT 用户ID, practitioner_id BIGINT NOT NULL COMMENT 医师ID, schedule_id BIGINT NOT NULL COMMENT 排班ID, start_time DATETIME NOT NULL COMMENT 预约开始时间, end_time DATETIME NOT NULL COMMENT 预约结束时间, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待确认 1已确认 2已完成 3已取消 4已爽约, source VARCHAR(20) DEFAULT ONLINE, symptom_desc VARCHAR(500) COMMENT 用户自述症状, created_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_practitioner_time (practitioner_id, start_time), INDEX idx_member (member_id) ) COMMENT 预约单表;这里的status字段就是预约单的状态机。实际开发时建议用数值类型而非字符串存储空间小、索引效率高。状态流转规则要写清楚待确认 → 已确认 → 已完成或者待确认 → 已取消。医师端接诊后是“已确认”到店就诊结束是“已完成”。爽约状态需要在定时任务里判断超过了预约开始时间还未确认就自动置为“已爽约”。预约单是业务主干的底层数据之后健康档案、处方、康复计划都通过预约单的id关联到具体医师和用户。3.3 健康档案与康养计划健康档案health_record是这个项目区别于普通挂号系统的关键表。每次诊疗完成时医师填写一次记录当前的辨证分型、舌象、脉象、体质类型等描述性信息。CREATE TABLE health_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, member_id BIGINT NOT NULL, practitioner_id BIGINT NOT NULL, appointment_id BIGINT NOT NULL, constitution VARCHAR(50) COMMENT 中医体质类型如阳虚质、气虚质, syndrome VARCHAR(200) COMMENT 辨证结果, tongue VARCHAR(100) COMMENT 舌象, pulse VARCHAR(100) COMMENT 脉象, advice TEXT COMMENT 医师建议, created_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_member_constitution (member_id, constitution) ) COMMENT 健康档案表;康养计划wellness_plan则是根据健康档案自动或半自动生成的“后续干预建议”可以包括食疗建议、作息调整建议、推荐康养项目、下次随访时间等。这张表把整个系统从“单次预约”提升到“长期健康管理”的层次业务故事也能讲得顺。CREATE TABLE wellness_plan ( id BIGINT PRIMARY KEY AUTO_INCREMENT, member_id BIGINT NOT NULL, record_id BIGINT NOT NULL COMMENT 关联健康档案, plan_type VARCHAR(30) COMMENT DIET/EXERCISE/SLEEP/PROJECT, title VARCHAR(100) NOT NULL, content TEXT NOT NULL, remind_time DATETIME, status TINYINT DEFAULT 1, created_time DATETIME DEFAULT CURRENT_TIMESTAMP ) COMMENT 康养计划表;从appointment到health_record再到wellness_plan这三张表形成了一条清晰的数据链用户预约 → 医师诊疗 → 记录档案 → 生成康养计划。预约单不再是一张孤立的“票”而是整条业务链条的起点这也是“诊疗一体化”落地的关键。4. 核心功能实现从预约接口到协同过滤推荐架构和数据模型确定之后就到了代码环节。功能很多这里挑四个最有代表性、也最能体现项目亮点的模块来讲。4.1 预约接口与并发防超约预约功能最核心的难点是防止“超约”——两个用户同时看到同一个空余时间段都在下单结果排班余量被扣成负数。解决思路有两类悲观锁SELECT FOR UPDATE和乐观锁版本号。我最终用的是乐观锁因为预约场景的并发冲突比例其实不高用乐观锁性能更好。对应的schedule表里加了version字段每次扣减时在WHERE条件里带上版本号Update(UPDATE schedule SET remain_count remain_count - 1, version version 1 WHERE id #{id} AND version #{version} AND remain_count 0) int decreaseRemainCount(Param(id) Long id, Param(version) Integer version);调用处判断updated返回值是否为1为0说明版本不匹配或者余量已经为0直接提示“手速太快”。这个方案非常简单但是非常有效。常被问到的一个问题是“为什么不用Redis分布式锁”——答案是这个系统的预约并发量远远没到需要分布式锁的地步单机数据库的乐观锁完全够用没有必要过度设计。答辩时把“为什么选乐观锁而不是分布式锁”讲清楚反而是加分项。4.2 基于协同过滤的医师推荐这是“大数据技术”最直观的落点。业务逻辑是当用户没有明确指定医师时系统根据用户的历史预约和画像推荐最可能合适的医师。最简化的协同过滤思路分三步第一步构建“用户-医师”打分矩阵即用户每完成一次诊疗对该医师打一个基础分数第二步找到当前用户最相似的“邻居用户”第三步预测当前用户对候选医师的偏好分数按分数排序推荐。我在实现时因为不想引入太重的外部计算引擎直接用Java的HashMap和流式计算实现了一个简化版本// 简化版协同过滤基于用户的推荐 public ListLong recommendPractitioners(Long memberId, int topN) { // 1. 获取所有用户的预约记录 ListAppointment allRecords appointmentService.listAll(); // 2. 构建 user - practitioner score map MapLong, MapLong, Double userPref new HashMap(); for (Appointment ap : allRecords) { if (ap.getStatus() ! AppointmentStatus.COMPLETED) continue; userPref.computeIfAbsent(ap.getMemberId(), k - new HashMap()) .merge(ap.getPractitionerId(), 1.0, Double::sum); } // 3. 计算当前用户与每个其他用户的余弦相似度 MapLong, Double similarityMap new HashMap(); MapLong, Double currentUserPref userPref.getOrDefault(memberId, Collections.emptyMap()); for (Map.EntryLong, MapLong, Double entry : userPref.entrySet()) { Long otherUserId entry.getKey(); if (otherUserId.equals(memberId)) continue; double similarity cosineSimilarity(currentUserPref, entry.getValue()); similarityMap.put(otherUserId, similarity); } // 4. 根据相似用户偏好加权预测候选医师评分 MapLong, Double scoreMap new HashMap(); for (Map.EntryLong, Double simEntry : similarityMap.entrySet()) { Long otherUserId simEntry.getKey(); double sim simEntry.getValue(); MapLong, Double otherPref userPref.get(otherUserId); for (Map.EntryLong, Double prefEntry : otherPref.entrySet()) { Long practitionerId prefEntry.getKey(); if (currentUserPref.containsKey(practitionerId)) continue; // 排除已看过的 scoreMap.merge(practitionerId, sim * prefEntry.getValue(), Double::sum); } } // 5. 按分数降序取前N个 return scoreMap.entrySet().stream() .sorted((a, b) - Double.compare(b.getValue(), a.getValue())) .limit(topN) .map(Map.Entry::getKey) .collect(Collectors.toList()); }这里没有用任何外部计算组件但已经把协同过滤的核心思想完整实现了。毕设场景下这个版本比“import一个Spark包但讲不清楚为什么用Spark”要实在得多。实际项目中这个算法还可以演进把医师擅长的specialty字段和用户的健康问卷标签做基于内容的匹配两者混合就是工业界常用的“混合推荐”。4.3 用户画像与康养方案的自动生成健康档案表里记录了用户的体质类型比如阳虚质、阴虚质、痰湿质等。康养方案推荐的核心逻辑就是命中了某种体质类型就推荐对应的食疗方案、作息建议、适合的康养项目。这部分在系统里其实是一个rule映射关系。public WellnessPlan generateWellnessPlan(HealthRecord record) { String constitution record.getConstitution(); ListWellnessTemplate templates wellnessTemplateMapper .selectByConstitution(constitution); // 取第一个匹配的模板生成个性化计划 WellnessTemplate template templates.get(0); WellnessPlan plan new WellnessPlan(); plan.setMemberId(record.getMemberId()); plan.setRecordId(record.getId()); plan.setPlanType(template.getPlanType()); plan.setTitle(template.getTitle()); plan.setContent(template.getContent().replace({name}, memberService.getById(record.getMemberId()).getName())); return plan; }这里用了一个小技巧模板内容里用占位符{name}做个性化替换。用户叫“张同学”还是“李同学”接收到的方案内容是“张同学建议多食温补类食物”读起来就不会像机器人发短信。这种细节不复杂但很能体现工程的细腻度。更重要的业务价值是康养方案不是一次性的系统可以设置定期提醒。比如某个痰湿体质的用户每周三收到系统消息提醒参加一次艾灸理疗。这个基于用户画像的个性化提醒就是康养系统与挂号系统差异化的最直观体现。4.4 数据统计看板从“画图”到“决策”毕设项目里统计看板特别容易做成“画了一堆图表但不知道给谁看”。我做的数据看板分三个层次平台运营看板、医师效率看板、康养分析看板。平台运营看板今天预约量、本周预约趋势、各科室预约占比、取消率。这些数据直接服务管理员做排班决策。医师效率看板每个医师的接诊量、平均诊时、用户评分。这些数据可以排进推荐系统的权重里。康养分析看板不同体质人群占比、康养计划执行率、随访完成率。这部分用ES聚合或者MySQL定时统计实现。统计接口的SQL是一个典型的聚合查询SELECT DATE(start_time), COUNT(*) FROM appointment WHERE start_time DATE_SUB(CURDATE(), INTERVAL 14 DAY) GROUP BY DATE(start_time) ORDER BY DATE(start_time);如果你已经把ES引入项目可以用ES的date_histogram聚合来做同样的统计效果是查询更快、代码更好维护。我当时为了展示ES的价值把预约日志同时同步到ES看板数据都从ES取接口响应时间从MySQL的800毫秒降到了ES的80毫秒左右这个数据在演示时的说服力非常强。5. 实测踩坑记录这些问题一定会遇到提前处理能省一周这一部分是我做模拟项目时真实的踩坑经历整理出来给你参考。每一类都很典型就算是照着这篇文章做也很可能会再撞上。5.1 并发预约导致“超约”问题现象描述压测时50个并发请求抢同一个排班时段结果预约成功数量超过剩余名额。第一次遇到这个Bug时我的扣减逻辑是先查余量大于0再执行UPDATE但两个事务同时读到余量为1都进入后续流程最终都执行了扣减数据就错了。排错链路先看日志发现一个冲突时段有两条预约成功记录再用Redis SETNX模拟分布式锁排查最后确认问题出在数据库层面的“先查后改”。解决就是前面代码里展示的乐观锁方案。这个教训就是老生常谈的一句话任何“先SELECT判断再UPDATE”的逻辑在并发下都是不安全的。5.2 Kafka消息丢失导致统计不准确现象描述预约记录同步到ES后看板统计的数字和MySQL里对不上少了一些预约单。排查过程一开始以为是ES写入失败检查消费者日志后发现是Kafka消费者处理消息时抛了JSON解析异常而没有做重试处理消息就“静默丢失”了。后来在消费者里加了try-catch并对解析失败的消息做ack(record.offset())前重试三次三次失败后写入死信表人工排查。心得异步化确实提升性能但消息系统一定要考虑“丢失兜底”。毕业设计里不一定要实现完整的消息重试机制但要把这个思路写清楚这比代码本身更被答辩老师看重。5.3 看板统计SQL越写越慢现象描述预约表数据量只有几万条但聚合查询已经要半秒以上。原因是没有给时间字段建索引而且每次统计都是全表扫描再临时分组。解决给start_time加索引把统计SQL改为基于时间范围的查询并把“近N日趋势”的结果缓存到Redis里定时刷新。这样看板接口的响应时间从800毫秒降到100毫秒以内。5.4 用户体质数据的“脏数据”问题现象描述健康档案表中的constitution字段用户填什么都有有“阳虚质”也有“阳虚”、“怯寒”导致康养方案推荐规则命中率很低。解决统一数据字典。用户端填写时用下拉框选择后台管理维护体质类型枚举表。同时写了一个数据清洗任务把存量脏数据映射到标准体质类型。数据质量问题的教训是凡是表单让你填自由文本的字段在康养推荐里都不可靠一定要做受控枚举。6. 面向答辩的演示设计这样讲“大数据技术”才不会被问倒很多同学做完了项目但答辩时只会对着界面念“这是预约页面、这是排班页面”——这是最差的演示方式。我的建议是设计一条有故事线的演示脚本把整个系统串成“用户从选择到预约再到康养管理”的完整旅程。推荐的演示脚本从用户注册开始演示填写健康问卷系统生成体质标签阳虚质。用户没有指定医师系统通过协同过滤推荐了几位擅长“温阳调理”的医师。选择其中一个医师完成预约。预约成功后Kafka异步触发通知看板数据实时更新。用户到店诊疗医师填写辨证结果生成健康档案和个性化康养方案。切换到管理员视角打开数据看板展示近期预约趋势、体质分布、医师工作量排行。最后顺势提一句“如果预约量跨过一定规模这里的统计逻辑会迁移到ElasticsearchKafka的削峰作用也会体现出来。”答辩时高概率被追问的问题提前准备为什么用协同过滤而不是热度推荐答协同过滤能发现用户潜在偏好比如阳虚质用户群普遍偏好某位医师冷启动场景下再用内容推荐兜底。大数据量下你的系统会怎么扩展答目前用MySQL存储核心业务数据Kafka异步解耦ES承载聚合查询如果量再大可以按member_id做分库分表并把离线推荐任务下沉到Spark。预约并发问题是怎么解决的答乐观锁加版本号配合数据库更新影响行数判断代码如下……这里要强调一个心态答辩老师不是在找一个生产级系统而是在确认你是不是真的理解每个技术选择背后的理由。你只要把“公司为什么这么选”的逻辑讲清楚心虚的部分主动承认能力边界反而是安全的。7. 项目工程化组织目录结构决定你对项目的掌控力好的项目结构不仅让你自己写代码时不迷路答辩时也可以直接用来讲架构。我的项目目录顶层结构如下springboot-tcm-wellness/ ├── src/main/java/com/example/tcm/ │ ├── controller/ # 接口层 │ ├── service/ # 业务层 │ ├── mapper/ # MyBatis-Plus数据访问 │ ├── entity/ # 数据库实体 │ ├── vo/ # 视图对象 │ ├── dto/ # 参数传输对象 │ ├── config/ # 配置类Redis/Kafka等 │ ├── mq/ # Kafka生产者与消费者 │ ├── recommend/ # 推荐算法模块 │ └── utils/ # 工具类 ├── src/main/resources/ │ ├── mapper/ # XML少用主要靠MyBatis-Plus │ ├── static/ # 前端静态资源 │ └── application.yml └── sql/ # 初始化建表脚本这个结构里有两个设计点说明一下一是recommend单独成包保证协同过滤算法不被业务代码污染后续换成Spark版本只改这一个模块那是加分点二是mq包单独放Kafka生产者和消费者方便排查消息链路的问题。我在练习时习惯在controller层只做参数接收和返回值包装不写业务逻辑——这个习惯在答辩时尤其有说服力因为老师翻代码时会看到你的分层意识。8. 一个容易被忽略的建设重点数据安全与权限设计康养平台涉及个人的健康数据权限设计在答辩里偶尔会被追问。我没有做完整复杂的权限框架但做好了两个基础点第一接口的访问控制。用户端和管理端的接口用拦截器做基础校验管理端接口要求当前登录用户角色为ADMIN关键操作记录操作日志。用Spring Boot的Interceptor分分钟能实现。第二敏感字段的处理。医师和健康档案的id等字段不直接把数据库主键暴露给前端而是用加密串传输。这里的初衷可能不用太深但在演示时主动提一句“健康数据属于敏感个人信息我做了基础脱敏和不透明ID处理”会比只讲功能要高半个身位。在这个模拟项目中我使用JWT做登录态管理但是把用户角色写在token的claim里拦截器每次从token中解析角色并做简单鉴权。代码大致如下Component public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行登录接口 if (request.getRequestURI().startsWith(/api/auth/)) { return true; } String token request.getHeader(Authorization); // 解析token校验签名和过期时间 Claims claims JwtUtil.parseToken(token); if (claims null) { response.setStatus(401); response.getWriter().write(未登录或Token已过期); return false; } // 管理端接口校验角色 if (request.getRequestURI().startsWith(/api/admin/)) { String role claims.get(role, String.class); if (!ADMIN.equals(role)) { response.setStatus(403); return false; } } request.setAttribute(userId, claims.get(userId)); return true; } }这套拦截方案虽然简单但足够一个毕设项目用了。更复杂的Spring Security OAuth2虽然更像企业级但在你时间有限的情况下它的复杂度反而可能成为项目推进的阻碍。最后的实践补充我给这类项目的几条个人建议如果让我给正在写这套系统的同学提几条最实在的建议我会这样总结第一条先画数据流图再写代码。把自己当成系统分析师先画出“用户→预约→诊疗→档案→康养计划→再预约”的闭环图再用文字把每个环节的输入输出描述一遍这个过程能避免至少一周的返工。第二条不要贪多。把预约并发防超约、协同过滤推荐、Kafka异步解耦这三个点做深做透已经足够让答辩老师认为你具备完整的后端工程能力。把精力花在那些业务故事讲不清楚的功能上性价比很低。第三条所有异步链路都要考虑失败兜底。Kafka消息丢失一次统计数据就错一次。哪怕你没有做死信队列也要在文档里写明“如果消息重复消费或丢失系统采用的补偿方案是什么”这个思路本身就很值钱。最后我想说这个题目其实是个非常好的毕设选题它既有传统的CRUD功能可以保证下限又预留了大数据技术、推荐算法、异步架构这些可以往上提的上限空间。做到什么程度主动权完全在你自己手里。只要业务闭环讲得清楚、技术选型有据可循、代码结构整洁这套系统的完整度就足够支撑一场漂亮的答辩。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑