SpringBoot+Vue宠物健康顾问系统:从架构设计到前后端分离实践

发布时间:2026/10/5 13:56:45
SpringBoot+Vue宠物健康顾问系统:从架构设计到前后端分离实践 1. 项目概览这个“宠物健康顾问”到底是什么先说结论这套SpringBootVue的宠物健康顾问系统核心是做“宠物医院的轻量级数字化管理”。它不是一个花架子demo而是把真实宠物门诊日常要干的几件事——宠物档案建档、在线问诊、疫苗提醒、健康资讯发布——全串起来的完整业务闭环。我拿到源码的第一感觉是该有的模块一个不少而且代码分层很规整确实适合当毕设或课设的基底也适合想搞懂前后端分离项目到底怎么协作的学习型选手。这套系统的技术栈非常主流后端是SpringBoot MyBatis-Plus MySQL前端是Vue 2 Element-UI Axios鉴权走JWT。没有引入一堆花里胡哨的中间件也没有人为制造复杂度就是一套“企业里最常见的组合”。对于学生来说这意味着参考价值极高——你去任何一家中小型公司实习看到的新项目大概率就是这类结构。它能解决的问题也很聚焦宠物主人可以注册登录、给自家宠物建档案、在线预约兽医问诊、查看问诊记录和健康建议兽医端可以管理预约、填写诊断和用药建议管理员则负责账号管理、资讯发布、基础数据维护。整个权限体系是“三种角色 一套路由”前端控制页面显示后端控制数据权限典型的RBAC思路。适合谁来参考我大概分成三类第一类是毕设选题和宠物医疗沾边的这套源码能帮你省掉大量从零搭建的时间第二类是课设要求“完整Web系统”的它的功能复杂度刚好卡在“工作量足够又不至于失控”第三类是单纯想学SpringBoot和Vue怎么配合的——把这份源码拆开看一遍比你看十篇零散教程都管用。2. 技术选型思路与整体架构拆解2.1 为什么偏偏是SpringBoot Vue我经常被学生问现在新框架那么多微服务、云原生都喊得震天响为什么毕设还得用SpringBoot Vue答案很现实这套组合是“性价比之王”。SpringBoot让Java后端开发变得极其轻量内嵌Tomcat不用打WAR包一个main方法就能起服务Vue则是目前国内中小型项目前端占有率最高的框架之一组件化开发让页面复用变得简单而且Element-UI组件库能直接拖出后台管理界面需要的表格、表单、弹窗。对比一下其它选项你就明白了如果你用JSP Servlet做传统单体应用虽然也能实现功能但前后端完全耦合代码维护成本高答辩时也容易被问“为什么不用更现代的技术”如果你强行上Spring Cloud微服务那根本是给自己挖坑——服务发现、配置中心、网关、分布式事务每一层都需要时间学习而一个宠物健康顾问系统根本撑不起微服务的体量。所以SpringBoot Vue是恰到好处既体现了“先进工程实践”又不会因为过度设计卡住你的进度。这套系统的架构是标准的前后端分离前端跑在Node环境中开发模式下默认8080端口通过代理转发请求后端跑在SpringBoot内嵌Tomcat中默认8081端口两者通过RESTful API通信。前端负责页面渲染、表单校验、路由跳转后端负责业务逻辑、数据校验、持久化、权限校验。中间用JSON格式交换数据JWT做身份凭证。这种架构的好处是前端和后端可以并行开发我改接口文档你调页面互不阻塞。2.2 后端分层与前端工程结构解读后端代码是经典的“Controller → Service → Mapper”三层结构。Controller层只做参数接收和结果封装不写业务代码Service层处理核心业务逻辑比如预约状态流转、用户注册时的密码加密Mapper层用MyBatis-Plus的BaseMapper单表CRUD几乎不用写SQL复杂查询用QueryWrapper构造条件。实体类直接用TableName和数据库表对应字段命名用驼峰和数据库下划线自动映射省掉一大半xml配置。我特意看了一眼项目的包结构凡是按controller、service、mapper、entity、common、config分包的项目层次都非常清晰。common包里放的通常是统一返回结果类Result、异常处理器、工具类config包里放的是跨域配置、拦截器配置、MyBatis-Plus分页插件配置。如果你拿到源码后要改东西先按包名找文件就行了。前端工程用的是Vue CLI标准脚手架src下分api、router、store、views、components、utils几个目录。api目录集中封装了所有请求方法比如login(loginForm)内部调用request({url:/user/login, method:post, data:loginForm})router里定义了路由表而且用了动态路由——根据登录用户的角色动态添加菜单和路由store用Vuex存用户信息和token刷新页面后从localStorage恢复。这套结构很典型面试官要是问你“Vue项目怎么组织”照着这套说就行。2.3 登录鉴权和权限控制的实现思路登录鉴权是这类系统最容易被问到的点。这套系统用了JWTJSON Web Token流程很简单用户提交账号密码后端校验通过后生成一个包含用户ID、用户名、角色的签名token返回给前端前端把它存到localStorage之后每次请求都在请求头里带上Authorization: Bearer token后端拦截器校验token的合法性解析出用户信息存入ThreadLocal后续业务代码需要当前用户ID时直接取。JWT的好处是服务端无状态不用存session天然适合前后端分离。但有两个坑我提醒一下一是token过期时间要设置合理太短用户频繁重新登录太长又不利于安全一般设置2到4小时二是JWT一旦签发在过期前是无法主动作废的所以如果系统要求“管理员封禁用户后用户立刻失效”就得额外引入Redis黑名单机制。就毕设场景而言简单点用拦截器 token过期时间足够。权限控制方面后端是在拦截器里校验角色比如RequireRole(ADMIN)之类的自定义注解凡是没有对应角色的请求直接返回403。前端则是通过Vue Router的beforeEach路由守卫和动态菜单控制不同角色看到不同侧边栏。对于课设答辩你把这套“前端控制显示、后端控制访问”的权限设计讲清楚已经是加分项了。3. 数据库设计与核心功能模块解析3.1 数据表设计理清宠物健康数据的主线数据库是这套系统的地基设计得好不好直接决定后面的编码量。我打开SQL脚本看了一遍核心表大概是这么几张user用户表账号、密码、真实姓名、手机号、角色类型、pet宠物档案表宠物名、品种、性别、生日、体重、是否绝育、appointment预约表宠物ID、医生ID、预约时间、状态、consultation问诊记录表预约ID、症状描述、诊断结果、用药建议、reminder提醒表宠物ID、提醒类型、提醒日期、是否已处理。这几张表之间的关系不难看出来一个用户可以养多只宠物所以pet表用user_id外键关联一个宠物可以多次预约、多次问诊预约和问诊是一对一关系一次预约对应一次问诊但一个宠物可以有多条预约和多条问诊记录提醒表依附于宠物档案用来做疫苗和驱虫提醒。对整个系统来说这就是“用户-宠物-问诊”三条主线所有功能都围绕它们展开。具体建表时的几个细节值得学一下一是时间字段统一用datetime并且默认值设为CURRENT_TIMESTAMP方便后续排序二是状态字段用tinyint存储比如预约状态0待确认、1已确认、2已完成、3已取消而不是用字符串这样存储更省查询更快三是所有表都加了deleted逻辑删除字段和create_time、update_time这是MyBatis-Plus的标配翻数据时不会出现“把记录删了就再也找不回来”的尴尬。3.2 核心业务流程一宠物建档与疫苗提醒宠物建档是最基础的功能但业务上有个隐藏需求一个宠物主可能有三只猫两条狗建档时得区分清楚。系统里通过pet表关联user_id实现“我的宠物列表”前端根据当前登录用户加载对应宠物后端查询时用LambdaQueryWrapper.in或eq限定用户维度。疫苗提醒的实现思路是定时任务扫描。系统启动时开启一个Spring的Scheduled定时任务每天跑一次扫描reminder表里“未处理且提醒日期距今天小于等于N天”的记录把需要提醒的用户ID查出来生成待提醒消息。这个场景在毕设中属于亮点了——你要能在答辩时说出“我用Spring内置的Scheduled定时任务扫描数据库查到过期未处理的疫苗记录自动推送给宠物主”老师会觉得你确实理解了业务而不只是跟着视频抄代码。3.3 核心业务流程二在线问诊与预约状态机预约模块是系统里业务逻辑最重的部分。我常说预约状态不要用if-else写散而应该脑子里有一张“状态机”图用户发起预约时状态为待确认医生接诊后变已确认医生填写诊断报告并提交后变已完成用户或医生有权取消。每一个状态变更都要在Service层校验当前状态是否合法比如“已完成”状态不能被直接改成“待确认”。在线问诊的业务流程大概是用户选择宠物和医生填写症状描述和预约时间生成预约记录兽医在后台看到待确认列表点击确认后问诊记录生成用户可以在“我的问诊”里查看医生的诊断建议。这里面有个容易遗漏的细节医生填写诊断建议时除了文字内容往往还伴随用药建议字段所以问诊记录表要预留medicine_advice字段免得后期加需求时又要改表。我实际跑通这套流程时发现它的Controller参数用了RequestBody接收JSON前端提交的数据要保证字段名跟后端实体字段一致——比如petId如果前端传成pet_id就会直接接收不到这是新手最容易踩的坑之一。遇到这种问题最快的排查方式是在浏览器Network面板看请求体里的字段名再回到代码里对齐别上来就改后端。3.4 数据字典与健康资讯模块的加分设计健康资讯模块虽然业务简单但做得好不好看就体现在这些细节上。资讯表通常有标题、封面图URL、摘要、正文内容、发布时间、作者ID。后台管理端提供富文本编辑框前端门户页展示文章列表和详情。做成独立模块后也方便毕设答辩时演示“管理员发布资讯、用户端实时看到”的功能。数据字典是容易被忽略的加分点。宠物品种、疫苗类型、提醒类型这些字段如果硬编码在页面里后期改起来非常痛苦做成数据字典表前端通过接口拉取枚举数据渲染下拉框后端校验时也从字典里取值代码会干净很多。这套系统里虽然字典没有做得特别复杂但设计思路上已经预留了类似结构。你想在答辩时展示工程素养把“数据字典如何避免魔法值散落各处”讲出来是很加分的一环。数据库表与业务模块的对应关系我整理成了一张速查表业务模块核心表关键字段说明登录/注册userusername, password, rolerole区分用户/医生/管理员宠物档案petuser_id, name, breed, weight一只宠物归属一个用户预约问诊appointmentpet_id, doctor_id, statusstatus用状态机控制问诊记录consultationappointment_id, symptom, diagnosis一对一连结预约疫苗提醒reminderpet_id, remind_type, remind_date定时任务扫描日期健康资讯articletitle, cover, content, author管理员发布数据字典dicttype, key, value下拉框动态数据4. 从零跑通环境准备与项目启动实战4.1 环境版本清单千万别用最新的用能跑的老规矩先放一套我实际验证过“一定能跑起来”的环境配置。这套系统的依赖版本不算激进后端SpringBoot用的是2.7.xJava用8或者11都行MySQL用5.7或者8.0都兼容前端是Vue 2.6 Vue CLI 4/5。千万别图新鲜上来就装SpringBoot 3.x那玩意默认Java 17起步很多老依赖比如javax.servlet换成jakarta.servlet会直接把项目搞崩。我见过太多人“明明按教程做的却一直报错”最后发现是版本兼容性问题。环境组件推荐版本备注JDK1.8 或 118就够没必要升Maven3.6阿里云镜像配置好Node.js14 或 16Vue CLI 5要求Node 12MySQL5.7 或 8.08.0记得关SSL或加参数IDEA2021社区版也可用VSCode任意前端开发用第一次接触JavaWeb项目的同学我建议先把这三个装好JDK、Maven、MySQL。Node.js如果只跑前端装个16版本就够了。装环境这块不要跳步但凡有一个环节的版本对不上后面启动报错能把人折磨到怀疑人生。4.2 后端启动步骤从导入Maven工程到接口可用后端启动分四步。第一步在IDEA里选择“导入Maven工程”选中后端根目录pom.xml等待依赖下载完成。如果下载慢得像蜗牛就去~/.m2/settings.xml里把中央仓库换成阿里云镜像这一步能节省你80%的等待时间。第二步修改application.yml里的数据源配置——数据库地址、账号、密码以及mybatis-plus的配置。这里要注意MySQL 8.0的驱动类名是com.mysql.cj.jdbc.Driver而且URL得加上serverTimezoneAsia/Shanghai否则时间会差8个小时如果用旧驱动连8.0会报SSL连接错误直接在URL后加useSSLfalse即可。第三步在Navicat或命令行里执行项目的SQL脚本把表和测试数据都导进去。第四步启动SpringBoot的main方法看到Tomcat started on port(s): 8081说明后端起来了。测一个最简单的接口——登录接口用Postman发一条POST请求如果返回JSON里带token说明环境没问题。我提醒一下第一次启动时如果端口被占用就在application.yml里换个觉得陌生的端口比如8089避免你本机某个程序占着8081。4.3 前端启动步骤依赖安装、代理配置与联调前端的启动比后端稍微麻烦一点。在项目前端目录下打开终端执行npm install装依赖。这一步有两个常见坑一是Node版本太高有些老依赖编译失败解决办法是降Node版本或者换npm镜像源npm config set registry https://registry.npmmirror.com二是node_modules下载到一半就报错多半是网络不稳或权限不足删除node_modules和package-lock.json后重装即可。依赖装完后最关键的是vue.config.js里的代理配置。开发环境中前端默认跑在8080端口后端跑在8081前端请求/api开头的接口时通过devServer的proxy项转给http://localhost:8081。比如前端请求/api/user/login代理会转发到后端的/user/login。这样做的好处是避免了跨域问题而且上线部署时也只需改代理目标地址。联调的第一步是先把登录页跑通。打开浏览器访问http://localhost:8080输入管理员账号密码如果能跳转后台首页整条链路就走通了。走不通的时候先看浏览器Console的报错分清是404还是跨域还是500。404大概率是路径少了前缀跨域报错是代理没生效500就去看后端日志多半是SQL写错或者空指针。4.4 核心代码快照登录接口、JWT拦截器、分页查询这系统里有几个代码片段非常典型值得拿出来单独看。第一个是登录Controller它接收用户名和密码调用userService.login()返回自定义的Result对象里面封装了token和用户信息。第二个是JWT拦截器核心逻辑在preHandle方法里从请求头取token用Jwts.parser()解析解析成功就把用户ID放到request的attribute里失败就返回401。第三个是分页查询用MyBatis-Plus的Page对象加LambdaQueryWrapper一句.page()就能拿到分页数据免手写SQL。// 登录接口核心代码 PostMapping(/login) public Result login(RequestBody LoginDTO loginDTO) { String username loginDTO.getUsername(); String password loginDTO.getPassword(); // 校验账号密码 User user userService.getOne(new LambdaQueryWrapperUser() .eq(User::getUsername, username) .eq(User::getPassword, MD5Util.encode(password))); if (user null) { return Result.error(用户名或密码错误); } String token JwtUtil.createToken(user.getId(), user.getRole()); return Result.success(new HashMapString, Object() {{ put(token, token); put(user, user); }}); }// 拦截器里解析token Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String token request.getHeader(Authorization); if (token ! null token.startsWith(Bearer )) { token token.substring(7); try { Claims claims JwtUtil.parseToken(token); request.setAttribute(userId, claims.get(userId)); request.setAttribute(role, claims.get(role)); return true; } catch (Exception e) { response.setStatus(401); return false; } } response.setStatus(401); return false; }// MyBatis-Plus分页查询 PageAppointment page new Page(current, size); LambdaQueryWrapperAppointment wrapper new LambdaQueryWrapper(); wrapper.eq(Appointment::getDoctorId, doctorId) .orderByDesc(Appointment::getCreateTime); IPageAppointment result appointmentMapper.selectPage(page, wrapper);Vue侧对应有三个经典片段axios请求拦截器在请求头加token路由守卫判断登录状态动态渲染表格数据。这三个片段配合后端两个核心类就是整个前后端交互的精髓。把这几段代码背下来你就能在答辩现场从容回答“登录流程怎么实现的”“分页怎么做的”这种高频问题。5. 常见问题与排查技巧实录5.1 MySQL连接报错SSL、驱动、时区三连坑我统计过后端启动失败的原因里MySQL相关问题占了一半还多。最典型的是这个报错Establishing SSL connection without servers identity verification is not recommended——这不是代码逻辑错误而是MySQL 8.0默认要求SSL连接旧驱动却不会自动判断。解决办法是在连接串后面加?useSSLfalse。第二种是ClassNotFoundException: com.mysql.jdbc.Driver——驱动类名用错了。MySQL 5.7用com.mysql.jdbc.Driver没问题但8.0必须用com.mysql.cj.jdbc.Driver并且pom里依赖版本也得同步更新成mysql-connector-java8.x。第三种是时区问题报错里有The server time zone value字样在连接串后加serverTimezoneAsia/Shanghai就解决了。建议你拿到源码后直接把连接串一次性写成jdbc:mysql://localhost:3306/pet_health?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghai后面省心。5.2 Maven依赖下载失败与镜像源配置Maven依赖下不下来也是新手必踩的坑。默认中央仓库在国外访问慢到经常超时恢复的办法是配置国内镜像源。打开Maven的settings.xml在mirrors节点新增阿里云镜像mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror改完之后到IDEA里点一下Maven面板的刷新按钮重新拉取。如果某个依赖还是死活拉不下来可能是本地仓库有损坏的半成品文件把对应依赖的整个目录从~/.m2/repository里删掉再重新reimport。这里再提醒一句依赖首次下载特别耗时间尽量一次性等完别中途取消否则容易出现各种奇怪的缓存错乱。5.3 前后端联调跨域、404、字段不一致联调阶段遇到最多的问题是跨域。如果你不用代理直接从8080的页面请求8081的接口浏览器会拦截响应。解决方案有两种第一种是我前面说的vue.config.js代理第二种是在后端加一个全局CORS配置类。两者选其一就行不要同时配否则可能出现“预检请求被拦截”的反效果。404问题先确认请求路径是否跟后端Controller的RequestMapping完全一致注意大小写和后缀。举个例子如果后端是/user/login前端请求恰好是/api/user/login代理里又没做pathRewrite把/api去掉那永远404。字段不一致问题多出在时间类型上——后端返回LocalDateTime时默认格式是2024-06-01T10:30:00前端如果不认得这个格式就得在后端配置统一的时间格式化Jackson序列化器。这些小细节调试的时候一旦踩中没有两小时很难发现。5.4 部署阶段的另外两个高频卡点很多同学的毕设要求线上演示这就需要把前端打包后塞进后端。Vue项目里执行npm run build会生成dist目录把里面的内容复制到后端项目的src/main/resources/static下再重启后端访问http://localhost:8081就能看到前端页面。这里有个关键打包后的静态资源默认路径是/如果后端接口都在/api下两者就不会冲突。但如果前端路由用了history模式刷新页面会404解决办法是把history模式改成hash模式或者在后端加一个索引页转发控制器。另外一个高频卡点是内存不足。SpringBoot项目默认启动参数堆内存不够大的时候导入大量数据后可能直接OOM。解决办法是在IDEA的运行配置里增加VM参数-Xms256m -Xmx512m前端Node服务如果提示内存不足用NODE_OPTIONS--max-old-space-size1024给足空间。5.5 常见问题速查表报错现象常见原因快速解法MySQL SSL连接错误MySQL 8.0 旧驱动URL加useSSLfalseClassNotFound驱动类版本驱动类名变更换成com.mysql.cj.jdbc.DriverMaven下载卡死默认源太慢配阿里云镜像并删除损坏缓存前端请求404代理未转对或路径缺/多前缀核对proxy和pathRewrite前端请求500SQL报错或空指针看后端控制台日志定位行号跨域预检失败前端代理与后端CORS重复配置二选一保留页面刷新404Vue history路由改hash模式或添加转发Controller端口被占用本机其他进程占用端口用netstat -ano查PID并关闭进程6. 毕业答辩前必须吃透的几个“为什么”源码能跑通只是第一步答辩时老师更关注你“理解不理解”。我建议把下面这几个问题提前准备好为什么用JWT而不是Session关键术语是“无状态、分布式友好、扩展性好”。为什么MyBatis-Plus能少写SQL因为它基于MyBatis做了通用Mapper的二次封装复杂查询照样能构造。为什么前端能根据角色动态显示不同菜单因为登录返回的user对象里有role字段路由守卫每次跳转时动态添加对应权限路由。有几个点还可以作为加分项来发散。如果你的系统有定时任务就讲清楚Scheduled的cron表达式如果有文件上传就讲一下OSS存储和本地存储的区别如果有图表统计就说是用ECharts做的数据可视化。怕就怕代码写完了面对“这个功能怎么实现的”只能回答“就跟视频里一样”——这不叫理解叫背诵。给一个练习小技巧把源码从头到尾读三遍。第一遍只读Controller和路由搞明白“有哪些接口、每个接口干什么”第二遍读Service实现搞懂“每个接口背后的业务逻辑是怎么组织的”第三遍读Mapper和数据库表弄清楚“数据在哪里、怎么查出来”。三遍读完之后你甚至能不看源码自己在纸上画出整张系统的架构图。能做到这一步答辩基本稳了。我再唠叨一句关于二次开发的方向。这套源码的底子很干净你可以在它上面加很多有意思的东西比如给预约加个简单的排班功能让医生能设置可预约时间段比如加一个导入导出功能用EasyExcel把宠物信息导出成Excel比如引入Redis缓存热门资讯。每加一个功能都要记得在论文里描述需求背景、表结构设计、接口设计和页面效果四个部分。这些扩展不追求技术的炫酷但追求工程上的完整和逻辑自洽这才是毕设图纸该有的深度。从我实际翻源码、跑环境、调接口的经验来看这套系统最大的优点是没有刻意堆坑每一行代码都有迹可循。只要你能把环境跑起来再顺着业务走一遍项目逻辑基本就刻在脑子里了。后面无论是换数据库、改前端UI还是加新模块你都清楚该动哪一层。这才是这份“源码”最值钱的地方。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询