ARTICLE DETAIL

资讯详情

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

SpringBoot+Vue宠物健康顾问系统:从零搭建Java Web毕设项目全解析

SpringBoot+Vue宠物健康顾问系统:从零搭建Java Web毕设项目全解析 SpringBootVue 宠物健康顾问系统平台完整项目源码SQL脚本接口文档【Java Web毕设】最近整理存档时翻出一个毕业设计项目正好后台又有人问宠物健康类管理系统怎么做。干脆把这个完整的“SpringBoot Vue 宠物健康顾问系统平台”从头到尾拆开讲一遍。这个项目不是那种只跑通页面就完事的小demo它包含了完整源码、SQL初始化脚本、接口文档、以及设计文档。整套东西拿来做Java Web毕设、课程设计、或者自己练手学习都合适。先说清楚这个项目能做什么。它的核心定位是“宠物健康顾问服务”覆盖宠物主人端的健康档案管理、在线问诊预约、疫苗驱虫提醒、健康资讯浏览以及后台管理员的宠物信息审核、服务项目管理、订单处理、数据统计。技术栈是SpringBoot做后端接口Vue 2做前端界面MySQL存数据。整条链路从前端表单提交、后端接口处理、SQL表设计到接口文档输出全部都是毕设和中小型管理系统最典型的一套组合。为什么要选SpringBoot Vue这套组合而不是SSH或者纯JSP因为SpringBoot解决了传统Spring配置地狱问题Vue的前后端分离模式让分工更清晰MySQL又是最普及的关系型数据库。对毕设来说这套组合既不会太简单显得没工作量又不会像微服务、云原生那样难以落地。而且面试官看到这套组合也最容易继续往下问——问框架原理、问接口设计、问数据库优化你都有东西能答。如果你是刚接触Java Web的在校生或者准备短期完成毕设、正在找思路的开发者这篇文章会给你从零理解这个宠物健康顾问系统的功能架构和表设计前后端分离项目怎么在本地跑起来IDEA VSCode 小皮面板完整的API设计思路和接口文档写作套路毕设答辩时最容易踩的坑例如如何回答“为什么用JWT做登录认证”1. 系统整体设计与功能拆分1.1 业务需求从哪来宠物健康场景的痛点宠物健康顾问系统本质上是一个垂直领域的“挂号问诊 健康管理平台”。我们要做的不是宠物电商也不是宠物社区而是围绕“健康”这个关键词主人需要记录宠物的基础档案比如品种、年龄、体重、绝育状态、既往病史主人需要预约宠物医生做线上问诊或者预约线下体检、疫苗、驱虫主人希望通过系统记录每一次就医、疫苗、驱虫、体检的时间点形成连续健康记录管理员需要维护宠物医生信息、服务项目疫苗、体检、驱虫、绝育手术、健康资讯内容管理员需要处理预约订单、查看收入统计、用户数量、宠物数量这里有一个很多毕设新手会犯的错把功能做得特别大比如加个拼团秒杀、宠物社交广场、积分商城。结果时间全花在写CRUD上业务亮点找不到数据库表关系还乱七八糟。我个人的建议是围绕“健康档案 预约问诊 后台管理”三个核心模块做深做细再适当加一个亮眼的小功能比如疫苗到期自动提醒就足够撑起一篇80分的毕设论文了。1.2 用户角色划分前台、用户端、管理员端系统按角色拆成三类用户对应的前端页面和后端接口权限完全不同角色核心功能前端页面示例后端权限普通用户宠物主人注册登录、宠物档案管理、预约问诊、查看健康记录、查看资讯首页、宠物管理、预约挂号、个人中心只能操作自己的数据管理员用户管理、宠物审核、医生管理、服务项目管理、预约订单处理、资讯发布后台工作台、数据统计、内容管理、订单管理全部权限Spring Security拦截游客浏览健康资讯、查看服务项目、查看医生介绍首页、资讯列表、服务项目无需登录这里需要特别注意的是宠物档案设计成“需要管理员审核”。为什么因为宠物健康咨询有一定严肃性用户随意填写、或者乱传宠物照片会引发纠纷。审核状态字段设计为0待审核、1审核通过、2审核驳回每次申请预约必须先有审核通过的宠物档案。这一个小设计在答辩时可以和“业务闭环”挂钩比普通的新增宠物CRUD有说服力得多。1.3 功能模块明细你交付文档里必须出现的图我建议论文里的系统功能结构不用太复杂按下面这种方式列出来评审老师一眼就懂用户端注册登录手机号注册、用户名密码登录、JWT鉴权宠物档案新增、编辑、查看、删除软删除、审核状态显示健康记录就诊历史、疫苗记录、驱虫记录、体重变化预约管理选择服务项目、选择医生、选择时段、提交预约、支付模拟、取消预约资讯浏览健康文章列表、分类筛选、详情页个人中心修改个人信息、查看我的预约、我的宠物管理端首页数据概览今日预约数、总用户数、总宠物数、总订单金额用户管理禁用/启用账号、重置密码宠物管理审核宠物档案、查看健康记录医生管理维护医生排班、擅长领域、简介服务项目管理新增疫苗套餐、体检套餐、定价、上架/下架预约订单管理按状态筛选预约、完成/取消订单资讯管理发布/编辑/删除健康科普文章系统管理管理员账号、菜单管理如果有权限管理模块2. 技术栈选型与项目结构2.1 SpringBoot后端版本、依赖、分层这个项目后端采用SpringBoot 2.4.x版本。为什么不用SpringBoot 3.x因为3.x基于Jakarta EE很多老教程、原生JDK8环境下的插件可能出现兼容性问题对毕设来说没必要冒这个风险。用2.x版本哪怕在JDK8上也能稳定运行公司里的生产环境也大量保留2.x。如果你因为学校要求必须用3.x请注意把javax改成jakartaMyBatis的依赖也要相应调整。核心依赖清单dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.4.1/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-api/artifactId version0.11.2/version /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-impl/artifactId version0.11.2/version scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency为什么用MyBatis-Plus它和SpringBoot的整合极其顺滑内置的BaseMapper已经提供了单表CRUD你只需要写少部分自定义SQL。对宠物健康系统来说用户表、宠物表、预约表的大量操作都是单表或简单联表用MP可以节约大量时间把精力放在业务逻辑上。答辩时如果有人问“为什么用MyBatis-Plus不用JPA”你可以回答MyBatis-Plus在复杂查询时SQL可控性强XML中可以精确编写联表SQL且支持分页插件、逻辑删除、自动填充契合这个系统里报表统计和多条件筛选的场景。2.2 Vue前端版本、路由、Vuex状态管理前端采用Vue 2.x Element UI Axios Vue Router Vuex。这里特别注意一点不要一上来就上Vue 3 Vite TS除非你非常熟悉。毕设项目最重要的是“可运行”Vue 2中文资料最多Element UI组件全遇到Bug搜一下就能解决。当然如果学校要求必须Vue 3那也可以类比着做Element Plus的用法几乎完全一致。前端工程结构pet-health-web/ ├── src/ │ ├── api/ │ │ ├── user.js │ │ ├── pet.js │ │ ├── appointment.js │ │ └── admin.js │ ├── assets/ │ ├── components/ │ ├── router/index.js │ ├── store/modules/ │ ├── utils/request.js │ ├── views/ │ │ ├── Home.vue │ │ ├── user/ │ │ ├── admin/ │ │ └── login.vue │ ├── App.vue │ └── main.js在utils/request.js里统一封装Axios实例配置基准路径、请求拦截器、响应拦截器。请求拦截器的作用是自动往Header里塞token响应拦截器统一处理业务错误码和401跳转。很多新手喜欢在每一个页面里单独调用axios这样后期改域名、改超时时间、统一加loading效果的时候能改到哭。封装之后每个页面里只需要这样调用// 前端调用封装的api import { getPetList } from /api/pet; export function getPetList(params) { return request({ url: /pet/list, method: get, params, }); }2.3 MySQL数据库与SQL脚本的交付方式SQL脚本文件应该放在工程根目录下的sql文件夹里命名建议为pet_health.sql。整个脚本包含建库语句、建表语句、索引定义、初始数据管理员账号、医生信息、服务项目、资讯文章。为了答辩演示数据库脚本里还要预留一个测试账号比如admin/123456前台用户账号是user/123456。我在SQL脚本里会加几条注释说明例如-- 创建数据库 CREATE DATABASE IF NOT EXISTS pet_health DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci; USE pet_health; -- 用户表 DROP TABLE IF EXISTS sys_user; CREATE TABLE sys_user ( id BIGINT AUTO_INCREMENT COMMENT 用户ID, username VARCHAR(50) NOT NULL COMMENT 用户名, password VARCHAR(100) NOT NULL COMMENT BCrypt加密后的密码, phone VARCHAR(20) COMMENT 手机号, role TINYINT DEFAULT 0 COMMENT 0-普通用户 1-管理员, status TINYINT DEFAULT 1 COMMENT 1-正常 0-禁用, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB COMMENT系统用户表;这里有一个细节密码字段一定不要用明文。项目里用Spring Security的BCryptPasswordEncoder对密码做哈希处理SQL脚本里的初始密码也是预先加密过的一串字符串。答辩时老师如果问“你的密码存的是明文吗”你回答“存的BCrypt加密串登录时通过匹配器校验”这一个回答就能拉开层次。3. 数据库设计核心表结构与关系梳理3.1 核心数据表一览宠物健康顾问系统的表不多但关系要理清楚。我按模块拆开讲。第一组是用户与宠物档案sys_user用户表pet_info宠物信息表pet_health_record宠物健康记录表就诊、疫苗、驱虫等第二组是预约与订单appointment预约表service_item服务项目表doctor_info医生信息表第三组是内容管理health_article健康资讯文章表article_category文章分类表sys_config可选系统配置表我给这个项目的核心表画出对应关系一个用户可以有多只宠物一只宠物有多条健康记录一个用户可以给宠物提交多次预约一次预约关联一个服务项目和一个医生。这里不需要设计成多对多的复杂关系保持简洁。3.2 关键表字段详解以pet_info为例pet_info表我们单独拆开看一下你能在答辩时说出每个字段的设计理由字段类型说明设计理由idbigint主键雪花ID避免暴露自增IDuser_idbigint所属用户用户外键pet_namevarchar(30)宠物名称用户填写pet_typetinyint宠物类型1-狗 2-猫 3-其他breedvarchar(30)品种例如金毛、英短gendertinyint性别1-公 2-母birthdaydate出生日期用于计算宠物年龄weightdecimal(5,2)当前体重单位kg疫苗剂量参考avatarvarchar(255)头像图片URL存储在本地或OSSstatustinyint审核状态0-待审核 1-通过 2-驳回create_timedatetime创建时间自动填充为什么需要birthday和weight因为宠物健康顾问的核心场景之一是计算疫苗用量、驱虫用量体重是调整用药的重要依据。系统甚至可以根据生日自动计算宠物年龄如果小于3个月在预约页面会提示“幼龄宠物需谨慎用药”。这些细节拿出来讲才说明你是不是真的做过业务调研。3.3 预约表的状态设计不能只存一个普通字段appointment表是系统里业务逻辑最复杂的一张表我来完整讲一遍CREATE TABLE appointment ( id BIGINT PRIMARY KEY COMMENT 预约ID, order_no VARCHAR(32) NOT NULL COMMENT 预约编号, pet_id BIGINT NOT NULL COMMENT 宠物ID, doctor_id BIGINT COMMENT 医生ID, service_id BIGINT NOT NULL COMMENT 服务项目ID, user_id BIGINT NOT NULL COMMENT 下单用户ID, appoint_date DATE NOT NULL COMMENT 预约日期, appoint_time VARCHAR(20) COMMENT 时段如09:00-10:00, status TINYINT DEFAULT 0 COMMENT 0-待确认 1-已完成 2-已取消 3-已过期, remark VARCHAR(255) COMMENT 备注, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINEInnoDB COMMENT预约表;状态字段为什么有四种现实中用户提交预约后管理员需要确认能否接待如果时间冲突管理员可以取消用户自己也可以取消。已过期状态则是通过定时任务扫描超过预约日期仍未完成的订单自动标记。你可以设计一个简单的Spring定时任务每天凌晨扫描一次更新过期状态。这个定时任务也是答辩时的加分项它说明你不只是会写CRUD还考虑了数据时效性。3.4 SQL脚本与接口文档的配合使用这一步很多人会忽略SQL脚本和接口文档不是两个独立文件而是必须一一对应。接口文档里所有字段的命名、类型、长度都要和表结构严格一致。我见过不少项目SQL脚本创建时间为create_time但接口文档写的是createDate结果前后端联调时各种字段对不上浪费大量时间。建议多花一小时整理一份“字段映射表”放在接口文档或团队wiki的附录里。表格形式就三列表字段、实体类属性、前端参数名。比如数据库的user_id对应后端Java的userId对应前端传给后端的参数也是userId。这样无论是后端开发还是前端开发拿到文档后直接照着字段名代码全程不用猜。4. 后端实现与核心接口设计4.1 JWT认证授权不用Session用Token宠物健康顾问系统的用户端和管理员端都在同一个后端服务里认证方式选择JWTJSON Web Token。为什么要用JWT因为前后端分离架构下前端可能是Vue单页面应用后端接口无法依赖Session保持状态而JWT天然适合无状态接口。JWT的逻辑是用户登录成功后后端把用户ID、用户名、角色编码等信息放进Token里用密钥签名返回给前端。前端每次请求都在Header里带上Authorization: Bearer token后端通过过滤器解析Token获取当前登录用户并判断是否有权限访问当前接口。在SpringBoot里实现JWT的核心配置类Component public class JwtAuthenticationFilter extends OncePerRequestFilter { Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String token request.getHeader(Authorization); if (token ! null token.startsWith(Bearer )) { token token.substring(7); // 解析token获取用户ID } chain.doFilter(request, response); } }节选代码只做示意。真正的项目里还要配置Spring Security的SecurityFilterChain放行登录接口、注册接口、资讯列表接口拦截其他的接口校验Token。注意“鉴权”和“认证”的区别登录只做身份认证对预约管理、后台管理等接口还要做角色鉴权普通用户的Token不能访问管理员接口。4.2 接口路径设计Restful API规范接口文档里我用Restful风格来组织路径。宠物系统的接口路径设计如下功能模块请求方式路径说明登录注册POST/api/auth/login登录注册用户POST/api/auth/register注册获取当前用户GET/api/user/info获取当前登录用户信息宠物列表GET/api/pet/list获取当前用户的宠物列表新增宠物POST/api/pet/add新增宠物档案编辑宠物PUT/api/pet/update修改宠物档案删除宠物DELETE/api/pet/delete/{id}删除宠物档案服务项目列表GET/api/service/list服务项目列表游客可看医生列表GET/api/doctor/list医生列表创建预约POST/api/appointment/add用户提交预约取消预约PUT/api/appointment/cancel/{id}用户取消预约我的预约GET/api/appointment/myList当前用户的预约列表后台宠物列表GET/api/admin/pet/list管理员查看所有宠物审核宠物PUT/api/admin/pet/audit管理员审核宠物档案每个接口在接口文档里都应该有请求参数说明、请求示例、响应结果示例、错误码说明。用Postman或者Apifox导出的Markdown格式是很标准的。下面是我常用的一个接口文档模板### 创建预约接口 - POST /api/appointment/add - 认证方式Bearer Token - 请求参数 | 参数名 | 类型 | 是否必填 | 说明 | |--------|------|---------|------| | petId | Long | 是 | 宠物ID | | doctorId | Long | 否 | 医生ID若为空则系统自动分配 | | serviceId | Long | 是 | 服务项目ID | | appointDate | String | 是 | 预约日期格式yyyy-MM-dd | | appointTime | String | 是 | 预约时段如09:00-10:00 | - 请求示例 json { petId: 1, doctorId: 2, serviceId: 3, appointDate: 2024-06-10, appointTime: 09:00-10:00 }响应示例{ code: 200, message: 预约提交成功, data: { appointmentId: 101, orderNo: 202406100001 } }### 4.3 分层架构与代码组织 后端项目包结构建议这样组织这也是毕业设计论文中“系统实现”一章的目录来源pet-health-server/ ├── config/ │ ├── SecurityConfig.java │ ├── MybatisPlusConfig.java │ └── CorsConfig.java ├── controller/ │ ├── AuthController.java │ ├── PetController.java │ ├── AppointmentController.java │ └── admin/ │ ├── AdminPetController.java │ └── AdminAppointmentController.java ├── service/ │ ├── PetService.java │ ├── AppointmentService.java │ └── OrderNoGenerator.java ├── mapper/ │ ├── PetMapper.java │ └── AppointmentMapper.java ├── entity/ │ ├── PetInfo.java │ └── Appointment.java ├── dto/ │ ├── LoginDTO.java │ └── AppointmentDTO.java ├── common/ │ ├── Result.java // 统一返回体 │ ├── ResultCode.java │ └── GlobalExceptionHandler.java └── PetHealthApplication.java统一返回体ResultT类包含code、message、data三个字段所有接口返回的都是Result对象。这样前端可以在response拦截器里统一判断code是否为200如果不是就直接弹出message里的错误信息不用每个页面重复写异常处理逻辑。 ### 4.4 定时任务与业务提醒的实现细节 我前面提到了“疫苗到期提醒”这个小亮点这里把实现方式也讲一下。在宠物健康记录表pet_health_record里每一条疫苗记录都要保存next_due_date字段表示“下次接种日期”。然后我们写一个定时任务 java Component public class VaccineRemindTask { Autowired private PetHealthRecordService recordService; // 每天9点执行一次 Scheduled(cron 0 0 9 * * ?) public void remind() { // 查询未来7天内需要到期接种疫苗的记录 // 根据user_id组装提醒内容 // 向用户发送站内信或者生成系统通知到通知表 } }这里不需要真的集成短信服务因为在毕设答辩环境里申请短信服务比较麻烦。可以建一张notification表定时任务往notification表里插数据。前端用户登录后在个人中心看到“未读提醒数”点击进入查看提醒列表。一组完整的“任务调度 数据生成 前台展示”链路就闭环了。这也比单纯做一个“疫苗记录新增”功能强很多因为它是系统主动帮你做健康管理而不是你手动去查记录。5. 前端实现与页面交互5.1 前端路由设计与权限控制Vue Router的配置里要区分“公开页面”和“需要登录的页面”。公开页面包括首页、健康资讯列表、服务项目介绍、登录注册页。需要登录的页面包括宠物管理、预约管理、个人中心、后台管理。使用Vue Router的beforeEach导航守卫做全局判断router.beforeEach((to, from, next) { if (to.meta.requiresAuth) { const token localStorage.getItem(token); if (!token) { next({ path: /login, query: { redirect: to.fullPath } }); } else { next(); } } else { next(); } });另外还有一个细节管理员后台路由和普通用户路由要分开。最简单的方式是路由表里加meta属性role: admin在导航守卫里检查当前用户的角色。从后端获取的userInfo存到Vuex里刷新页面时再从本地存储里恢复。这样就不会出现用户手动改路由进入后台页面的情况。5.2 核心页面拆解你上台演示时怎么讲首页宠物健康顾问平台的首页不要只放一张图。我建议放这几个区域顶部导航、轮播图/功能入口、医生团队展示、服务项目展示、健康资讯列表。首页是答辩演示的第一屏一定要做得干净整洁。Element UI的Card组件和Layout组件配合很容易搭出现代感。宠物管理页进去是一张宠物卡片列表每张卡片显示宠物头像、名字、品种、年龄、体重右上角有“健康档案”按钮。宠物健康档案页是亮点用时间线组件展示疫苗、驱虫、体检、就诊记录。答辩时可以现场演示新增一只宠物提交后管理员账号在后台审核审核通过后再去给这只宠物预约疫苗服务流程演示完整。预约页这是整个平台最核心的交互页面。用户先选择宠物下拉框只显示审核通过状态的宠物、选择服务项目疫苗、体检、驱虫等、选择医生根据服务项目自动筛选出相关医生、选择日期和时段。选完日期后后端接口返回该日期已被占用的时段列表前端将这些时段置灰。这一步就是“排班校验”在答辩时非常出效果。!-- 预约时段的禁选用例 -- el-date-picker typedate v-modelappointmentDate changeloadAvailableTime/el-date-picker el-select v-modeltimeSlot el-option v-foritem in availableTimeList :keyitem :labelitem :valueitem :disableditem 09:00-10:00 currentDateHasConflict /el-option /el-select5.3 前端表单校验与体验细节Element UI的表单校验功能要用满。宠物年龄、体重、手机号都可以写上自定义校验规则。比如体重不能为负数手机号要符合11位手机号正则。虽然后端接口也有参数校验Valid注解但前端校验的作用是让用户不用等接口返回就能得到即时反馈这是体验层面的优化。答辩时你完全可以直接说“前端校验只负责提升用户体验真正数据安全的是后端校验”显示你的意识是完整的。另外还要注意全局Loading效果。在Axios的请求拦截器里开启Loading遮罩在响应拦截器里关闭。这样每次提交表单时用户不会重复点击按钮体验会好很多。5.4 前端如何应对“图片上传”和“富文本编辑”宠物头像上传、健康资讯的配图都涉及文件上传。最简单的方案是后端提供一个上传接口接收MultipartFile文件保存到本地磁盘的static/upload目录然后返回一个URL。前端上传组件用el-upload设置action地址为后端的上传URL。注意跨域问题后端需要配置Cors允许前端的请求头带token。如果担心上传文件的安全可以在application.yml里配置限制文件大小spring: servlet: multipart: max-file-size: 5MB max-request-size: 20MB健康资讯发布时候的正文可以简单用textarea或者el-input typetextarea输入纯文本Markdown语法再配合一个Markdown渲染组件。不建议在毕设里引入完整富文本编辑器因为图片处理、样式内联、XSS过滤都挺麻烦。用Markdown足够应付资讯展示而且渲染出来的样式干净答辩演示不会因为富文本样式问题穿帮。6. 本地环境搭建与部署实操6.1 环境要求照着做就能跑这里列一个我在项目README里写的环境清单读者直接按这个准备就行JDK 1.8 推荐8u202以上版本Maven 3.6用3.6即可IDEA自带的也行MySQL 5.7或8.0Node.js 14 / npm 6IDE后端用IDEA 2020及以上市场版本前端用VSCode或IDEA都可以后端启动步骤用Navicat或命令行执行pet_health.sql脚本完成建库建表打开application.yml修改数据库连接的用户名和密码IDEA导入后端工程Maven自动下载依赖运行PetHealthApplication.java启动类看到端口8080日志就成功了前端启动步骤把pet-health-web目录拖入VSCode在终端执行npm install安装依赖修改src/utils/request.js里的baseURL指向http://localhost:8080执行npm run dev浏览器访问localhost:3000或者Vue配置文件里指定的端口6.2 本地部署常见的坑第一个坑是端口占用。后端默认8080端口很容易被其他进程占用。如果在IDEA启动时提示端口被占用可以去application.yml里改端口号或者杀掉占用进程。前端如果默认8080需要把Vue项目配置里的host和port改掉改成3000或者8081避免和后端冲突。第二个坑是MySQL字符集。如果创建数据库时没指定utf8mb4中文字段插入数据可能报Incorrect string value错误。所以执行SQL脚本前一定要先确认前面那句CREATE DATABASE ... DEFAULT CHARSET utf8mb4已经带上不要单独用Root工具手工建库。第三个坑是跨域。后端不配置CORS的话浏览器会拦前端请求。我的建议是后端写一个全局CorsConfig允许所有来源、所有方法、带token的请求头Configuration public class CorsConfig { Bean public CorsFilter corsFilter() { CorsConfiguration config new CorsConfiguration(); config.addAllowedOriginPattern(*); config.addAllowedHeader(*); config.addAllowedMethod(*); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, config); return new CorsFilter(source); } }6.3 打包与部署把前后端合并到一个jar很多同学会在答辩前遇到一个问题演示项目需要开两个进程一个后端jar一个前端npm run dev。你要是能把前端打包进后端只跑一个jar答辩环境会显得非常专业。做法是前端执行npm run build生成dist目录将dist目录下的所有文件复制到后端工程的src/main/resources/static目录下重新打包后端工程执行mvn clean package -DskipTests部署时直接java -jar pet-health-server.jar然后访问http://localhost:8080就可以了这样做的原理是SpringBoot把static目录作为静态资源映射路径。前端打包后本质上是HTML、JS、CSS文件SpringBoot把它们当作静态资源处理后端接口仍在8080端口前端请求的baseURL可以改成相对路径/api避免跨域。这个操作在论文“系统部署”章节里非常加分。6.4 接口文档如何生成从Postman到Apifox接口文档不仅是交付材料也是你自己调接口时的重要工具。我推荐直接用Apifox或Postman来管理接口因为它们支持从后端代码自动生成接口清单还支持在线分享文档。毕设答辩时评委老师可能会要求你展示接口文档一份在线链接或者PDF版本的接口文档会比口头描述要清晰很多。如果你是手工整理接口文档注意每份文档都要包含请求URL、请求方法、请求头、请求体JSON示例、成功响应示例、失败响应示例、每个字段的说明。文档不需要长篇大论重点是让人照着能调通接口。我自己整理接口文档的习惯是“先写好再调接口”前端还没开始写代码前先把接口定义清楚再让前端照着文档对接这样能减少联调沟通成本。7. 常见问题与排查技巧实录7.1 登录接口报401Token相关配置这种情况多半是拦截器放行配置的问题。Spring Security默认拦截所有接口如果你没有在SecurityConfig里排除登录和注册接口那么请求打到后端就被拦住了返回401。处理方式是在SecurityConfig的web.ignoring()中放行/api/auth/login、/api/auth/register、以及静态资源路径。还有一种情况是前端带token的Header名不对后端解析的是Authorization前端却传了token或者baseURL配置错误。排查思路先用Postman直接请求接口判断是后端配置问题还是前端传参问题再把问题定位到具体端。7.2 Mysql执行SQL脚本时报错字段名冲突MySQL 8.0以上版本order、desc、rank这类词是保留关键字。如果表里有字段名恰好叫order或desc执行建表语句会报错。解决办法有两个给字段起名时避开保留关键字例如预约表里的字段叫order_no不叫order或者给表名和字段名都加上反引号。我的建议是表名统一用单数名词字段名尽量用下划线命名法与数据库关键字区分开。7.3 MyBatis-Plus查询不到数据驼峰映射问题数据库字段是create_timeJava实体属性是createTime。如果没有开启MyBatis-Plus的下划线转驼峰配置查询出来的createTime就是null。在application.yml里这样配置mybatis-plus: configuration: map-underscore-to-camel-case: true这个配置默认是true但如果你的配置文件手滑覆盖错了位置就可能失效。另外如果你自定义了XML里的SQL结果映射同样需要设置columncreate_time propertycreateTime。7.4 前端页面能打开但空数据后端返回字段不对这是前后端分离项目联调阶段最常见的Bug。前端请求宠物列表接口接口返回成功data也是数组但页面上列表空白。打开控制台看数据后发现后端返回的字段是petName前端绑定的却是pet_name。这就是没有遵循“接口文档字段规范”导致的。排查步骤先在浏览器Network面板里看接口真实返回的JSON逐字段比对前端绑定字段如果接口返回正常就检查前端代码里字段名是否完全一致。养成“后端先返回前端照文档绑定”的习惯这种问题可以少一半。7.5 SpringBoot项目启动失败依赖版本冲突最常见的冲突来自spring-boot-starter-security和某些旧版spring-web版本或者是JWT相关依赖的版本不对。我的建议是不要手动组合各种第三方版本尽量用spring-boot的parent pom统一管理版本再引入其他库时也要注意它们是否兼容SpringBoot 2.4.x。启动时报错看第一行关键信息多半是“No qualifying bean of type”或者“ClassCastException”根据提示去搜解决方案通常很快。8. 答辩准备与项目扩展建议8.1 答辩时大概率被问的问题结合多年评审经验我把宠物健康顾问系统最容易遇到的答辩问题整理成一份速查列表为什么选SpringBoot不选SpringMVCSpringBoot简化了配置和部署内置Tomcat支持自动装配和约定优于配置但底层还是SpringMVC这套机制。JWT和Session有什么区别JWT无状态服务器不保存会话数据天然适合分布式Session需要存储在服务端或Redis状态集中管理。JWT的缺点是注销难、过期时间控制不够灵活。如何保证预约数据不冲突数据库里对(doctorId, appointDate, appointTime)增加唯一约束同时后端在插入预约之前先查一次占用情况并开启事务。严谨的做法还要加分布式锁但毕设做到唯一索引级别已经够用。权限控制怎么做的用Spring Security JWTToken里绑定角色。前端通过路由守卫隐藏页面后端通过注解或拦截器校验角色权限。数据库为什么用InnoDBInnoDB支持事务、行级锁、外键约束。预约和订单模块对数据一致性要求高需要事务保证。8.2 如何把这个项目做出“亮点”普通CRUD的宠物管理系统很多你的毕设要脱颖而出不能只在“能不能跑”上做文章。我提供三个可以让系统更有分量的扩展方向第一个方向是“疫苗到期提醒 消息中心”。我已经在前面介绍了定时任务的实现这里在补充一点可以给消息中心做成一个tab页未读消息显示红点点击后标记已读。答辩时现场演示创建一条7天后即将过期的疫苗记录然后把定时任务的时间改到一分钟后刷新页面就能看到提醒效果直接拉满。第二个方向是“预约排班冲突校验”。不要只做一个简单的“选时间提交预约”要把医生排班设计成一张独立的doctor_schedule表。后台可以给医生配置一周的排班表。用户端选日期后系统先查医生当天是否有排班再查该时段是否已满。这个逻辑能体现你对业务细节的思考。第三个方向是“数据可视化看板”。管理后台除了预约订单的数据统计可以加一个ECharts页面展示近7天预约量趋势、服务项目销售占比、用户增长曲线。前端安装echarts依赖后端提供一个统计接口返回聚合数据也就是一两天的开发量。但这个看板在视觉效果上非常加分答辩时也容易调动评委兴趣。8.3 项目后续还能往哪里扩展如果做完毕设之后想继续完善我建议按照下面的优先级发展第一集成微信小程序端宠物主人通过小程序预约更方便。第二引入消息队列/定时任务框架例如使用SpringBoot整合RabbitMQ或Redisson处理预约高峰。第三把本地文件存储换成阿里云OSS把头像和体检报告进行云存储。第四做一个小程序端的健康档案PDF导出功能用户可以一键导出宠物体检报告用来给线下医生查看。每一步的扩展都能对应到真实企业级开发场景这样面试聊起来也有话题。9. 经验总结与最终交付清单9.1 一个毕设项目最终应交付哪些材料很多同学以为“写完代码就算完”实际上到了毕业设计验收阶段你还要交出一整套让人“看了就能跑、跑了能演示、演示能讲明白”的材料。我给这个宠物健康顾问系统整理一份完整交付清单可以直接跟着准备项目源码后端pet-health-serverMaven工程前端pet-health-webNode工程SQL脚本pet_health.sql包含建库、建表、初始数据接口文档Markdown/PDF格式包含所有核心接口部署说明文档README.md写明环境要求、启动步骤、常见问题解决演示账号说明管理员admin/123456普通用户user/123456答辩PPT项目背景、系统架构图、功能模块、数据库设计、核心接口、项目演示、总结展望毕业设计论文包含选题背景、技术栈、需求分析、设计、实现、测试、总结再强调一次README的重要性。答辩前你不可能每次都手动帮评委配置环境一份好的README能让任何人在30分钟内把项目跑起来。如果评委在你的电脑上看到一篇逻辑清晰、步骤完整的说明文档第一印象绝对加分。9.2 项目开发过程中的几点真实体会把这个宠物健康顾问系统完整做下来我最大的体会是后期最耗时间的其实不是写代码而是“接口不一致”和“重新拆表”。前期设计数据库时多花一点时间把表关系、状态字段、审核逻辑想清楚后面开发效率会提升好几倍。如果一上来就写代码做到一半发现预约表缺少宠物关联或者发现用户表没有角色字段再回头改表、改接口、改前端整个项目节奏就乱了。另一个体会是一定要用版本管理工具哪怕只是自己一个人写。我把整个项目放在Git仓库里每完成一个功能模块就提交一次。这样即使某一天改崩了也能轻松回退到上一个稳定版本。答辩前回顾git log还能清楚看到每段时间做了什么回答“你的工作量主要在哪”就特别有底气。第三个体会是选一个你自己真正感兴趣的领域做毕设会让整个过程舒服很多。如果你喜欢宠物、有养宠物经验你在做需求分析时的很多判断会自然带上“真实感”——知道接种疫苗要注意幼接年龄知道绝育手术需要术前禁食知道体检报告要给主人讲解指标。这些细节全都是普通CRUD模板给不了你的。9.3 给准备拿这套项目做毕设的同学的最后建议如果你要交付的是毕业设计别把数字写进标题里当噱头而是把项目当成一个完整的产品来对待。做完这个宠物健康顾问系统你要能做到几乎不用看代码就能在白板上画出完整的“用户端功能 管理员端功能 数据库表关系 核心接口链路”。这样答辩时无论老师怎么追问你都能从容应对。如果时间真的非常紧至少要把这三件事做扎实第一数据库建表脚本流畅执行确保不报错第二登录和核心预约流程完整跑通能演示。第三接口文档至少有十个核心接口格式清晰。做到这三点评委会认为你“对项目有完整的掌握能力”。剩下的功能可以少但是不能乱不能有半成品页面。我个人在实际操作中的体会是宠物健康顾问系统比传统的“学生管理系统”“图书馆管理系统”多了一层业务温度它需要你去理解宠物主人和医生之间的关系理解健康管理不只是记录更是提醒和预防。如果你把这层理解写进论文写进答辩演示时的每一句描述里这套项目的价值就远不止是一个毕设作品。
返回列表