ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于Spring Boot的中医学习服务管理系统开发实战详解

基于Spring Boot的中医学习服务管理系统开发实战详解 每年毕业季总有同学拿着类似“XX管理系统”的题目一脸迷茫跑来问我这到底该怎么做、能做什么。今天这个题目就是典型——《基于Spring Boot的中医学习服务管理系统》。第一次看到它很多人会误以为要做一个能辨证论治的中医辅助诊疗系统实际完全不是这么回事。它本质上是一个基于Spring Boot的主流Java Web管理系统业务对象换成了中医学习资源与学习过程服务。这种题适合计算机科学与技术、软件工程等专业的学生做毕业设计也适合刚工作没多久的后端开发者拿来找练手场景。它的核心价值在于覆盖了从需求分析、数据库设计、接口开发到前端联调、打包部署的完整Web开发链路做完之后你对Spring Boot全家桶的理解会扎实很多。我接触过不少类似的项目也帮人排查过不少“能跑但不知道在跑什么”的代码。感觉这种题目最大的问题不是技术难而是需求边界容易失控有人把它想成医疗系统有人把它做成普通CMS。今天这篇文章我就以“中医学习服务管理系统”为例把从题目解读、功能设计、技术选型、数据库设计到核心业务落地、常见问题排查的完整思路拆一遍也把我在实操中踩过的坑一并列出来希望能帮你少走几段弯路。1. 项目定位与功能需求拆解1.1 这个题目真正要解决什么问题毕设选题的成败首先取决于你对题目的理解是否准确。中医学习服务管理系统重点词不是“中医”而是“学习服务管理”。它要解决的是这样一个场景中医爱好者、中医药院校学生甚至部分基层从业者面对海量的中医知识普遍缺乏一条清晰的学习路径。方剂、穴位、药材、经典条文散落在不同地方学了就忘、没有反馈、没有计划所以需要一个系统把内容组织起来把学习过程管理起来。简单说它更接近“在线学习平台”加“知识管理后台”的结合体而不是门诊挂号、病历管理那套医疗信息化系统。想明白这一点边界立刻清晰了核心要做的是内容资源的组织、学习计划的推进、学习行为的记录、学习效果的评价再加上后台的管理维护。我见过有学生把电子处方、中医诊断等功能塞进这种题目结果代码写了三千行业务逻辑却前后矛盾答辩时被老师追问两句就露馅了非常可惜。做毕设一定记住管理系统从字面就是要做“管理”把业务流程组织好而不是去实现某个专业领域的高深算法。具体到中医学习这个业务我建议把领域拆成四个方向内容资源中医基础理论、方剂学、中药学、针灸穴位等知识的分类管理与展示。学习过程用户制定学习计划、每日打卡、写学习笔记解决“怎么学”的问题。学习评价在线测试、自动判分、错题回顾解决“学得怎么样”的问题。系统管理用户、角色、分类、资源、试题、数据统计解决后台维护的问题。这四个方向与用户端、管理端的划分高度吻合后续需求、表结构、接口、页面全部围绕这个框架展开就不容易跑偏。1.2 核心业务流程怎么梳理拿到题目之后不要急着写代码先梳理两条主线流程。我习惯用最简单的方式在白纸上画“用户一条线”和“管理员一条线”。用户学习主线可以这样走注册登录 → 浏览/检索学习资源 → 选择某门课程或某个专题加入学习计划 → 按计划学习资源内容 → 每日打卡记录进度 → 完成章节测试 → 查看积分、排行榜和学习统计。这条线是一个闭环学习计划、打卡、测试都围绕着资源展开所以学习资源表是核心中的核心其他表和它都有直接或间接的关系。管理员维护主线则相对常规登录后台 → 统计仪表盘 → 管理学科分类 → 维护学习资源内容 → 管理试题和试卷 → 查看用户列表与学习数据 → 发布公告。这条线体现的是系统“可运营”的能力。如果学校要求必须引入三类角色你也可以再增加一个“中医专家/教师”角色负责内容审核、试题出题和回答用户提问。但作为毕设我把建议降到两个角色普通用户和管理员。如果时间充裕再扩展第三个角色也不迟但千万不要一开始就三角色并行开发工作量会迅速失控。再补充几个容易被忽略但答辩会被问到的点分类维度中医领域通常按学科分类比如中医基础理论、方剂学、中药学、针灸学也可以按资源类型分类比如图文、视频、音频。我建议做二级结构一级学科分类二级标签或小节分类。不要做太深的树否则后台维护和前端树形展示都很折磨人。学习计划的形态建议做成“按天拆解”。比如用户选择一门《方剂学》课程系统根据资源章节数量和预估学习时长生成一个30天的学习计划每天解锁几个方剂的学习任务学完自动解锁当天测试。这样才算真正体现“学习服务”。打卡的深度如果打卡只是“我今天学了”那太单薄。建议打卡时让用户填写当日学习心得、记录实际学习时长这样后续才能支撑学习统计图表和积分系统。数据维度多一点页面展示才有料。1.3 功能需求清单把方向落到具体功能一张表格就足够让工作量变得可估算。我列一下我常用的功能清单你完全可以直接在此基础上增减模块功能点具体说明用户管理注册登录用户名/邮箱注册、密码加密、JWT或Session登录用户管理个人信息头像上传、昵称修改、密码修改内容管理学科分类一级/二级分类增删改查树形展示内容管理学习资源标题、摘要、正文、封面、分类支持关键词检索内容管理资源上下架管理员可改变资源状态用户端只显示已上架内容学习过程学习计划选择资源生成按天计划进度可视化学习过程每日打卡记录学习时长与心得防止同一天重复打卡学习过程学习笔记关联资源记录笔记可公开或私密学习评价在线测试按分类/资源组卷随机抽题提交自动判分学习评价错题回顾记录答错题目支持重新练习与掌握状态标记学习评价积分与排行学习、打卡、测试获得积分展示排行榜系统管理后台仪表盘用户数、资源数、打卡次数、平均分等统计系统管理公告管理管理员发布学习公告用户端展示这张表基本就能支撑起一个完整且逻辑自洽的毕设。如果学校要求必须有亮点功能我建议把“错题回顾”和“打卡热力图”做深一些有真实数据展示时明显比普通CRUD有说服力。2. 核心技术选型解析2.1 后端框架为什么锁定Spring Boot现在做JavaWeb毕设Spring Boot几乎已经是默认答案。但选它不应该是纯粹跟风你得清楚它对这个题目到底好在哪里。我的看法有三点一是起步快一个main方法就能把Web服务跑起来没有传统SSM那些繁琐的XML配置对第一次做完整项目的人特别友好二是生态成熟MyBatis、Redis、Shiro、Swagger这些常用组件都有现成的starter引入依赖就能用三是市场接受度高这一套技术栈简历上写出来面试官基本都能和你聊下去。版本选择上目前稳定且教程最多的是Spring Boot 2.7.x对应JDK 8或JDK 11。如果学校没有硬性要求我建议你直接选Spring Boot 2.7.18 JDK 1.8 MyBatis 3.5.x MySQL 5.7或8.0这个组合。网上随便搜都能找到大量同版本资料踩坑时也好搜答案。Spring Boot 3.x当然更先进但强制JDK 17而且部分旧版依赖不兼容比如有些PageHelper版本在Spring Boot 3下直接报错对毕设这种时间敏感的项目来说稳定性永远排第一。再说说为什么不选JPA而选MyBatis。中医学习资源这种业务列表查询条件非常自由按标题模糊查、按分类过滤、按上下架状态筛选、按时间排序动态SQL非常常见。MyBatis的if、foreach写起来很顺手JPA虽然也能做但如果不会写Specification碰到稍复杂的多条件查询就很容易卡住。再加上很多学校教的就是MyBatis你用它也方便向老师解释。2.2 前端方案怎么选Thymeleaf还是前后端分离前端框架的选择会直接影响你的工作量。如果做前后端分离用Vue加Element UI页面确实好看交互也顺滑但代价是要同时维护两个工程处理跨域、联调、打包部署一系列问题。如果不熟悉前端工程化光一个Vite打包配置就能折腾一两天。相反如果只用Thymeleaf做服务端渲染所有页面都放在Spring Boot工程的templates目录里部署只有一个jar包简单省事但复杂交互做起来会比较别扭尤其是学习计划拖拽、实时图表这类页面。我个人给毕设的折中建议是Spring Boot Thymeleaf Bootstrap ECharts然后在部分复杂模块里引入Vue片段。比如打卡页面用Vue实例处理日期选择和心得输入测试页面用Vue管理题目切换和答案暂存。这样既控制住了工程复杂度又能让页面体验不至于太原始。等你真正理解了模板渲染和Ajax请求两种交互方式的区别再决定要不要完全前后端分离比一上来就选重型方案稳妥得多。2.3 辅助工具和中间件按需添加这类个项目通常不需要上高深技术但有些中间件能明显提升完成度需要注意“按需引入”MySQL数据库必须用它字符集必须选utf8mb4否则中医古籍里的生僻字、特殊符号存进去会变乱码。Redis可加可不加。如果你对Redis不熟别硬上。真想加建议只缓存首页分类和积分排行榜避免处理缓存一致性、序列化这些复杂问题。文件存储本地磁盘目录就够了数据库只存相对路径。不需要接云存储除非你手里有稳定的测试账号否则演示现场云端上传失败会很尴尬。Swagger接口文档推荐用knife4j集成Spring Boot 2.x版本自动生成接口文档。答辩时现场打开Swagger页面展示接口列表工程化意识立刻就有了。选型原则我用一句话总结能少用一个组件就少用一个但用到的每个都要能讲清为什么。展示稳定的项目比堆砌技术但跑不动的项目强一百倍。3. 数据库设计与核心表结构3.1 设计思路以资源为中心以用户学习记录为轴数据库设计是整个项目的地基表结构错了后面代码全得返工。中医学习服务管理系统的核心就两件事资源怎么组织、用户怎么和资源产生交互。资源组织靠分类表和资源表交互靠学习计划表、打卡表、笔记表、测试记录表、积分流水表。我的建议是至少设计以下几张核心表sys_user用户表sys_role角色表或者简化为用户表加一个角色代码字段learn_category分类表learn_resource学习资源表learn_plan学习计划表learn_checkin打卡记录表learn_note学习笔记表exam_question试题表exam_record测试记录表sys_point_log积分流水表exam_answer_record答题明细表记录某次测试中每道题的作答情况其中资源表和试题表是基础数据其他表围绕它们展开。下面重点拆几张表的关键字段。3.2 核心表结构示例用户表sys_user主键id、username、password存加密后的字符串、nickname、avatar、phone、role_code、status、create_time、update_time、deleted。毕设阶段不用搞复杂的角色表直接存一个role_code字符串即可admin或user逻辑简单开发效率高。学习资源表learn_resourceid、category_id、title、summary、content、cover_image、resource_type、source_from、author、view_count、status、create_time、update_time。这里有几个必须注意的字段细节content要用TEXT或LONGTEXT绝对不能用VARCHAR(255)一篇方剂讲解正文几百到几千字是常态255长度只能装个摘要。view_count用于展示阅读量虽然真实系统要防刷但毕设里简单实现每次详情访问加1就够了。status字段建议用1表示已上架、0表示下架用户端查询时强制加status 1条件管理端则要看全部。学习计划表learn_planid、user_id、resource_id、plan_name、total_days、current_day、start_date、end_date、status。核心逻辑是“进度推进”用户选择资源后生成一行计划每天打卡或学完任务后就更新current_day当current_day达到total_days时将status置为已完成。如果你想更细可以增加一张plan_task表把每天的学习任务清单列出来但毕设阶段我建议不要拆太细否则前后端的工作量会翻倍。打卡记录表learn_checkinid、user_id、plan_id、checkin_date、learn_duration、content、create_time。这里最关键的是要加一个唯一约束UNIQUE KEY uk_user_date(user_id, checkin_date)。这样不管代码里怎么并发同一天同一用户也插不进第二条打卡记录数据安全有了兜底。试题表的字段也要注意id、category_id、question_type单选/多选/判断、question_content、option_a、option_b、option_c、option_d、answer、analysis、difficulty、create_time。answer字段存的是选项编码或固定答案标记比如单选题存“A”判断题存“T”或“F”不要在数据库里存完整答案文本否则后续自动判分时格式非常难统一。3.3 表关系设计与字段规范表与表之间的关系我建议不建物理外键只做逻辑关联。原因很简单外键会导致数据的删除、导入非常麻烦而且MyBatis分页查询时如果带着外键约束操作顺序稍有不对就会报错。只需要在笔记表、计划表、打卡表里存user_id、resource_id这些关联字段查询时手动JOIN完全够用。答辩时你可以理直气壮地说公司真实项目中外键用得很少逻辑层保证数据完整性更灵活。所有业务表统一带创建时间、更新时间、逻辑删除三个字段create_time、update_time、deleted。deleted用0和1表示未删除与已删除查询时必须带上WHERE deleted 0。逻辑删除的好处是以后你删一个分类不会直接把相关内容物理抹掉数据不会因为误操作就彻底丢光。时间字段统一用datetime类型。应用配置MySQL连接时建议加serverTimezoneAsia/Shanghai参数否则可能会出现时间偏移8小时这种让人抓狂的问题。这些规范看起来不起眼但等到答辩前调试时才暴露就晚了。4. 后端核心业务功能实现4.1 统一响应封装与全局异常处理很多第一次做项目写Controller的人习惯直接返回一个Map或者返回实体对象结果接口格式千奇百怪前端联调时痛苦无比。我的建议是动工之前先写一个ResultT封装类所有接口统一返回code message data的JSON结构。代码非常简单public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(操作成功); result.setData(data); return result; } public static T ResultT error(String message) { ResultT result new Result(); result.setCode(500); result.setMessage(message); return result; } }配合RestControllerAdvice做全局异常处理器把业务异常和系统异常统一拦截。这样做的好处不仅是代码整洁更重要的是联调效率页面报错时永远能拿到一条可读的业务提示而不是满屏500堆栈。这个习惯从毕设开始养成以后进公司都很受用。4.2 登录认证与权限控制登录方案最常见的有Session和JWT两种。如果你用的是Thymeleaf服务端渲染用Session配合拦截器最简单如果你用了Vue前后端分离推荐JWT方案。毕设阶段我不建议硬上Spring Security全家桶用拦截器完全足够。以一个前后端分离的结构为例JWT登录的流程是用户登录成功后后端生成一个包含用户id和过期时间的token返回给前端前端每次请求在Header里带上Authorization后端写一个拦截器解析token并把当前用户id放到request属性里后续业务直接取用。拦截器核心结构如下Component public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); if (StringUtils.isBlank(token)) { throw new BusinessException(未登录); } // 解析token失败则抛出401异常 Long userId JwtUtil.parseToken(token); request.setAttribute(currentUserId, userId); return true; } }注册拦截器时一定记得排除登录接口和静态资源路径。这个步骤新手特别容易漏漏了以后连登录页的CSS、JS都加载不了然后开始怀疑是不是静态资源配置错了实际上拦截器把它们拦了。我第一次做时就卡在这个问题上半小时排查出来之后哭笑不得。4.3 学习资源管理模块实现资源管理是最典型的CRUD但要注意分页、搜索、上下架三个能力必须齐全。分页推荐用PageHelper插件引入依赖后在service方法里执行PageHelper.startPage(pageNum, pageSize)紧接着直接执行Mapper查询返回的PageInfo里已经包含了total、pages、list前端分页组件直接消费。这里有个大坑startPage之后必须紧跟Mapper查询中间不能夹带任何其他查询否则分页会作用到错误的SQL上。我看到过好几次有人统计完数据再分页结果总数还算了对的列表却是全量数据就是这个原因。Controller层的接口大概长这样RestController RequestMapping(/api/resource) public class ResourceController { Resource private ResourceService resourceService; GetMapping(/list) public ResultPageInfoResourceVO list(RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize, String keyword, Integer categoryId) { PageHelper.startPage(pageNum, pageSize); ListResourceVO list resourceService.queryResourceList(keyword, categoryId); return Result.success(new PageInfo(list)); } }Service里的动态SQL拼写时关键词搜索建议只做单个关键词的模糊匹配不要把用户输入拆成多个词再用or连接比如“肺癌 食疗”这种搜索在数据量小的时候反而查不出内容还容易导致SQL逻辑混乱。更稳妥的做法是先做标题模糊匹配再配合分类过滤再加上资源类型过滤足够应付演示。如果想要一个“高级感”功能可以在资源表加一个tags字段存逗号分隔的标签查询时用FIND_IN_SET过滤这个技巧不难但能体现你对搜索场景的理解。4.4 学习计划与每日打卡的业务逻辑学习计划和打卡是这套系统真正有业务含金量的地方不能当成单纯的增删改查。用户点击“开始学习”时后端要做的不只是insert一条计划而是一个完整的动作校验用户是否已有进行中的同资源计划有则直接返回提示避免重复创建。根据资源中预设的“建议学习天数”生成start_date和end_date初始current_day为1。把计划状态置为“进行中”。打卡接口的逻辑更要注意。用户传入计划id和当天学习时长后端先查询当天是否已存在打卡记录存在则返回“今日已打卡”不存在才插入新记录。插入成功后更新learn_plan表的current_day如果当前天数已经等于total_days顺手把计划状态改成“已完成”。给用户的学习体验是每天打开系统先看今天该学什么学完点打卡有种打怪升级的获得感。这里必须强调事务问题。生成计划和初始化任务涉及多张表方法上一定要加Transactional注解否则中途出错会出现“计划建了但任务没生成”的脏数据。更隐蔽的问题是事务注解只在Spring代理的public方法上生效如果同一个类内部调用带事务注解的方法事务会静默失效。不信你可以在Service里写个方法A调用方法BB上有Transactional断点看连接commit的时机你会发现它根本没生效。面试官和答辩老师都很喜欢揪这个点能讲清楚绝对是加分项。4.5 在线测试随机组卷与自动判分在线测试模块建议拆成两层管理员出题用户答题。管理员在后台维护试题用户端根据分类或者资源随机抽取若干道题组成一次测试。组卷SQL可以简单写成SELECT * FROM exam_question WHERE category_id #{categoryId} ORDER BY RAND() LIMIT 10。数据量只有几百条时这个写法非常舒服不需要复杂的随机算法。用户提交答案时前端把题号和用户答案按约定格式传到后端。我建议定义一个AnswerDTO包含questionId和userAnswer两个字段后端接收一个ListAnswerDTO然后循环比对正确答案累加得分同时记录错题。错题的记录表可以简化成id、user_id、question_id、statusstatus字段标记“未掌握”和“已掌握”。这样用户在“错题回顾”页面可以反复练习同一道题做对了就标记为已掌握。多选题的判分是另一个容易踩坑的地方。别只比对选项个数比如正确答案是“AB”用户选“BA”其实也是对的如果只比对字符串就会误判。我建议先把用户答案排序拼接成字符串再和正确答案排序拼接后的字符串比对。判断题答案格式也要全局统一用“T/F”还是“对/错”前端下拉选项和后端判分逻辑必须一致不然就会出现用户明明选对了却判错分的诡异bug。这类业务逻辑不复杂但需要在动手前想清楚判分规则否则写出来的判分代码会是一大堆if-else自己看着都头疼。5. 前端页面与交互实现5.1 页面组织布局与Thymeleaf应用如果你采用Thymeleaf方案前端页面统一放在src/main/resources/templates目录下静态资源放static目录下。布局上建议抽取一个公共片段比如左侧菜单栏和顶部导航栏用th:replace或者th:insert嵌入到各页面维护时只改片段文件所有页面同步生效。这个思路和JSP的include很类似理解起来不困难。页面目录建议按业务分admin目录放管理端页面user目录放用户端页面common目录放公共片段。管理端可以用Bootstrap加一个现成的AdminLTE模板颜色往中式风格调一调比如深棕、米白、中国红点缀中医的辨识度一下就有了。用户端则要营造学习氛围首页放学科入口、热门资源、排行榜个人中心放打卡日历和积分信息。如果需要在Thymeleaf页面里嵌入Vue片段你要注意一个坑Vue默认的插值语法是{{}}Thymeleaf也会用${}和[[${}]]两者混在一起会因为解析冲突导致页面渲染错乱。解决办法是修改Vue的定界符比如设置delimiters: [${, }]但改完以后要记得在模板里不用Thymeleaf的${}表达式否则会被Vue误解析。这个细节我调试了一下午才明白网上很多教程都没提。5.2 列表分页筛选与其他交互管理端资源列表页如果用Bootstrap Table插件要特别注意它默认的请求参数是limit和offset不是pageNum和pageSize。最简单的处理方式是在初始化Table时配置queryParams把参数转换一下或者后端写一个PageRequest对象同时兼容两套参数名。我习惯后端统一接收pageNum/pageSize前端通过queryParams函数做适配。筛选条件方面分类下拉建议做成二级联动选了“方剂学”这个一级学科后二级下拉自动出现对应的小节资源类型用复选框多选筛选条件变化时重新请求第一页数据。交互细节做完后整体体验就专业不少。列表页还要注意空数据状态最好显示一张友好的提示图而不是一个空白表格。5.3 富文本编辑器与文件上传中医资源正文会有大量图文混排后台必须集成一个富文本编辑器。我推荐wangEditor中文文档、集成简单、体积小。集成流程不复杂在资源编辑页面引入wangEditor的JS文件初始化编辑器在提交表单时把editor.txt.html()赋值给一个隐藏textarea再提交即可。图片上传有一个细节要特别注意不要把富文本图片转成base64直接存进content字段。那样会导致正文几十KB甚至更大数据库表膨胀非常快。正确做法是给编辑器配置自定义上传接口接口接手MultipartFile把文件保存到服务器本地指定目录然后返回一个图片的访问URL编辑器会把URL插入到正文里。本地上传路径建议放在一个可配置的目录比如upload/不要放到classpath资源目录内否则打包之后路径可能失效。部署到服务器时只需要把配置文件里的路径改一下图片就能正常访问。上传接口同样要做类型和大小校验只允许jpg和png单文件不超过2M。这个限制虽然简单但能防止答辩现场上传过大的图片导致页面卡死。5.4 学习数据可视化数据可视化是加分项。建议至少做四个图表打卡热力图类似GitHub贡献图展示一个用户的每日打卡情况。学习时长趋势折线图按周统计累计学习时长。积分排行榜展示总积分Top10用户。管理端仪表盘用户总数、资源总数、打卡总次数、测试平均分。ECharts是首选前端图表库普通图表配置并不难。数据来源是数据库聚合查询打卡热力图连续打卡天数可以通过程序端分段统计性能完全够用。这些图表最怕的就是没数据。所以我特别建议开发阶段写一个测试数据生成工具类往库里插入几十个用户、几百条打卡记录、几十道试题模拟一个月的真实学习行为。答辩演示时打开统计页面图表红红火火比打开个人中心一片空列表效果强太多。这个准备工作很多人忽略结果演示现场只能给老师看一堆空表格和报错日志效果当然差。6. 实操过程中踩坑与排查实录6.1 启动失败和端口问题Spring Boot启动失败最常见的原因第一是端口被占用。尤其在IDEA里前一个项目没关掉后一个项目又启动控制台会直接报Port 8080 was already in use。解决办法两种要么找到占用进程杀掉要么直接改application.yml里的server.port。我建议开发时用一个不常用的端口比如8085后端我甚至用过8088但部署到80或8080时反而要记住改回来。第二是JDK版本和Spring Boot版本不匹配。比如你用了Spring Boot 3.x却还在用JDK 8编译期有时不报错但一到运行就抛UnsupportedClassVersionError。解决方法是把IDEA的Project Structure里Project SDK和Modules的Language Level都改成17以上只改一处没用的这个我帮人排查过很多次。6.2 数据库连接、时区与乱码问题数据库连不上绝大多数是连接URL配置不全导致的。MySQL 8的驱动类和MySQL 5不同URL里建议显式加上useSSLfalseallowPublicKeyRetrievaltrueserverTimezoneAsia/Shanghai缺了会在连接阶段或查询阶段报出各种奇怪的异常。更常见的坑是characterEncodingutf8没有放到URL里导致中医内容里的生僻字、特殊符号存进去变问号。就算表字段字符集已经设成utf8mb4连接串没指定编码整个数据链路还是可能乱码。事务失效这个坑前面提过我再详细说一次。典型场景一个Service类里的方法A调用方法B方法B上有Transactional结果B抛了异常A里的数据没有回滚。原因是事务注解是通过Spring代理实现的内部方法调用走的是当前对象而不是代理对象所以事务切面拦截不到。解决办法是让B独立成一个Bean或者把事务边界放在最外层调用方法A上。这个知识点实操性极强也是经典面试题值得专门掌握。6.3 MyBatis动态SQL和分页查询的大坑Mapper动态SQL里判断条件最容易踩的是类型不一致问题。if testkeyword ! null and keyword ! 中如果keyword是Integer类型加! 就会触发类型比较异常。建议所有参数类型都明确判断统一写成! null加上! 前端传空字符串时在Controller层先转成null。PageHelper分页的坑还有一个典型场景列表查询带多表JOIN比如查询资源列表并关联分类名称PageHelper自动生成的count SQL有可能会出错导致分页总数不对或查询报错。我的建议是主查询只查主表字段然后用一个批量查询select * from learn_category where id in (...)把分类名称补齐。这既避免了JOIN带来的分页风险也顺带解决了N1查询问题属于一举两得。6.4 部署演示与测试数据准备开发完成后的打包命令很简单mvn clean package -DskipTests生成一个可执行jar包服务器上用java -jar xxx.jar启动。但部署前有三个隐藏坑要提前排查数据库迁移本地库和服务器库要一致尤其是字符集。建议用Navicat直接迁移整个库结构和测试数据手动建表很容易漏字段。上传路径差异本地是D:/upload服务器是/data/upload路径不对图片就会404。把上传根路径做成配置项放进application.yml切换环境只改一行。内存限制云服务器内存只有1G的话建议启动参数加-Xmx512m否则Java进程很容易因内存不足被杀掉。答辩演示前强烈建议准备一套演示剧本。我的习惯是先用管理员账号演示新增资源与试题再切到用户账号演示加入学习计划、每日打卡、做测试、查看错题、查看排行榜。整个过程控制在10分钟以内而且演示数据要提前造好不要现场输入。曾经有个学生现场创建资源结果富文本图片上传卡了半分钟全场等他那张图转圈印象分直接掉了一截。这种尴尬完全可以靠提前准备规避。6.5 代码整洁度与答辩准备最后说一个看起来“虚”但很重要的点答辩老师不一定有时间一行一行跑你的代码但一定会翻项目结构。所以包名要规范比如com.example.tcm下面按controller/service/mapper/entity/config/common分层类名要有业务含义别出现Test2Controller这种东西Controller里只做参数接收与响应封装业务逻辑放到Service层。分层一清楚代码可读性立刻上去了。接口路径建议也统一风格用户端接口统一/api/user/**管理端接口统一/api/admin/**拦截器按路径前缀做不同校验。如果在项目里集成Swagger并给所有接口补充注释答辩现场打开接口文档展示老师会觉得你的工程化意识明显高于平均线。如果答辩时老师问你“系统的不足”不要慌。你可以诚实说当前打卡防刷机制比较简单、错题重练算法还有优化空间然后马上接一句“后续可以引入Redis的分布式锁以及基于学习行为的推荐算法”。这样既表现出你有思考又把话题拉回到你熟悉的扩展点上。切忌全程说“我的系统很完美”老师最怕这种没有反思的回答。这个项目做完之后你对Spring Boot开发链条的理解会完全不一样从需求分析到数据库建模从接口设计到前端联调从本地调试到打包部署每一个环节都在逼你思考“为什么要这么做”。哪怕你以后不碰中医学习业务这套思路放到任何管理系统上都成立。最后再分享一个我自己的习惯做毕设不要贪大需求范围控制得越准完成度就越高。很多人一开始想把智能推荐、AI诊断全塞进去结果到答辩前两天还在调登录最后只能连夜删功能。反过来你把核心闭环打磨通数据充足、流程顺畅、页面干净就已经能稳稳超过大部分同学了。希望这篇拆解能帮你少走点弯路祝你顺利。
返回列表