
做这类系统最怕的就是看起来什么都做了实际上每块都没做透。SpringBoot Vue MySQL 做社区医院管理系统是JavaWeb方向最经典的毕业设计组合但它之所以经典恰恰是因为它把前后端分离、权限控制、业务流转、数据建模这些核心面试题全包进去了。我拆过不少这种项目也带过一些同学复现今天就以这套系统为例把从立项、技术选型、数据库设计到前后端编码、部署、论文撰写、答辩准备的完整链路一条龙讲清楚。这篇文章适合下面三类人一是正在做类似毕业设计、需要一套完整思路作为参照的同学二是工作后想拿一个全栈型项目练手、补齐前后端衔接经验的初级开发三是准备用这个项目做面试亮点、需要把业务细节讲明白的人。内容会尽量贴近真实开发里踩过的坑来写能抄作业的地方直接抄。1. 项目价值拆解与整体定位1.1 为什么社区医院管理系统是毕业设计的好选题社区医院这种业务场景恰好卡在复杂度够用和边界清晰之间。它不像三甲医院那样有几十个复杂的子系统也不像单纯的图书管理系统那样业务过于单薄。核心业务大致就这几条线挂号、分诊、门诊开单、收费、药品库存、患者档案。这几条线串起来以后天然就有了多角色的需求——管理员、医生、收费员、药房、护士、患者不同角色看到的东西、能操作的功能完全不同。这就逼着你去做登录鉴权、路由守卫、接口权限控制。要知道毕设答辩的老师最常问的问题之一就是你的系统安全性怎么体现的如果只是一个登录页没有任何角色层面的控制逻辑这一问基本就挂了。另外这个场景能产生数据统计的需求。比如某段时间内各科室接诊量、某类疾病的开药趋势、药品消耗排名这些既可以用MySQL的聚合查询来做也可以顺便引入一个简单的ECharts图表展示。有了统计模块项目的展示面就拉得很高演示的时候能讲的东西也更多。1.2 技术栈选型的真实考量这里重点说下为什么是这三个东西组合而不是别的。SpringBoot提供了一个约定优于配置的开发骨架内置Tomcat不用再手动打war包扔外置容器里和MySQL的整合也极其顺滑起步依赖引入后几十行配置就能把数据源跑起来。如果选传统的SSHStruts2 Spring Hibernate或SSM框架光配置文件的折腾就能耗掉一半时间而且答辩时还要被追问一堆XML配置的细节属于自己给自己加难度。Vue这边用Vue 2.6 Element UI属于最稳的组合。有同学问为什么不用Vue 3 Element Plus原因很直白网上现成的管理系统模板、博客文档、报错解决方案绝大多数都是Vue 2这套生态。你碰到一个编译报错随手一搜基本都有答案这就省了太多时间。Vue 3 TypeScript的版本确实更现代但作为一个以业务为展示核心的毕业设计稳定、文档全、易排查优先级比前沿性高得多。MySQL不用多说开源、免费、装起来方便Navicat之类的图形化工具一应俱全。做毕设完全够用没有任何理由去选Oracle或SQL Server。2. 系统功能架构与数据库设计思路2.1 六类角色与核心业务闭环这套系统里我建议把用户角色拆成六类分别是系统管理员、医生、护士、收费员、药房管理员、患者。有人会觉得角色太多了实现起来麻烦。但我的观点是角色多不是负担而是毕业设计最大的加分项。每多一个角色就多一组接口、多一组菜单权限配置、多处一个可讲的业务点论文里的功能描述也更有话可写。先说核心的业务闭环。患者通过系统注册账号并完善基本信息按科室查看医生排班表选择合理的时间段完成挂号。医生在待诊列表中看到已挂号的患者接诊后填写诊断结果开药品处方或检查项。检查项可以选择立刻做还是预约时间做药品处方先传到药房患者拿着处方单到收费窗口缴费缴费后去药房取药。这里有一个容易忽略但又很重要的点收费模块一定要跟库存和处方状态联动。如果处方缴费后药房没有减库存也没有把处方标记为已取药那药房就只能看着处方单手动发药整条链路就断了。所以数据库设计的时候就要提前把状态字段想清楚。以处方单为例状态至少要有四个待缴费、已缴费待取药、已取药、已退费。每个状态对应一条审批流这样在演示的时候就能把事情讲得很细——医生开方后处方状态为待缴费患者到收费窗口结算收费员操作后变成已缴费待取药药房看到处方后发药并减库存状态改为已取药。除了业务主链路还有一些辅助模块也要分给合适的角色。系统管理员负责用户管理、角色分配、科室管理、基础字典数据的维护比如性别、血型、药品分类、检查项目类型等。护士侧可以负责分诊台操作比如为患者量体温血压并记录到就诊信息里。这类小功能不需要太多但每个角色有一个专属功能答辩的时候讲多角色协作就有具体的支撑。2.2 数据库表设计的关键取舍表怎么设计能直接看出来你有没有真实做过项目经验。我见过很多毕设的数据库表就三五张全是核心主表业务主表和业务明细表完全分不开。比如一张挂号表里就塞了诊断、处方、费用、缴费状态这种设计答辩时老师一眼就能看出来没经过正规训练。我这里给一个经过实践筛选的表清单大家可以直接照着建这些表数量控制在十六到二十张之间团队的规模也刚好是有一定工作量但又不至于臃肿系统管理类sys_user用户、sys_role角色、sys_menu菜单/权限、sys_user_role用户角色关联、sys_role_menu角色菜单关联机构人员类department科室、doctor_info医生信息包括职称、排班、所属科室患者业务类patient患者档案和sys_user可以分开也可以合在sys_user里加patient_type字段、appointment挂号预约/挂号记录诊疗业务类medical_record门诊病历/诊断记录、prescription处方单、prescription_item处方明细收费与药品类charge_order收费单、charge_item收费明细、drug_info药品、drug_stock药品库存扩展业务类check_report检查报告、bed_info病床、hospitalization住院记录这里单独说一个很多同学的误区sys_user是一张统一的登录账号表。不要给医生、收费员、患者各自建一张用户表然后登录的时候拿Type字段去区分查询哪张表。正确做法是一张sys_user表里放上用户类型字段打比方说role_type为1、2、3……分别对应不同角色。用一张表做登录校验逻辑最清晰写JWT鉴权拦截器时也不用一段代码里写多次查询。还有一点是外键的问题。我在实际开发里很少在数据库层面建真正的外键约束都是逻辑外键也就是用字段关联id但不加FOREIGN KEY。原因有两个一是MySQL里的物理外键在删除和更新时容易导致倒不下数据的问题做毕设关键表中反而容易自缚手脚二是实际项目里物理外键约束对性能影响不小现在主流的互联网团队基本都用逻辑外键。这一点答辩时如果被问到可以讲从性能和维护性考虑采用逻辑外键设计由代码保证关联完整性是加分的回答。3. 环境准备与项目初始化实战3.1 开发环境清单与版本选择这一节是很多新手第一步就卡住的地方所以我想把版本号和坑都写清楚。JDK1.8。别上来就装JDK 17或21。Spring Boot 2.x系列在JDK 8上运行最稳定16以上版本会出现一些兼容性问题还需额外处理。Maven3.6.3或3.8.x。装3.9也可以但不要装最新的4.x。IDEIntelliJ IDEA社区版就够用。注意用Ultimate版的话要新建Spring Initializr项目比较方便社区版则直接新建Maven项目pom里加依赖即可一样的效果。Node.js14.x或16.x。这个版本很有讲究Vue CLI 4对低版本Node兼容更好我见过有人装了Node 20执行npm install直接报错看得头大。MySQL5.7或8.0。两个版本都行但注意不同版本连接驱动和时区配置有细微差别后面会专门说。Navicat建议选Navicat 16或免费的DBeaver。不推荐破解版的Navicat容易下到带广告或者带木马的东西DBeaver完全够用。上面版本建议的理由其实就一条把环境的不确定性降到最低。毕业设计最怕的从来不是业务写不出来而是时间全耗在环境问题上。3.2 后端项目骨架搭建SpringBoot项目我习惯用手工建Maven工程的方式来做这样pom文件里的每个依赖都能讲明白作用。在pom.xml中加入以下核心依赖parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.14/version /parent dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.1/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency dependency groupIdcom.auth0/groupId artifactIdjava-jwt/artifactId version3.19.2/version /dependency dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.18/version /dependency /dependencies补充说明一下为什么选MyBatis而不是MyBatis-Plus。有很多同学会直接用MyBatis-Plus因为它自带BaseMapper单表CRUD不用写SQL非常省事。但我个人建议做毕设的时候用原生MyBatis原因有两个方面。第一MyBatis-Plus太方便了方便到写代码的时候你基本不思考SQL答辩时老师问你这个关联查询怎么写的你一下想不起来自己封装了什么场面会很尴尬。第二原生MyBatis的XML文件里每一条SQL都是自己一条条写出来的这恰恰是论文里可以做重点展示的部分直接把核心SQL贴出来配合业务逻辑讲解比贴一堆方法名有说服力得多。再看HashMap。MyBatis查询返回的resultType直接写成MapString, Object会偷懒很多。有些同学所有的查询都返回Map结果service里到处是类型强转代码看着脑袋都大。我建议所有核心业务表都建对应的实体类比如Appointment、PrescriptionMap只在统计报表之类的动态字段查询时使用。项目包结构我这里直接给出一个可以照抄的版本比很多博客里那种无意义的entity/dao/service/controller四层多了业务分组的语义com.hospital ├── config (跨域配置、拦截器配置、全局异常处理) ├── controller (接收请求只做参数校验和结果封装不写业务逻辑) ├── service (业务逻辑事务控制在这里) ├── mapper (MyBatis的mapper接口) ├── entity (数据库表对应的实体类) ├── dto (前端传来的请求参数对象避免直接用entity接收) ├── vo (返回给前端的数据对象比如带分页结果的PageVO) ├── utils (通用工具类比如JWT工具类、日期处理工具类) └── common (统一返回结果类Result、统一状态码枚举)3.3 前端Vue项目搭建与联调准备前端我建议直接用Vue CLI而不是Vite。原因跟前端框架选型的逻辑一样Vue CLI生态成熟、配置直观、报错可搜。Vite的冷启动确实快但现在回想一下毕业设计的演示场景下这种开发体验差异微乎其微而Vite下碰到特殊插件兼容问题时排错要花的时间可不少。创建项目用以下命令npm install -g vue/cli vue create hospital-web选的时候注意Vue版本选2.x不要选3跟上面Element UI的道理一样。我建议在创建项目时不要勾选eslint。ESLint固然能规范代码但新手经常出现代码写得没问题但一直报错的情况里头的报错信息反而更让人抓狂格式化风格还会影响项目启动。在毕设阶段建议先把功能写对、把项目跑起来后面再考虑规范的事。装依赖npm install element-ui2.15.14 axios vue-router3.5.4 vuex3.6.2注意版本号Vue 2项目的vue-router要装3.x不能装Vue 3专用的4.x。这是前端最经典、最迷惑的版本问题之一。axios请求封装这里最核心的一点是响应拦截器。要在后端返回结果里约定一个统一格式前端拦截器里判断状态码。后端Result的结构可以这样设计public class ResultT { private Integer code; // 200成功401未登录500失败 private String msg; private T data; }axios请求封装示例import axios from axios import { Message } from element-ui import router from /router const service axios.create({ baseURL: /api, // 后面配代理 timeout: 10000 }) service.interceptors.request.use(config { const token sessionStorage.getItem(token) if (token) { config.headers[Token] token } return config }) service.interceptors.response.use(response { const res response.data if (res.code 401) { sessionStorage.clear() router.push(/login) Message.error(登录已过期) return Promise.reject(new Error(未登录)) } return res }) export default service这里有个容易忽视的细节Token放在请求头里的键名要跟后端拦截器里读取的键名保持一致。有的同学前端请求头里面写Authorization后端签发的却是个自定义header比如X-Token两边对不上登录后任何请求都会被拦截器干掉——这种小问题排查起来经常就是半小时起步。4. 核心功能模块实现详解4.1 JWT登录鉴权与拦截器配置登录鉴权到底用Session还是JWT之前有些同学用Session方式实现就是登录后往HttpSession塞一个user对象后面每个请求用request.getSession().getAttribute()去取。这个方案写起来确实简单但有两个明显的问题第一个问题是前后端分离部署时Session跨域很麻烦就算能通过配置解决也属于不攻自破的隐藏坑第二个问题是会话数据在服务端内存里分布式部署时第一个机器上没有session就废了。所以用JWT是更符合行业主流方式的方案。JWT的使用逻辑就是这样用户在登录接口提供用户名密码校验通过后后端用私钥生成一个tokentoken里塞userId、userName、roleType之类的核心信息然后返回给前端。前端存到sessionStorage里之后每次请求都在请求头带上token。后端写一个拦截器统一拦截请求登录之外的所有接口都校验token存在且合法。生成token的工具方法示例private static final String SECRET hospital-secret-key; public static String generateToken(Long userId, String userName, Integer roleType) { Algorithm algorithm Algorithm.HMAC256(SECRET); return JWT.create() .withClaim(userId, userId) .withClaim(userName, userName) .withClaim(roleType, roleType) .withExpiresAt(new Date(System.currentTimeMillis() 2 * 60 * 60 * 1000)) .sign(algorithm); }校验token的核心逻辑public static Long getUserIdFromToken(String token) { DecodedJWT jwt JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token); return jwt.getClaim(userId).asLong(); }拦截器配置时要注意开放路径的问题。比如/api/auth/login、/api/auth/register这两个接口必须是放行的否则用户还没登录就进不来。另外前端项目的静态资源路径、错误页面路径也需要放行。我见过很多同学拦截器配得比较严格导致登录页自己都无法访问这个在配置映射的时候要多检查一遍。还有一个面试常考的点把密码以明文方式存进数据库。不管是不是毕业设计这一点都应避免。建议密码使用MD5加盐的方式存储原理是MD5原始密码 固定盐值后入库。加盐是为了防止彩虹表反查这个点可以在论文和答辩中专门提出来说。4.2 科室与排班模块科室模块看起来是简单的增删改查但里面藏着两个常见的设计问题。第一个是科室和医生的关系。正确设计先在department表里维护科室再在doctor_info表里存储doctor_id和department_id关联。一个医生有且仅属于一个科室但可以通过排班灵活调配出诊时间。有的同学会把科室列表字段直接存成医生表的一个字符串字段比如内科、外科这样后端的科室统计几乎没法做排班也没有任何扩展性可言。第二个是排班的设计。排班表我建议单独建一张表不要硬塞在医生表里。排班表可以设计成schedule表大致字段有id主键、doctor_id医生id、department_id科室id、schedule_date出诊日期、period_type上午1/下午2/晚上3、total_count总号源、booked_count已挂号数量、status排班状态。这样挂号的时候才能按科室日期时间段组合查到排班然后判断booked_count是否小于total_count。如果排班槽位已经挂满挂号接口要返回号源已约满不能无脑往appointment表里插入。这是体现业务完整性的一个小细节答辩时值得主动提一句。4.3 挂号与门诊收费闭环挂号流程的前端交互不复杂但后端要处理好三个联动问题。首先挂号的时候要检查患者是否已经存在在patient表里。如果患者是通过注册入口进入系统的挂号时可以直接读取当前用户的patient档案但患者填写的信息发生变更时也要能更新档案。比较好的做法是不让患者自己维护病历而是由挂号处核对处写入。其次挂号操作应该做成事务第1步插入appointment记录第2步更新schedule表的booked_count 1。这两步不能只做其中一步否则要么号源超卖、要么挂号记录缺失。给service方法加上Transactional注解就能解决Transactional(rollbackFor Exception.class) public int registerAppointment(AppointmentDTO dto) { scheduleMapper.increaseBookedCount(dto.getScheduleId()); return appointmentMapper.insert(dto); }再说收费模块。收费单我建议从挂号记录和处方单两个来源产生。挂号时直接生成一张挂号费收费单就诊后医生开的处方产生一张处方收费单。收费员界面有两块未缴费列表、已缴费列表。未缴费列表只展示状态为待缴费的记录收费员点击收款按钮后后台做两件事把收费单状态改为已缴费同时把关联的处方单状态改为已缴费待取药。这里的状态流转一定要更新到关联单据我见过不少系统只更新了收费单药房那边的处方状态没有任何变化等于药房模块白做。药品库存扣减的时机很容易踩坑。我建议药品库存不扣在收费时而扣在药房发药时。比如患者虽然缴费了但一直不去取药如果收费时已经减了库存药房过了两天盘点才发现账实不符。正确的做法是药房发药事务里同时执行两条更新者检查库存足够后做发货外加库存数量减减和处方状态改改。5. 部署上线流程与完整交付清单5.1 前后端打包与Nginx部署毕设答辩不能只在自己电脑上跑那样老师是无法给部署的分数。这里给一套能够在单台云服务器或本机完成的前后端分离部署流程。后端打包mvn clean package -DskipTests这条命令会生成一个target目录下的jar包比如hospital-server.jar。然后直接java -jar hospital-server.jar就能启动后端。需要注意配置文件里MySQL地址、用户名、密码的配置方式。如果说你用的是云服务器数据库要将jdbc的url改成公网数据库地址本地则是jdbc:mysql://localhost:3306/hospital?useSSLfalseserverTimezoneAsia/Shanghai。serverTimezone这个参数很关键。MySQL 8默认时区可能是UTC会导致时间数据查出来差8小时。加了serverTimezoneAsia/Shanghai之后就能避开。另外useSSLfalse也有用不然数据库连接会报SSL连接错误。前端打包npm run build打包完成后会在dist目录生成静态文件。把这些dist文件放到Nginx的html目录里。Nginx配置目录建议这样写server { listen 80; server_name localhost; # 前端静态资源 location / { root /usr/share/nginx/html/hospital; index index.html index.htm; try_files $uri $uri/ /index.html; # Vue Router的history模式要加这句 } # 后端接口反向代理 location /api/ { proxy_pass http://127.0.0.1:8080/api/; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }try_files $uri $uri/ /index.html这行一定要写。Vue Router如果用的是history模式刷新某个非根路径比如/medical-record时会404加上这一行就把请求都先引到index.html再由前端路由器接管。前后端端口的问题也要注意如果后端接口是/api开头后端Controller里所有接口要做统一前缀在application.yml里可以配server: port: 8080 servlet: context-path: /api后端有自己的统一跨域配置。但一旦走后端部署的反向代理同源情况下就不需要跨域配置了。开发环境调试的时候前端可以配一个proxy代理来解决跨域devServer: { port: 3000, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }5.2 数据库脚本与初始化数据交付清单里数据库这块有两个东西是必须的一个是建库建表脚本一个是初始化数据脚本。建表脚本要保证新环境上可以一键导入。如果你在Navicat里手动建的表执行转储SQL文件导出时注意勾上包含建库语句和包含数据两个选项。我遇到过一个同学的交付包里没有数据库脚本部署文档里写着请按照ER图手动建表这种交付直接会被降级评价。初始化数据也很重要。管理员账号必须内置一个不然他部署完连初始账号都没有就没法登录后台。另外药品分类、科室列表这些基础数据不要放空表直接插入几条示例数据进去演示的时候就有画面了。还应生成几十条模拟的挂号记录因为如果你库里一张挂号单也没有统计图表页面根本看不出效果。6. 论文写作与答辩要点6.1 论文结构安排与核心章节怎么写论文模板学校通常会发但内容架构基本都逃不开下面这几章绪论、相关技术介绍、需求分析、系统设计、系统实现、系统测试、总结与展望。这里有一个比较划算的安排方式如果工作量集中在系统设计那论文就把系统设计拆成两大章——总体设计和详细设计。总体设计里写总体架构图、功能模块划分、数据库概念模型ER图详细设计里按模块分别讲类设计、接口设计、业务流程时序图和关键表结构。需要把关键代码贴进论文里比如JWT拦截器的核心代码、挂号事务的代码、MyBatis关联查询的SQL。代码不要全部代码只贴核心部分并在代码前后写上设计思想。答辩老师看论文主要是扫图、扫标题、扫代码块。有一个图论是系统架构图、功能模块图、数据库ER图、业务时序图。这四张图画好论文整体基调也就稳了。需求分析部分一定要有用例图配用例描述。比如患者挂号这个用例前置条件患者已登录且存在有效排班、主流程选择科室、选择医生、选择排班时段、确认挂号、异常流程号源已满、未登录。这类描述在网上可以搜到很多模板但最好自己结合代码里的实际业务改写更贴近真实。6.2 答辩时的高频问题与应答思路答辩场上老师提问一般都围绕这几个角度技术细节、业务设计、代码有没有你自己写的、解决方案的取舍。举个例子老师可能会问SpringBoot的自动配置原理是什么这道题是经典中的经典。答复思路大致这样说SpringBoot是通过启动类上的SpringBootApplication注解该注解组合了EnableAutoConfiguration它会引入AutoConfigurationImportSelector通过SpringFactoriesLoader读取META-INF/spring.factories文件里的自动配置类再按照条件注解ConditionalOnClass、ConditionalOnMissingBean等判断是否生效。再比如为什么数据库表不用物理外键这个问题前文已经埋过答案了重点从性能和可维护性两个角度去答。还有Vue的v-if和v-show有什么区别这个很常被问到。v-if是真正的条件渲染触发重新创建或销毁组件v-show是设置display为none。建议高频切换用v-show初始化高频的用v-if。教师可能会截取系统里的一段核心代码进行提问所以答辩前要把自己最核心的模块——登录模块、挂号模块、收费模块——代码从头到尾过一遍保证每个方法的作用、每条SQL的意图都能说得清。不管你实际是不是从别人的代码改的都要像自己亲自写一样熟练这个很关键。7. 常见问题与避坑实录7.1 数据库连接与版本问题先说MySQL 8的连接问题。用com.mysql.jdbc.Driver会在启动时报错Loading class is not registered正确driver是com.mysql.cj.jdbc.Driver。Spring Boot 2.x的mysql-connector-java 8.0.x版本已经自动管理这个驱动但如果你在pom里乱指定旧版本就麻烦了。SSL连接错误的处理报错文本通常类似SSL connection error或Public Key Retrieval is not allowed。解决方法就是在url后加useSSLfalseallowPublicKeyRetrievaltrue。千万不要只加useSSLfalse因为MySQL 8的caching_sha2_password认证模式下allowPublicKeyRetrieval默认false时还是会报错。时区问题表现是数据库里存的时间正常但Java查询出来多了8小时或者前端显示的时间不对。解决就是在url后加上serverTimezoneAsia/Shanghai。7.2 前端跨域与Token失效类问题开发模式下跨域报错这个场景特别多。如果前端端口是3000后端端口是8080浏览器里会出现CORS错误。处理方案在5.1已经写过了。这里补充一个排查要点加了代理后即使浏览器地址还是localhost:3000但接口请求已经由Node代理转发到8080了所以浏览器不会再报跨域。如果你的项目不是通过devServer代理而是直接在axios里写http://localhost:8080那就要考虑后端统一加CORS配置了。Token失效的典型症状是登录状态过了一段时间后操作都报401需要重新登录。这就是token过期时间到了符合逻辑。但两个更隐蔽的问题需要排查一是在拦截器中异常没处理导致任何非200状态码都没有返回给前端二是前端没有在拦截器里对401做跳转处理导致用户看着页面所有请求都在401。7.3 后端启动失败与接口报错排查端口占用的问题很常见后端启动时报Port 8080 was already in use。Windows上可以通过netstat -ano | findstr 8080查看占用进程然后taskkill /PID xxx /F结束。开发机上有其他服务占用8080时也可以直接改application.yml里的端口。MyBatis中特别常见的两种报错绑定异常明明写了Mapper接口还在接口上标了Mapper运行却报Invalid bound statement。绝大多数原因都是XML里的namespace写错了或者mapper.xml文件没有放到resources目录下、没匹配到接口名。检查顺序应该是namespace完全等于接口全限定名XML里的id等于方法名SQL里所用的参数名与接口方法参数对应。这三条逐一对照。Only java.lang.String and primitive types are supported这种报错也很常见通常是MyBatis传参时没用Param注解采用多个参数没有用map包装。解决办法方法的参数上加Param(xxx)注解或者封装成一个DTO对象。7.4 从零到答辩的时间规划建议如果按照上面的方案来推进结合我实际带项目的经验一个正常的节奏大约是四周第一周需求分析和数据库设计。写清楚有哪些角色、哪些核心流程表格建好初始化数据基本跑通。 第二周后端核心接口。先做登录和鉴权再做挂号、医生、收费等主体接口。 第三周前端页面。先把登录和后台布局搭好再实现每个模块的列表、表单和路由。开发时可以后端的接口尽量早设计前后端并行推进。 第四周部署和答辩材料准备。打包部署整理论文做PPT复盘接口细节模拟答辩问题。这套系统最终的呈现形态是四个交付物可运行源码、SQL脚本、完整论文、部署文档。这四样如果都做扎实这个毕业设计不仅是一个项目更是你面试时可以拿出来讲的完整全栈案例。最后分享一个我自己体会很深的点做完这个项目以后把每个模块的状态流转画成一张图比如挂号状态的流转、处方状态的流转、收费单状态的流转。答辩的时候这张图比任何一百页PPT都管用。因为老师能看出来你是真的梳理过业务而不是单纯背了几个框架。就讲到这里接下来把环境装好照着上面的步骤干就行。