
每年毕业设计的节点上总有一批人被“基于SpringBoot和Vue的XX平台系统”这类题目困住。看起来只是把两个热门技术拼在一起实际上从环境搭建到前后端联调每一步都有坑。今天我就拿“宠物之家平台系统”这个题目把完整的设计思路、技术选型、核心代码和踩坑记录全部摊开讲帮你少走弯路。这个题目要做的本质上是一个前后端分离的Web应用前端用Vue搭建用户界面后端用SpringBoot提供接口数据库存业务数据。宠物之家这个主题则决定了业务模块——宠物领养、寄养、寻宠、养宠知识分享、用户管理等。整套系统做下来既能展示你对SpringBoot的理解又能体现Vue的组件化开发能力是典型的全栈毕设项目。适合JAVA方向、软件技术专业、或者想转行做Web开发的学生参考。1. 项目整体设计与思路拆解1.1 宠物之家平台到底要解决什么问题很多同学拿到题目第一反应是“这不就是一个宠物信息发布网站吗”。如果只做到这一步功能太单薄答辩时老师几个问题就能问住你。我建议把平台定位成“面向城市养宠人群的一站式宠物服务平台”核心解决三个痛点宠物领养信息不透明、临时寄养找不到靠谱渠道、新手养宠缺乏知识经验。围绕这三个痛点整个平台拆成前台和后台两个大端。前台面向普通用户提供宠物浏览、领养申请、寄养预约、养宠论坛、个人中心等功能后台面向管理员提供宠物审核、用户管理、寄养订单管理、论坛内容管理、数据统计等功能。这样一拆业务逻辑就清晰了也方便后面写功能清单和数据库设计。还有一点要提前想明白普通用户和管理员是同一套登录体系但权限不同。所以后端必须要有用户角色区分接口要有权限控制。常见的做法是用JWT做登录令牌再通过拦截器判断请求携带的token对应的用户角色管理员接口单独校验。这一点在答辩时是加分项。1.2 为什么选SpringBoot加Vue这套组合选SpringBoot和Vue不是因为它俩是“网红技术”而是这套组合在毕业设计场景下收益最高。SpringBoot解决了传统SSH项目配置繁琐的问题内置Tomcat打一个jar包就能跑还支持自动配置、starter机制写后端接口非常快。你只需要关注Controller、Service、Mapper这几层业务代码不用折腾一堆XML配置。Vue这边最大的优势是组件化开发和响应式数据绑定。写页面就像搭积木一个导航栏组件、一个宠物卡片组件、一个表单组件写好了到处复用。配合Element UI组件库后排管理页面也能做得有模有样不输商业项目。而且Vue对新手相对友好没有React那么多概念模板写起来跟原生HTML很像学习曲线平缓很多。前后端分离还有一个隐形好处接口数据格式统一用JSON前端拿到数据自己渲染后端不需要关心页面长什么样。调试的时候用Postman单独测接口用浏览器单独看页面哪边出了问题一眼就能定位。相比老式JSP项目混在一起写这种模式出错的概率小得多。1.3 功能模块怎么拆才既合理又容易实现功能模块的拆分直接决定你后面写代码的量和工作量。我建议按角色拆。普通用户端保留这些核心模块用户注册登录、宠物信息浏览支持按品种、地区、年龄筛选、领养申请、寄养预约下单、收藏宠物、论坛发帖回帖、修改个人资料。管理员后台保留登录、宠物发布审核管理员可以自己发宠物信息也可以审核用户申请的发布、用户管理禁用/启用账号、寄养订单管理、论坛帖子管理、数据统计大屏。为什么这么拆首先每个模块都可以单独做成一个功能点写论文时也方便对应章节做到“系统实现”部分有东西可写。其次功能之间有依赖关系比如领养申请必须在用户登录后发起申请的时候要关联宠物ID和用户ID这在数据库设计时就是外键关系写起来有整体感。千万别贪多。有人把在线支付、地图定位、聊天室全加进去结果代码量直接翻番最后答辩前连项目都跑不起来。毕设的本质是把你学过的东西完整展示一遍不是做一个产品。CRUD做好、权限做好、前后端交互做好已经能达到优秀毕设的标准把精力花在代码质量和文档上更划算。2. 技术栈版本选择与环境搭建实录2.1 后端技术栈选型和版本避坑后端我推荐用SpringBoot 2.7.18不要用SpringBoot 3.x。原因很现实3.x版本把javax包全改成了jakarta很多教程和网上的代码片段直接用不了MyBatis-Plus的兼容性也要专门配版本。你现在搜到的“SpringBoot项目搭建教程”可能有一半是2.x的老方法对3.x全部失效。答辩又不要求你用最新版本稳定够用就行。JDK选1.8。虽然已经有些年头了但它跟SpringBoot 2.x是绝配而且IntelliJ IDEA里新建项目时默认对JDK 1.8支持依然很好。我当时就踩过坑装了JDK 17结果IDEA创建SpringBoot项目时一堆插件不兼容后来换回1.8什么问题都没有。现在有些老师要求必须用新版JDK那就装两个版本项目级切换不要让它成为拦路虎。数据库用MySQL 8.0即可SQLyog或Navicat任选一个可视化工具。连接Maven仓库慢的问题直接修改Maven的settings.xml文件把镜像换成阿里云地址。这个操作一定要做否则拉依赖能拉到你怀疑人生。我见过太多新手卡在这一步项目还没创建就先崩溃了。2.2 前端技术栈选择和Vue版本策略前端我建议Vue 2.6加Element UI而不是Vue 3加Element Plus。原因很简单教程最多、踩坑资料最全。Vue 3虽然性能更好但组合式API、Teleport这些新特性对新手来说转移成本高。而且很多学校老师的课件、历届学长源码都是Vue 2你出了问题要找参考也容易。Node.js版本装14.x或16.x。之前有同学装了Node 18启动Vue项目直接报错查了半天发现是OpenSSL版本兼容性问题。后来重新装Node 16运行npm install和npm run serve就正常了。还有Vue CLI单独装npm install -g vue/cli这样创建项目时可以用图形化界面和命令行两种模式。前端项目创建用Vue CLI的默认预设就可以但有两个配置要提前改一是vue.config.js里加devServer代理把 /api 开头的请求转发到后端8080端口解决开发环境的跨域问题二是安装axios、element-ui、vue-router、vuex这几个核心依赖npm install axios element-ui vue-router3 vuex3注意Vue 2配vue-router3Vue 3才用vue-router4版本别搞混了。2.3 环境搭建的常见翻车现场第一个翻车点IDEA里新建SpringBoot项目时如果选择了Spring Initializr默认下载地址是start.spring.io在国内经常超时。解决办法是改成阿里云的Spring Initializr地址https://start.aliyun.com。改完之后创建项目秒成。第二个翻车点项目创建成功但pom文件的依赖一直报红。不要急着删IDEA先看Maven本地仓库有没有文件。把mvn -v在命令行跑一下确认Maven能运行再检查IDEA里Maven设置是不是用了自己解压的Maven而不是IDE自带的。如果仓库没加载执行reimport一般能解决。第三个翻车点前端创建Vue项目卡在“chromedriver”下载。这是Node环境下的老问题建议在安装依赖时不要直接用npm install而是用npm install --legacy-peer-deps或者把package.json里的chromedriver依赖删掉这个包本地跑项目根本用不上。3. 数据库设计与后端核心实现细节3.1 数据库表结构设计先把字段想清楚数据库是整个系统的基础表设计得好不好直接影响后期开发效率。宠物之家平台我建议建七张核心表用户表user、宠物表pet、领养申请表adopt_apply、寄养订单表boarding_order、帖子表post、评论表comment、收藏表favorite。再根据需求看要不要加公告表notice。用户表user的字段id、username、password加密存储、nickname、phone、avatar、roleUSER/ADMIN、status0正常1禁用、create_time。宠物表pet的字段id、name、category猫/狗/其他、breed、age、gender、vaccine_status是否已打疫苗、description、image、status0待审核1展示中2已领养、user_id发布人、create_time。领养申请表adopt_apply的字段id、pet_id、user_id、reason领养理由、phone、status0待审核1通过2拒绝、create_time。寄养订单表boarding_order的字段id、user_id、pet_id、boarding_start、boarding_end、price、remark、status0待处理1进行中2已完成、create_time。这些字段一听答辩问题“你的业务表有哪些字段”你就能对答如流。表与表之间的关系也要心里有数。用户和宠物是一对多一个用户可以发布多只宠物用户和领养申请是一对多宠物和领养申请是一对一一只宠物被申请多次但只通过一条。这些关系在写SQL时要用JOIN查出来代码别写在实体里绕来绕去。3.2 后端项目分层结构和关键注解解析后端代码分层不要乱按这个包结构写controller接口层、service业务层、mapper数据访问层、entity实体类、config配置类、common公共类统一返回结果、异常处理、工具类。新建SpringBoot项目时基础依赖加上Spring Web、MySQL Driver、MyBatis-Plus、Lombok。这里重点说MyBatis-Plus它是MyBatis的增强工具不用写XML基本CRUD方法直接继承BaseMapper就能用。分页查询时先new Page对象再用selectPage方法最后在配置类里加PaginationInnerInterceptor拦截器。这是高频考点竞赛和面试都爱问。写实体类的时候字段名和数据库列名用驼峰对应MyBatis-Plus默认开启驼峰映射Java里写createTime数据库列create_time自动匹配。类上标TableName(表名)主键标TableId(type IdType.AUTO)这样可以省掉写XML映射文件的麻烦。Controller层接口的RESTful风格要规范。比如宠物列表接口GET /api/pet/list?page1size10categorycat宠物详情接口GET /api/pet/detail?id1提交领养申请POST /api/adopt/apply。返回值统一用Result对象包装结构包含code状态码、message提示信息、data数据。这样前端拿到数据后只需判断code是否为200再取data字段就行。3.3 JWT登录认证与权限拦截的实现用户登录接口是系统第一个要做的接口。前端会把用户名和密码作为JSON传给后端ControllerService层先用QueryWrapper查用户表比对密码是否一致。密码不能明文存储用BCrypt加盐哈希这也是Spring Security里用的标准密码加密算法比MD5安全得多。就算数据库被脱库也不怕密码泄露。登录成功后用jjwt库生成token返回给前端。token里放userId和role这两个信息。代码很简单String token Jwts.builder() .setSubject(user.getId().toString()) .claim(role, user.getRole()) .setExpiration(new Date(System.currentTimeMillis() 1000 * 60 * 60 * 24)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact();这个secretKey是签名密钥自己写死一个字符串就行相当于给token盖章。之后每次前端请求都在请求头里带Authorization字段值就是token。后端写一个拦截器继承HandlerInterceptor在preHandle方法里从请求头取token解析校验如果解析失败就返回401状态码如果成功把userId和role放到request的attribute里供后续接口使用。拦截器注册到WebMvcConfigurer中注意放行登录接口、注册接口、宠物列表和详情接口其他接口都拦截。这里有个关键细节拦截器只做token合法性校验管理员接口再多加一步角色判断。比如在Controller上写PreAuthorize(hasRole(ADMIN))或者干脆在Service层判断当前登录用户role是否等于ADMIN。我推荐后者代码更直观答辩时也好解释。3.4 宠物领养与寄养的业务逻辑细节宠物发布流程用户在前端填写宠物信息上传图片后端收到后先保存图片文件把图片路径存到pet表的image字段pet状态初始为0待审核管理员在后台审核后改为1展示中。这个流程考验文件上传的处理。SpringBoot处理文件上传用MultipartFile接收文件然后通过transferTo方法保存到本地目录。图片保存要单独加配置不然上传大小有限制。在application.yml里设置spring: servlet: multipart: max-file-size: 10MB max-request-size: 10MB同时设置一个静态资源映射把本地保存目录映射成URL路径这样前端就可以用 http://localhost:8080/image/xxx.jpg 直接访问图片。也可以把图片转成base64存在数据库但这样数据库会膨胀不推荐。领养申请的时候要判断这只宠物是否已经被领养过如果pet表状态已经是2前端列表里就直接隐藏“申请领养”按钮。后端在提交申请接口时也要再查一次避免并发下出现一只宠物被两个人同时领养成功的情况。查询之后修改pet状态为2这一步要放在同一个事务里用Spring的Transactional注解包起来。寄养订单算价逻辑前端选好开始时间和结束时间传一个宠物类型过来后端根据单价和天数算出总价。比如猫每天50元狗每天80元两狗一猫十天就是28010150102100元。这个计算可以在前端做展示后端下单时根据存储的单价重新算一遍防止别人改前端数据骗价。这个点写进论文就是“业务安全校验”。4. 前端页面与交互功能实现4.1 Vue初始化、路由配置和页面结构前端项目结构建议这样组织router文件夹放路由配置views文件夹放页面组件components文件夹放复用组件api文件夹放接口请求方法utils文件夹放axios封装。页面组件划分首页Home.vue、宠物列表PetList.vue、宠物详情PetDetail.vue、领养管理AdoptManage.vue、寄养预约Boarding.vue、论坛Forum.vue、个人中心Profile.vue、登录注册Login.vue。后台管理单独一个布局包含宠物管理、用户管理、订单管理等页面。路由配置里/login和/register是公开的首页和宠物列表也公开给游客浏览但点击“申请领养”时要判断是否登录。实际操作是给路由加meta属性比如meta: { requiresAuth: true }然后在router.beforeEach全局前置守卫里判断。router.beforeEach((to, from, next) { if (to.meta.requiresAuth !getToken()) { next(/login); } else { next(); } });getToken方法从localStorage取token。这个判断逻辑也是前端权限控制的核心答辩论及“你系统怎么做权限控制”时前端守卫和后端拦截器都要提。4.2 Axios请求封装、拦截器和接口调用axios封装是前端项目的灵魂。直接在组件里用axios.get写请求代码会非常乱。更好的做法是先在utils/request.js里创建一个axios实例统一配置baseURL和超时时间然后加请求拦截器每次请求前把localStorage里的token放进请求头再加响应拦截器后端返回401时自动跳转登录页。service.interceptors.request.use(config { const token getToken(); if (token) { config.headers[Authorization] token; } return config; }); service.interceptors.response.use( response { const res response.data; if (res.code ! 200) { this.$message.error(res.message); return Promise.reject(new Error(res.message)); } return res; }, error { if (error.response error.response.status 401) { removeToken(); router.push(/login); } return Promise.reject(error); } );统一封装之后每个页面调接口就非常清爽。比如宠物列表在api/pet.js中写一个方法export function getPetList(params) { return request({ url: /pet/list, method: get, params }); }组件里导入这个方法后调用即可。传参方式POST用dataGET用params这个规则要统一不然前后端对不上会报参数不合法。4.3 核心页面组件实现与交互细节首页设计不要花里胡哨突出平台定位即可。顶部导航栏放Logo、菜单、登录按钮中间放一个轮播图展示领养活动或平台公告下面放三只“推荐宠物”卡片点击卡片跳转宠物详情页。宠物卡片用el-card嵌套el-image图片懒加载属性lazy可以直接用Element UI封装好的。宠物列表页要有筛选栏和分页。筛选条件包括宠物类别下拉框、地区输入框点击查询后触发getPetList请求把page、size、category、region作为查询参数传给后端。分页组件用el-pagination注意current-page和page-size要同步到data里的变量current-change和size-change事件对应重新加载数据。查询结果用v-for循环渲染宠物卡片卡片上放“查看详情”按钮。宠物详情页是转化核心。页面分三块左侧宠物图片大图右侧基本信息名字、性别、疫苗状态、描述下方两个大按钮“申请领养”和“收藏”。点击申请领养弹出el-dialog对话框让用户填写联系电话和申请理由提交到后端。这个过程要用表单校验el-form的rules属性写基本规则电话必填且格式合法理由必填且不少于10个字。后台管理页面向管理员布局用el-container嵌套el-aside和el-main。左侧菜单用el-menu点击菜单切换右侧的el-tab-pane或子路由页面。宠物管理表格用el-table数据列绑定pet对象属性操作列放“通过审核”“拒绝”“下架”按钮每行操作调用不同接口。表格数据量大时可以用el-table的remote筛选功能但毕设不强制普通显示即可。论坛页面实现发帖和回帖功能我是用el-timeline来展示帖子列表每条时间轴节点显示用户头像、昵称、发帖时间、帖子内容点开后有回复框和已有的回复列表。论坛比较能体现“用户与用户之间的交互”比单纯的信息展示类系统有深度是答辩时可以多聊的模块。5. 项目汇总梳理与部署验证5.1 前后端联调要注意的细节联调阶段最烦的是跨域问题。前端devServer代理配置就能解决devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } }这样前端请求 /api/pet/list 会被转发到 http://localhost:8080/pet/list后端不用额外处理跨域。如果后端也配置了CrossOrigin开发时没问题但放到服务器上两台不同域名时容易冲突建议统一由前端代理解决。接口报错要对齐格式。很多同学前后端联调前端报错“Cannot read property data of undefined”一看是后端返回的不是标准json格式状态码错误时直接返回了一个字符串。这种情况就要用统一的Result对象兜底。后端全局异常处理器加RestControllerAdvice捕获未知异常返回Result.error(“系统异常”)至少前端不会白屏。密码修改、头像上传这类操作后端接口尽量在请求参数用DTO接收不要直接用实体类接收所有字段。比如用户实体有role字段直接接收用户更新请求别人可以篡改自己的角色为管理员这是严重的安全漏洞。分期一下更新资料接口用UserUpdateDTO只包含昵称和头像字段这样天然防止越权修改。5.2 打包部署步骤和答辩前自查清单后端打包IDEA右侧Maven面板点击package命令在target目录下生成jar包。执行命令java -jar 项目名.jar 启动。打包前注意application.yml里数据库连接地址要改成你服务器或正式环境的MySQL地址账号密码也要对上。前端部署执行npm run build会在dist目录生成静态文件。本地环境访问直接双击dist里的index.html是不行的路由会失效必须用nginx或其他静态服务器部署。在nginx配置里把location / 指向dist目录设置try_files $uri $uri/ /index.html这是为解决Vue路由history模式刷新404的问题。如果不想配nginx也可以把dist文件夹放在后端项目resources/static目录下重新打包这样jar包自带页面直接访问8080端口就行省事很多。答辩前自查清单我每次都会给学生列一份注册新用户能否正常登录、未登录情况下访问个人中心是否跳转登录页、管理员登录后能否看到后台菜单、宠物审核通过后前台是否展示、领养成功后宠物状态是否变为已领养、寄养订单计算价格是否正确、论坛发帖回帖是否刷新即可看到。把这七条功能流程在答辩前完整跑一遍基本不会现场翻车。6. 常见问题与排查技巧实录6.1 高频问题速查表问题现象可能原因解决方案IDEA创建SpringBoot项目超时Spring Initializr国外地址访问慢改用阿里云地址 https://start.aliyun.comMaven依赖一直下载失败未配置国内镜像settings.xml加阿里云镜像删除本地仓库.lastUpdated文件后重新reimportJDK版本冲突导致项目启动失败JDK版本过高或过低统一使用JDK 1.8与SpringBoot 2.7.18MySQL连接报Public Key Retrieval错误数据库连接URL未配置allowPublicKeyRetrievalURL加参数allowPublicKeyRetrievaltrueuseSSLfalse前端npm install报ERRNode版本过高安装Node 14或16或加--legacy-peer-deps前端页面能打开但接口请求404后端接口路径与前端请求不一致检查后端Controller的RequestMapping路径和前端api方法url是否匹配登录后访问其他接口返回401token处理链路问题检查axios请求拦截器是否把token放到Authorization请求头后端拦截器是否正确读取分页数据返回total为0未配置MyBatis-Plus分页插件添加PaginationInnerInterceptor配置类上传图片后无法访问静态资源映射缺失WebMvcConfigurer中addResourceHandlers把保存目录映射到URL路径Element UI组件样式不生效未完整引入样式文件main.js里import element-ui/lib/theme-chalk/index.css6.2 我踩过几次坑之后总结的经验第一个坑是关于版本号的。刚开始图省事直接在pom里写了最低版本没写具体版本号结果拉下来SpringBoot 3.x版本所有javax的import全报错。后来统一锁版本号SpringBoot 2.7.18、MyBatis-Plus 3.5.3、jjwt 0.9.1再没出过奇怪问题。这里强调一下毕设项目要优先保证代码能跑不要盲目追求新版本。第二个坑是前后端联调时接口数据格式不统一。一会儿后端返回的是List一会儿返回的是Map前端写死的取数逻辑经常拿不到数据。后来我强制要求所有接口返回Result对象即使List也放在data里面从此世界清净了。前端取数永远是这样res.data唯一例外是分页查询分页数据额外多包一层最终返回的是{list: [], total: 0}前端取res.data.list。第三个坑是登录状态在页面刷新后丢失。之前用Vuex存储用户信息刷新页面后state重置页面虽然没有跳转登录页但很多接口请求失败。后来用vuex-persistedstate插件把Vuex里的用户信息自动持久化到localStorage刷新后自动恢复。这也是提升用户体验的一招还挺加分的。6.3 从项目实操到答辩展示的技巧答辩的时候很多同学只拿代码跑一遍演示老师很快就失去兴趣追问几个细节就慌。我建议准备一页“核心功能架构图”或者“系统功能模块图”手绘也行展示的时候按这条线讲用户从注册登录开始浏览宠物列表发起领养申请管理员审核寄养订单生成论坛发帖讨论。每一步都点出背后用到的技术点JWT鉴权、MyBatis-Plus分页、文件上传、事务控制。老师常问的几个问题提前准备答案。比如“为什么用SpringBoot不用SSH”答SpringBoot自动配置减少XML配置内嵌Tomcat一键部署starter生态完善。“Vue的双向绑定原理”答基于Object.defineProperty数据劫持和发布订阅模式Vue 2里用Object.definePropertyVue 3改成Proxy。“MyBatis-Plus和MyBatis的区别”答MP是增强工具内置通用Mapper方法分页插件好用但不改变SQL写法。再准备一段数据统计的展示。在后台管理页面加一个简单的ECharts图表统计宠物领养数量按月变化趋势或者宠物品种分布饼图。这个功能技术上不难前端装echarts依赖拼一个饼图数据结构后端写一个统计接口返回JSON效果却非常直观能给答辩老师留下深刻印象。这也符合“基于SpringBoot和Vue的宠物之家平台系统”里面“平台”二字的定位带有一定数据分析能力。在这套系统做完之后我自己又扩展了一个公告管理模块管理员可以发布平台公告前台首页轮播图下面滚动展示。总体功能上多了一块内容论文也多了几百字可写。所以我建议你核心功能做扎实之后有余力就往两个方向扩展一是大数据展示加图表统计二是文件处理加导出Excel报表。这两个方向都绕不开前后端联调技术含量还高能给毕设增加不少亮点。最后再分享一个实际经验把整个项目的api文档单独整理成Markdown包括每个接口的请求方式、参数、返回值、示例。开发后期越来越多的前端页面要调接口你边开发边记录联调时会非常高效写论文“系统设计”章节也更省力。答辩时老师问接口怎么设计的你直接打开自己的接口文档讲思路清清楚楚比临时翻代码强太多。