宠物领养系统毕设源码拆解:SpringBoot3+Vue3前后端分离实战解析

发布时间:2026/10/7 16:49:56
宠物领养系统毕设源码拆解:SpringBoot3+Vue3前后端分离实战解析 简介这套宠物领养系统是一份面向2025届毕业设计/课程设计的完整项目资源选题聚焦现实中的动物领养场景适合计算机科学与技术、软件工程等专业学生参考。项目采用主流前后端分离模式后端用SpringBoot3简化业务开发前端以Vue.js3构建交互界面MySQL8负责用户、宠物和领养申请等数据的持久化流程覆盖宠物展示、注册登录、领养申请、后台审核与管理等环节同时从用户隐私和SQL注入防护角度做了安全考量。资源包共6个文件、总大小103.3MB包含三个zip压缩包主源码、返修源码和返修文档、一个sql数据库脚本、一张需求文档截图和一段mp4操作录屏能够支撑从环境搭建到功能验证的完整学习过程。目前已有128人学习/下载。参考本资源时可以重点学习前后端接口交互、数据表设计、状态流转实现等核心点录屏教程能帮助快速启动项目需求文档辅助理解整体功能边界。整体而言这是一套结构清晰、资料齐全的实战型毕设方案对想掌握SpringBoot3Vue3开发流程的读者颇具价值。1. 宠物领养系统 JAVASpringBoot3Vue.js3从选题到答辩这份毕设源码的完整拆解做毕设最怕的不是不会写代码而是选了一个自己撑不起来的题目。宠物领养系统听起来简单但真动手才发现它牵扯的东西比预期多领养流程有状态流转、宠物信息有多条件检索、用户有角色权限、后台有审核闭环前端还得把地图、相册、表单校验这些体验做出来。这套 JAVASpringBoot3Vue.js3 的毕业设计源码正好卡在一个微妙的平衡点上——功能量够写一篇像样的论文技术栈又没冷门到答辩时被问倒。它的完整度接近一个能直接上线的商用模板登录注册、宠物发布与浏览、领养申请、后台审核、管理员面板都是现成的拿到手改改名字和细节就能跑。适合三类人Java 后端基础不牢想攒实战经验的新手、论文已经开题只差可运行系统的学生、以及想用最短时间完成课程设计交付的在职党。这篇笔记按我实际拆项目的顺序来写先看结构和环境再跑通核心链路最后讲我复现两遍才踩平的坑。2. 工程全景与启动环境先搞清楚这包代码怎么组织再动手跑2.1 前后端分离的双工程结构目录上先做减法解压这份资源后你会看到两个独立工程目录前端叫pet-frontend后端叫pet-backend这是 SpringBoot3 Vue3 项目最常见的组织方式。前端是 Vite 脚手架生成的标准 Vue3 工程核心代码集中在src下api目录按模块拆 Axios 请求views目录按角色拆页面管理员、普通用户、领养审核页router里做路由守卫。后端是 Maven 工程包名通常是com.example.pet或个人学号三层结构清晰controller只做参数接收和结果包装service写业务逻辑mapper是 MyBatis-Plus 的接口层。如果你刚拿到源码我建议先别急着启动花 10 分钟把目录过一遍认清资源给你的是「可运行系统」不是「示例片段」。环境方面有几个硬性要求缺一个都会在启动时报出莫名其妙错误。JDK 必须是 17 及以上SpringBoot3 底层是 Jakarta EEJDK8 连依赖都解析不出来Node.js 建议 18 LTS 或更高Vue3 的生态工具链在高版本下兼容性更好Maven 用 3.8 即可IDE 用 IntelliJ IDEA 会比较顺手Eclipse 对 Lombok 插件的支持不如 IDEA 稳定。建议先建一个干净的目录把前后端源码放进去再分别执行下面命令验证依赖环境。# 检查 Java 版本必须输出 17 或更高 java -version # 检查 Maven 版本3.8 以上比较稳 mvn -v # 检查 Node 版本18 及以上 node -v # 检查 npm 包管理器可用 npm -v这里每个命令都有一个实际意义。Java 版本决定了 SpringBoot3 能否加载jakarta.servlet相关类版本低了启动直接报NoClassDefFoundErrorMaven 版本影响依赖下载可靠性和spring-boot-maven-plugin的兼容性Node 版本关系 Vite 的构建效率旧版本可能不支持某些 ES 新语法。四项全过再往后跑就有底了。2.2 数据库初始化脚本建库、初始数据、连接参数一次性配齐这套系统的数据层用的是 MySQL 5.7 或 8.0资源包里附带了pet_db.sql初始化脚本通常在backend/sql或doc目录。脚本内容包含建库语句、十几张业务表用户表、宠物表、领养申请表、宠物类型表等以及必要的初始数据——比如管理员账号、宠物类别枚举。我惯用的做法是先手动建一个空库再导入脚本这样能避免脚本里CREATE DATABASE与本地已有库冲突。导入后检查两张关键表的行数确认数据没丢比如用户表应该有一条admin记录宠物表至少有几条演示数据这两个检查项能在后面前后端联调时帮你快速区分「代码 bug」还是「数据缺失」。后端数据库连接配置集中在application.yml里这是启动前必改的一处。如果不改IDEA 里会看到 MyBatis 报一堆Communications link failure。配置本身简单但要注意 MySQL8 的驱动类名是com.mysql.cj.jdbc.DriverMySQL5.7 用com.mysql.jdbc.Driver也能跑但会有弃用警告。下面是一个我改完能直接用的最小配置块。server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/pet_adoption?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的密码 servlet: multipart: max-file-size: 10MB max-request-size: 50MB提示serverTimezoneAsia/Shanghai这一项很关键不配置的话 Java 8 时区处理会跟 MySQL 的 UTC 默认时区打架时间字段存进去和查出来差 8 小时在领养申请的「提交时间」这类字段上会直接出问题。max-file-size配置的是宠物图片上传上限毕设答辩演示时传手机拍的照片10MB 足够不要设太大否则前端等待上传的时间会很难看。2.3 前端启动前的固定动作装依赖、配代理、看默认端口前端项目拿到手第一步永远是在根目录执行npm install。由于 lock 文件通常已提交这步理论上很稳但国内网络源容易出现 node-sass 或 electron 这类二进制包下载卡住可以用 npmmirror 镜像来兜底。装完依赖后vite.config.js里有一个开发代理配置它把前端地址/api开头的请求转发到后端 8080 端口你在浏览器里看到的localhost:5173页面可以无缝请求localhost:8080的接口。这套代理是前后端分离项目的标配不用 Nginx 也能联调。// vite.config.js import { defineConfig } from vite import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, // 如果后端接口前缀不带 /api就打开重写 // rewrite: (path) path.replace(/^\/api/, ) } } } })把这段配置看完你基本理解开发模式下前后端是怎么协作的。changeOrigin: true是为了让后端收到的请求头里的 Host 变成后端地址避免一些后端校验 Origin 的逻辑误判rewrite这行注释掉的代码是处理路径前缀的如果你的后端Controller里的RequestMapping本来就带/api就需要把它打开否则请求会变成/api/api/...。不管毕设论文里怎么写架构图这个代理机制建议在答辩时提一句能显示你是真跑通过联调的而不是只贴了代码。3. 后端核心链路拆解SpringBoot3 MyBatis-Plus 下的领养业务实现3.1 实体设计与数据表映射MyBatis-Plus 的注解用法后端这块作者用了 MyBatis-Plus 而不是原生 MyBatis这是一个很适合毕设的选择——单表 CRUD 几乎不用写 SQL内置的BaseMapper提供现成的selectById、insert、updateById等方法代码量能少一半。实体类上用TableName注解映射表名用TableId标记主键用TableField处理驼峰和下划线字段名的转换。下面这组代码是从宠物表实体里摘出来的典型写法领养系统这类业务表都差不多的套路。Data TableName(pet) public class Pet { TableId(type IdType.AUTO) private Long id; private String name; private String breed; private Integer age; private String gender; private String status; TableField(cover_url) private String coverUrl; TableField(create_time) private LocalDateTime createTime; }这段代码的逻辑是Data来自 Lombok自动生成 getter/setter一个实体类省几十行样板方法TableId(type IdType.AUTO)声明主键自增插入宠物记录时不用手动赋值 idTableField(cover_url)解决 Java 驼峰属性名与数据库下划线字段名的映射MyBatis-Plus 默认开启驼峰转换但显式声明更保险。参数方面要注意LocalDateTime对应的数据库类型应当为datetime如果你在建表脚本里写的是timestamp在跨时区环境下会有精度或偏移问题。3.2 领养申请与状态机流转事务注解的正确放置点领养申请是整个系统的核心业务它的状态通常分为待审核、已同意、已拒绝、已完成四档。用户的「提交申请」动作和后端管理员的「审核通过」动作在代码里都涉及两个以上表的状态变更——申请记录表要插数据宠物表状态要改成被领养或待审核。这类操作一定要加事务否则用户在填写完申请、点击提交的一瞬间系统异常会出现申请记录已写入但宠物状态未改变的数据错乱。ServiceImpl 里通常会这么写Transactional(rollbackFor Exception.class) public boolean applyAdopt(AdoptApplyDTO dto) { // 1. 校验用户是否重复申请同一宠物 Long count applyMapper.selectCount( new LambdaQueryWrapperAdoptApply() .eq(AdoptApply::getUserId, dto.getUserId()) .eq(AdoptApply::getPetId, dto.getPetId()) ); if (count 0) { throw new BizException(您已申请过该宠物请勿重复提交); } // 2. 写申请表 AdoptApply apply new AdoptApply(); BeanUtils.copyProperties(dto, apply); apply.setStatus(AdoptStatusEnum.PENDING.getCode()); applyMapper.insert(apply); // 3. 同步修改宠物状态为申请中 Pet pet petMapper.selectById(dto.getPetId()); pet.setStatus(PetStatusEnum.APPLYING.getCode()); petMapper.updateById(pet); return true; }这段代码做了三件事。第一通过 LambdaQueryWrapper 查询当前用户对同一宠物的申请数大于零直接抛业务异常这是防止用户狂点提交按钮刷出多条申请的兜底逻辑。第二插入一条申请记录状态置为待审核PENDING。第三把宠物的状态从「可领养」改到「申请中」避免其他用户同时申请同一只宠物。注意rollbackFor Exception.class因为 Spring 默认只对运行时异常回滚而BizException这类自定义异常通常继承自 RuntimeException显式声明能让所有异常都触发回滚。实际项目里我还习惯在service层接口注释里写清楚这个方法的调用场景不然别人接手时会跟前端的「收藏」功能搞混——收藏不改变宠物状态申请才改变。3.3 权限控制与接口安全JWT 拦截器排除路径的设置逻辑毕设系统一般用 JWT 做登录态管理用户登录时后端签发一个带过期时间的 token前端每次请求携带到 Authorization 头。资源里后端会有一个JwtInterceptor或AuthInterceptor它拦截所有/api/**请求但放行登录、注册、首页宠物列表等匿名接口。配置拦截器时最常踩坑的点就是放行路径的写法用/**匹配多级路径用/*只匹配一级。下面这段是资源里典型配置的精简版我复现时调整过两处路径才让前端跑通。Configuration public class WebMvcConfig implements WebMvcConfigurer { Resource private JwtInterceptor jwtInterceptor; Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) .addPathPatterns(/api/**) .excludePathPatterns( /api/user/login, /api/user/register, /api/pet/list, /api/pet/detail/**, /error ); } }参数说明addPathPatterns(/api/**)表示拦截所有以/api/开头的接口excludePathPatterns里列的是不需要 token 就能访问的端点。这里有两处细节容易出错。第一/api/pet/detail/**的/**匹配后边的任意宠物 id如果你漏掉了这条前端浏览宠物详情页时不带 token 会直接被拦截器拒绝返回 401。第二/error也要放行否则拦截器内部抛出异常后 Spring Boot 的默认错误转发路径会被再次拦截导致前端收到的是空响应而不是 JSON 错误体。JWT 校验逻辑一般在拦截器的preHandle方法中解析 header 里的 token用密钥验签若过期或签名非法则直接response.sendError(401)只要这步过关后续 Controller 参数里用RequestAttribute(userId)就能取到当前登录用户 id。3.4 文件上传与静态资源映射宠物图片的本地存储方案宠物领养系统离不开图片展示资源里后端上传接口采用了本地磁盘存储方案——文件保存到项目某目录然后把 URL 返回给前端存入数据库。这个方案比云存储好部署也够答辩展示。上传接口接收 MultipartFile判断文件类型和后缀名是必要的体检否则一个 .jsp 文件伪装成图片传上来会有安全隐患。核心代码如下PostMapping(/upload) public ResultString upload(RequestParam(file) MultipartFile file) { if (file.isEmpty()) { return Result.error(文件不能为空); } String originalFilename file.getOriginalFilename(); String ext originalFilename.substring(originalFilename.lastIndexOf(.)); ListString allowExt Arrays.asList(.jpg, .jpeg, .png, .gif); if (!allowExt.contains(ext.toLowerCase())) { return Result.error(仅支持 jpg/png/gif 格式的图片); } String fileName UUID.randomUUID().toString() ext; String datePath LocalDate.now().format(DateTimeFormatter.ofPattern(yyyy/MM/dd)); File dir new File(uploadPath datePath); if (!dir.exists()) { dir.mkdirs(); } file.transferTo(new File(dir, fileName)); String url /upload/ datePath / fileName; return Result.success(url); }代码里的关键守则扩展名白名单校验是必须的UUID.randomUUID()生成随机文件名是为了防重名覆盖按日期分目录存放既避免单目录文件过多又方便后期排查。与此同时SpringBoot 默认不映射/upload/**到磁盘真实路径你必须在配置类里加一个WebMvcConfigurer的addResourceHandlers方法把/upload/**映射到本地磁盘目录不然前端img src/upload/xxx.jpg会一直 404。这个资源和拦截器配置写在同一个类里即可我习惯把路径写成配置文件里的变量因为 Windows 和 Linux 的路径分隔符处理方式不同硬编码会让搬运到服务器时多改好几个地方。4. 前端 Vue3 交互体系从路由守卫到领养申请全流程4.1 路由与权限动态标题、登录拦截、角色分流一体的 router 配置前端项目用的是 Vue Router 4路由表里定义了两个顶层容器/布局组件包含导航栏和底部和/admin布局组件管理员后台。前端权限控制的思路是所有需要登录的页面打上meta.requiresAuth: true路由守卫读取本地 token 判断是否放行。admin路由下嵌套的所有页面用meta.role: admin标记守卫里再校验当前用户角色。下面这段是在permission.js或router/index.js里写的核心守卫逻辑// 全局前置守卫 router.beforeEach((to, from, next) { document.title (to.meta.title ? to.meta.title - : ) 宠物领养系统 const token localStorage.getItem(token) if (to.meta.requiresAuth !token) { next({ path: /login, query: { redirect: to.fullPath } }) return } if (to.meta.role token) { const role localStorage.getItem(role) if (role ! to.meta.role) { next(/) return } } next() })这段逻辑很直白第一段在每次路由跳转时把浏览器标签页标题改成「当前页面 - 宠物领养系统」这个细节答辩演示时能加分实际使用也很顺手第二段判断目标页面是否要求登录——如果要求且本地没 token就跳去登录页并带上redirect参数登录成功后前端可以用这个参数跳回原目标页第三段是管理员后台的双重校验token 存在但角色不是 admin 则踢回首页。注意这里的角色信息是在登录接口返回值里由后端下发的前端拿到后存 localStorage。这种做法的缺陷是用户手动改 localStorage 里的 role 就能绕过前端限制但后端的 JWT 和拦截器还在真正敏感接口仍然安全毕设层面完全够用。4.2 Axios 封装token 注入、响应拦截与错误提示的代码细节资源前端的api/request.js是对 axios 实例的二次封装几乎所有页面都通过它发起 HTTP 请求。封装的核心是拦截器请求拦截器里把 localStorage 里的 token 塞进请求头响应拦截器里统一处理错误码——比如 token 过期返回 401 时清除本地登录信息并跳到登录页。封装的好处是如果后端接口返回格式统一为{ code, message, data }前端所有页面都能少写一堆错误判断。以下是这份资源里典型的封装方式import axios from axios const request axios.create({ baseURL: /api, timeout: 15000 }) // 请求拦截器附加 token request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization token } return config }) // 响应拦截器统一处理业务状态码 request.interceptors.response.use( response { const res response.data if (res.code 200) { return res.data } if (res.code 401) { localStorage.removeItem(token) localStorage.removeItem(userInfo) window.location.href /login } ElMessage.error(res.message || 请求失败) return Promise.reject(new Error(res.message)) }, error { ElMessage.error(error.message || 网络异常请检查后端服务是否启动) return Promise.reject(error) } )这里的几个参数决定前端所有接口的体验。baseURL: /api配合 vite 代理开发环境和后端发布的接口前缀保持一致timeout: 15000是给慢接口的兜底用户点击领养申请后如果后端 MyBatis 查询慢或网络卡15 秒内必须报错而不是无限等待。响应拦截器把「HTTP 状态码」和「业务状态码」分开了处理——HTTP 层 2xx 都进第一个回调业务层再细看res.code是否等于 200这样后端即使是 500 错误只要返回结构仍是{code: 500, message}前端也能拿到清晰提示而不是白屏。我个人习惯把ElMessage的提示时间设为 2 秒登录失败的「用户名或密码错误」不至于遮住表单太久。4.3 领养申请全交互链路状态联动、表单校验、二次确认前端「申请领养」是这套系统最完整的一条交互链路涉及三个文件的配合宠物详情页PetDetail.vue、领养申请表单ApplyForm.vue、个人中心申请记录页MyApply.vue。用户浏览宠物详情时后端返回的宠物状态如果是「可领养」页面上就渲染「申请领养」按钮如果这宠物已经有别人申请、状态变成「申请中」按钮就该置灰不可点。详情页拿到宠物数据后通常这么判断const canApply computed(() { return pet.value.status AVAILABLE (role.value USER || !role.value) })computed在这里做响应式计算宠物状态或角色一变按钮状态立即刷新。角色判断的目的是防止管理员在后台详情页也看到「申请领养」按钮——管理员只负责审核不应该申请。表单校验方面领养申请通常要求填自我介绍、居住情况、养宠经验这些字段validata规则里必填项和字数限制都有。用户点击提交后前端组装 payload 调applyAdopt接口成功之后要弹一个提示并跳转到个人中心的申请记录页用户在列表里能看到自己的申请是「待审核」状态。这个链路看起来简单但实际开发里翻车点往往在「提交后宠物状态立即变化」——如果接口请求成功后前端不重新拉宠物详情页面上的宠物状态还是「可领养」用户再点一次申请按钮就会拿到后端的「重复申请」报错。因此代码里这样写const handleApply async () { await formRef.value.validate() await applyApi.submit(form.value) ElMessage.success(申请提交成功请等待审核) await getPetDetail() router.push(/my/apply) }这里的关键是await getPetDetail()把宠物详情重新拉一遍让pet.status响应式更新成「申请中」这行代码决定了用户提交后按钮是否立即变灰。后续审核结果同步到个人中心是通过「我的申请」列表接口实现的列表每一项会根据后端返回的status字段渲染标签颜色和操作按钮——已拒绝的申请可以删除已同意的申请引导用户去详情页查看联系方式这样整个业务闭环就算完整了。5. 部署与联调避坑指南启动失败、数据错乱和图片 404 的完整排查5.1 后端启动即报错Failed to configure a DataSource现象在 IDEA 里直接运行PetApplication.java控制台一两秒后出现Failed to configure a DataSource: url attribute is not specified然后进程退出。原因SpringBoot3 的自动配置启动时就要连数据库而application.yml里没有正确加载数据源配置常见情况是本地没有 MySQL 服务、密码不一致、或者配置文件放错目录。解决先确认 MySQL 服务已启动Linux 用systemctl status mysqldWindows 任务管理器里看mysqld进程再确认application.yml确实在src/main/resources下且配置键名无误最后可以用下面命令快速测试数据库连通性这样拿结果说话最高效。# 用 Java 的 sql 客户端直接测试连接超出 3 秒连不上先查 MySQL 端口和防火墙 mysql -h 127.0.0.1 -P 3306 -u root -p密码 -e select 1提示如果你用的是 MySQL8且 MySQL 服务的根用户允许的认证插件是caching_sha2_passwordSpringBoot 的驱动要配useSSLfalse或allowPublicKeyRetrievaltrue否则即使密码正确也可能报认证失败。5.2 前端打开就是白屏控制台报Cannot GET /现象npm run dev跑起来后浏览器访问localhost:5173返回空白控制台提示Cannot GET /。原因路由模式用的是createWebHistoryVite 开发服务器对刷新后的深层路径如/login没有 fallback或者路由表里根路径/的重定向指向了一个不存在的组件。解决先确认router/index.js的/路由有没有redirect到/home或component: Layout指向正确路径再检查 Vite 配置里没有开historyApiFallbackVite 的 dev server 默认支持但如果你是对着旧 Vue2 webpack 配置改的容易漏掉。我实际遇到过把 Layout 组件的路径从/layout/index.vue改成/layout/Index.vue后 Linux 下大小写不匹配导致组件解析失败的这种错误看控制台会直接指向路由文件。5.3 图片上传成功但访问 404控制台显示Failed to load resource现象上传接口返回{url: /upload/2025/04/01/uuid.jpg}但浏览器打开这个地址 404。原因后端没有配置静态资源映射。SpringBoot 默认只映射classpath:/static/下的静态文件你自己定义的磁盘目录必须显式声明。解决在config包里补一个WebMvcConfigurer用registry.addResourceHandler(/upload/**).addResourceLocations(file: uploadPath)映射。同时要注意uploadPath是绝对路径还是相对路径——相对路径会让映射找不到目录。Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String path System.getProperty(user.dir) /upload/; registry.addResourceHandler(/upload/**) .addResourceLocations(file: path); }5.4 Windows 能正常跑部署到 Linux 服务器后接口通但图片不显示现象本机联调一切正常打成 jar 包放服务器上接口能查数据但所有宠物图片裂图。原因路径分隔符和当前工作目录。Windows 下File.separator是\Linux 下是/如果你在代码里把路径硬编码成了带盘符的形式到 Linux 一定爆。解决所有文件路径统一用System.getProperty(user.dir)拼接或干脆在application.yml配置一个upload.path属性启动时用Value注入。文件存储不要放在 jar 包同级目录之外的随机路径最好统一放在 jar 包目录的upload文件夹方便备份和迁移。5.5 领养审核通过后管理端用户列表和宠物列表状态不同步现象管理员在后台把申请状态改为「已同意」后去宠物列表页面刷新宠物状态还是「申请中」。原因审核接口在AdoptApplyServiceImpl里只更新了申请表的status字段没有同步更新pet表的status。解决在审核方法里加一段宠物状态联动更新——同意时将宠物状态置为「已领养」拒绝时把宠物状态从「申请中」改回「可领养」。这个问题的关键不在代码有多难而在于拆代码时很容易漏看状态机设计文档。建议把状态流转写清晰AVAILABLE(可领养) → APPLYING(申请中) → ADOPTED(已领养) APPLYING → REJECTED(申请拒绝) → AVAILABLE(可领养)补上这段业务后建议写一个简单的单元测试或直接用 Postman 走一遍申请→拒绝→再申请→同意四个状态节点全部核对一遍再继续往下开发能帮你省下答辩前夜改状态分支的时间。6. 生产环境切换技巧用 Spring Profiles 把开发环境与服务器配置分离这份资源默认的开发配置直连本地 MySQL、文件存本地、接口直接暴露适合课程设计演示。但如果你想把它放到真实服务器上跑几天给朋友体验或者答辩老师现场要求「在服务器上演示」这套默认配置就不太够用了——本地改配置、重新打包、再上传指纹文件的做法不仅繁琐还容易把调试代码带到生产。我一般会这么做引入application-dev.yml和application-prod.yml两套文件把差异化配置抽出来再用spring.profiles.active切换。# application.yml 主配置里只放公共配置 spring: profiles: active: dev# application-prod.yml 生产配置 server: port: 8080 spring: datasource: url: jdbc:mysql://你的服务器IP:3306/pet_adoption?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: pet_admin password: 强密码 servlet: multipart: max-file-size: 10MB mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# application-prod.yml 生产环境可以关闭 SQL 日志 spring: datasource: url: jdbc:mysql://服务器IP:3306/pet_adoption?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl打包后启动命令变成一句java -jar pet-backend-0.0.1-SNAPSHOT.jar --spring.profiles.activeprod个人习惯两个配置文件的公共部分尽量收敛到主文件里差异只用密码、地址、日志开关这种真正需要切换的项。这样在 IDEA 里开发用默认dev配置上线时加一个参数切到prod不需要动任何源码。验证配置是否生效很简单——看启动日志里The following 1 profile is active: prod这行输出确认无误再开始下一步。从那以后我每次上服务器都会强制走一遍这条流程本地跑通、切 prod 配置、打包、服务器启动、看日志确认 profile 生效、用浏览器走一遍核心链路五步缺一不可。这也是拆这套宠物领养系统源码时最值得记住的一条习惯希望帮到你。本文还有配套的精品资源点击获取