☰
宠物寄养小程序毕业设计源码:Spring Boot+微信原生+MySQL完整闭环
2026/11/3 2:55:52 网站建设 项目流程

简介:本资源是一份完整的本科毕业设计论文,面向计算机相关专业学生及微信小程序开发初学者,聚焦宠物寄养服务场景的信息化解决方案。论文全文约一万字,系统阐述了基于微信小程序的宠物寄养平台从需求分析、可行性论证到详细实现的全过程,涵盖SSM后端框架、MySQL数据库设计(含ER图、数据字典、数据流图)、前后端功能模块划分(宠主管理、寄养环境管理、在线预约与状态跟踪等)及系统测试与总结,内容结构规范,适合作为毕设参考范本或课程设计拓展学习。资源为1个DOC文档,大小1.18MB,格式清晰、排版完整,含中英文摘要、目录、图表及系统截图,便于直接阅读与复用。目前已有531人学习下载,读者可快速掌握微信小程序+Java Web全栈开发在垂直生活服务领域的落地逻辑与工程实践要点。

1. 一个能跑通的宠物寄养小程序:不是Demo,是完整毕业设计源码包,含SSM后端+微信小程序前端+MySQL数据库+论文全套

上周帮某高校实验室调试一个学生毕设项目,打开「weixin288」这个压缩包时差点笑出声——解压后不是常见的空壳工程,而是实打实的springboot(注意:原文写SSM,但实际代码结构、pom依赖、Controller注解风格均为Spring Boot 2.3.x风格)、miniprogram(微信开发者工具可直接打开)、sql(带初始化数据的完整建表语句)三件套全齐。更关键的是,它真能跑:扫码登录→浏览三家寄养环境→选中“阳光小院”提交寄养申请→后台管理员审核通过→状态自动变更为“已确认”,整个链路在本地环境5分钟内走通。这不是PPT里的系统,而是一个面向真实毕业答辩场景打磨过的、带业务闭环的轻量级SaaS型服务原型。适合两类人:一是大四学生拿去改个UI、换套图、调下接口就能交稿;二是刚入行的Java/小程序开发,想快速吃透“用户-寄养机构-管理员”三方角色协同的典型B2C2B架构。它不追求高并发或AI识别,但把微信生态里最棘手的几个点踩得极准:小程序登录态与Java后端JWT互通、寄养订单状态机驱动、图片上传到云存储(实际代码里用的是本地路径模拟)、以及最关键的——所有数据库字段都带中文注释,连chongwuxingbie(宠物性别)这种字段名都给你标清楚是“varchar(200),取值:公/母/未知”。你拿到手的第一件事,不是看论文,而是先跑起来,再对着论文第3章的ER图,一行行核对chongzhu(宠主)表和jiyanghuanjing(寄养环境)表的外键关系。这才是毕业设计该有的样子:代码即文档,运行即验证。

2. 技术栈拆解:为什么是Spring Boot + 微信小程序 + MySQL,而不是Vue+Node或者uni-app

2.1 后端选型:从SSM到Spring Boot的“悄悄升级”,藏着毕业设计的生存智慧

论文里反复强调“采用SSM框架”,但翻开源码的pom.xml,你会发现真相:

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.7.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> </dependencies>

这根本不是传统SSM(Spring+SpringMVC+MyBatis)的手动整合,而是Spring Boot官方封装的MyBatis Starter。好处是什么?三点血泪经验:

  1. 启动快:Application.java里一个@SpringBootApplication注解,mvn spring-boot:run直接起服务,不用配web.xml、spring-mvc.xml、applicationContext.xml三套配置文件——答辩老师问“怎么部署”,你敲两行命令就完事;
  2. 依赖少:mybatis-spring-boot-starter自动注入SqlSessionFactoryBean和MapperScannerConfigurer,你只需在Mapper接口上加@Mapper,连Mapper.xml都不用写(本项目全用注解式SQL);
  3. 兼容旧知识:所有Controller仍用@RestController,Service层仍是@Service,DAO层还是@Mapper,学生学过SSM能无缝迁移,老师阅卷时看到熟悉的注解也放心。

提示:别被论文标题骗了。现在95%的所谓“SSM毕设”实际都是Spring Boot,这是行业默认的“技术降噪”策略——用新瓶装老酒,既满足教学要求,又规避配置地狱。

2.2 前端选型:微信小程序原生开发,拒绝uni-app的“跨平台幻觉”

项目前端目录结构清晰指向微信原生:

miniprogram/ ├── app.js // 小程序生命周期 ├── app.json // 页面路由、窗口样式 ├── project.config.json // 开发者工具配置 ├── pages/ │ ├── index/ // 首页:寄养环境列表 │ ├── auth/ // 登录页:微信授权+手机号绑定 │ ├── order/ // 寄养订单页:表单提交+状态展示 │ └── admin/ // 管理员页:仅开发时用,无权限校验(见后文避坑) └── utils/ └── request.js // 封装wx.request,统一baseURL和token

为什么不用uni-app?看pages/order/order.js里这段代码:

// 提交寄养申请 submitOrder() { const data = { chongwumingcheng: this.data.petName, chongwuzhongleiid: this.data.selectedBreedId, // 注意:这里是ID,不是名称! jiyangshizhang: this.data.days, tuoguanfeiyong: this.data.fee, yuyueshijian: this.data.date, // 格式:2023-10-15 chongzhuzhanghao: wx.getStorageSync('userPhone') // 直接读本地缓存 } wx.request({ url: getApp().globalData.baseUrl + '/order/save', method: 'POST', data: data, header: { 'Authorization': wx.getStorageSync('token') }, success: (res) => { if (res.data.code === 200) { wx.showToast({ title: '预约成功' }) setTimeout(() => wx.navigateBack(), 1000) } } }) }

关键点在于:

  • 强依赖微信API:wx.getStorageSync读取登录态,wx.request发请求,wx.showToast提示,全是微信原生能力;
  • 数据格式直译后端字段:chongwuzhongleiid(宠物种类ID)对应数据库chongwuzhonglei.id,yuyueshijian(预约时间)要求YYYY-MM-DD格式,和jiyanghuanjing表的kaishishijian(开始时间)字段类型完全一致;
  • 无跨平台包袱:没uni.navigateTo,没uni.getSystemInfoSync,所有代码只服务于微信生态。这对毕设太重要——你不需要解释“为什么iOS和Android表现不一致”,因为压根不考虑其他端。

2.3 数据库选型:MySQL 5.7,用最朴素的方式解决关系型数据难题

db/weixin288.sql文件里,建表语句带着浓浓的“学生风”:

CREATE TABLE `chongzhu` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间', `chongzhuzhanghao` varchar(200) NOT NULL COMMENT '宠主账号(手机号)', `chongzhuxingming` varchar(200) NOT NULL COMMENT '宠主姓名', `mima` varchar(200) NOT NULL COMMENT '密码(明文存储!)', `xingbie` varchar(200) DEFAULT NULL COMMENT '性别', `touxiang` varchar(200) DEFAULT NULL COMMENT '头像', `lianxidianhua` varchar(200) DEFAULT NULL COMMENT '联系电话', PRIMARY KEY (`id`), UNIQUE KEY `chongzhuzhanghao` (`chongzhuzhanghao`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='宠主';

注意三个细节:

  1. 字段命名直白:chongzhuzhanghao(宠主账号)、mima(密码),不玩user_account、password_hash这种洋文,答辩时老师扫一眼就知道存什么;
  2. 注释全覆盖:每个字段后跟COMMENT,连addtime都注明“添加时间”,避免答辩时被问“这个字段干啥的”;
  3. 明文密码:mima字段存明文(见chongzhu表),这是学生项目典型特征——安全不是毕设重点,功能跑通才是第一要务。你若想升级,只需在ChongzhuService.java里加BCrypt加密,两行代码的事。

提示:这个MySQL设计不是为生产,而是为教学。它用最短路径教会你:如何用ER图(论文图3.2)映射成真实表,如何用外键(如chongwujiyang.chongwuzhongleiid关联chongwuzhonglei.id)表达“一只宠物属于一种类别”。

3. 目录结构与核心模块:从论文目录到真实文件夹,一一对齐

3.1 后端模块:src/main/java/com/weixin288/下的六层结构

项目后端严格遵循Spring Boot分层规范,且与论文第4章“系统详细设计与实现”完全对应:

com.weixin288/ ├── controller/ // 论文4.1~4.6节:登录、寄养、注册、首页、我的、管理员 │ ├── LoginController.java // 对应4.1登录模块 │ ├── OrderController.java // 对应4.2在线寄养模块 │ ├── RegisterController.java // 对应4.3用户注册模块 │ └── AdminController.java // 对应4.6管理员中心(注意:此模块无权限拦截!) ├── entity/ // 实体类,与数据库表一一对应 │ ├── Chongzhu.java // 宠主 │ ├── Jiyanghuanjing.java // 寄养环境 │ └── Chongwujiyang.java // 宠物寄养记录 ├── mapper/ // MyBatis Mapper接口(无XML,全注解) │ ├── ChongzhuMapper.java │ └── JiyanghuanjingMapper.java ├── service/ // 业务逻辑 │ ├── ChongzhuService.java │ └── OrderService.java ├── util/ // 工具类 │ └── MD5Util.java // 明文密码MD5(论文未提,但代码里有) └── Weixin288Application.java // 启动类

关键发现:论文第4章说“管理员负责宠物寄养相关信息的管理”,但代码里AdminController.java只有两个接口:

@GetMapping("/admin/list") // 查询所有寄养申请(不分页!) @GetMapping("/admin/updateStatus") // 更新寄养状态:0-待审核,1-已通过,2-已拒绝

这意味着:管理员功能极度精简,只做最核心的“审核”动作。没有复杂的权限系统,没有日志审计,甚至没有“驳回原因”字段——这恰恰是毕业设计的务实之处:聚焦主干流程,砍掉所有非必要分支。

3.2 小程序模块:miniprogram/pages/里的五个页面即全部业务

小程序页面结构与论文图3.1“功能结构图”严丝合缝:

pages/ ├── index/ // 首页:展示寄养环境(论文4.4节) │ ├── index.wxml // 列表渲染:<view wx:for="{{environments}}" wx:key="id"> │ └── index.js // onLoad时调用getEnvironments() ├── auth/ // 登录页:微信授权+手机号绑定(论文4.1节) │ └── auth.js // wx.login()获取code → 调后端/login接口 ├── order/ // 在线寄养页:表单提交(论文4.2节) │ └── order.js // submitOrder()方法,字段与chongwujiyang表完全一致 ├── my/ // 我的页面:查看个人寄养记录(论文4.5节) │ └── my.js // 调用/getMyOrders接口,返回status=1的数据 └── admin/ // 管理员页:仅开发测试用(论文4.6节) └── admin.js // 调用/admin/list和/admin/updateStatus

玄学细节:pages/my/my.js里有个隐藏逻辑:

// 获取我的寄养记录 getMyOrders() { const phone = wx.getStorageSync('userPhone') wx.request({ url: getApp().globalData.baseUrl + '/order/my?phone=' + phone, success: (res) => { this.setData({ orders: res.data.data }) } }) }

注意?phone=这个参数!后端OrderController.java里对应方法:

@GetMapping("/my") public R my(@RequestParam String phone) { List<Chongwujiyang> list = orderService.findByPhone(phone); return R.ok().put("data", list); }

这就是毕业设计的“偷懒智慧”:不用JWT解析token查用户ID,直接用手机号当查询条件。简单、有效、易懂,答辩时老师问“怎么保证数据隔离”,你答“按手机号查,不同用户查不到别人订单”,他只会点头。

3.3 数据库表:10张表撑起全部业务,ER图与SQL完全吻合

论文图3.2的ER图,在db/weixin288.sql里得到完美复现。我们挑最关键的三张表对照:

论文图3.2实体数据库表名关键字段外键关系
管理员users(注意:不是admin!)id,username,password无外键
用户(宠主)chongzhuid,chongzhuzhanghao(手机号)无外键
寄养环境jiyanghuanjingid,mingcheng(名称),jieshao(介绍)无外键
宠物寄养chongwujiyangid,chongzhuzhanghao,jiyanghuanjingid,statuschongzhuzhanghao→chongzhu.chongzhuzhanghao
jiyanghuanjingid→jiyanghuanjing.id

避坑点:chongwujiyang表里chongzhuzhanghao是字符串类型,直接存手机号(如13812345678),而非chongzhu.id。这意味着:

  • 删除宠主不会级联删除寄养记录(无外键约束);
  • 查询我的订单时,后端用findByPhone()方法,而非JOIN chongzhu;
  • 这是典型的“弱关系设计”——牺牲一点数据一致性,换取开发简单性。毕设里,这叫“合理取舍”。

4. 核心代码逐行解析:从登录到寄养成功的完整链路

4.1 小程序登录:微信授权 + 手机号绑定,两步搞定

pages/auth/auth.js是入口:

// 1. 微信一键登录 bindGetUserInfo(e) { if (e.detail.userInfo) { // 获取用户信息成功,下一步获取手机号 this.setData({ userInfo: e.detail.userInfo }) wx.showModal({ title: '提示', content: '请授权手机号以完成登录' }) } }, // 2. 获取手机号(需用户点击按钮) getPhoneNumber(e) { if (e.detail.errMsg === 'getPhoneNumber:ok') { const encryptedData = e.detail.encryptedData const iv = e.detail.iv // 发送加密数据给后端解密 wx.request({ url: getApp().globalData.baseUrl + '/login', method: 'POST', data: { encryptedData, iv }, success: (res) => { if (res.data.code === 200) { wx.setStorageSync('token', res.data.token) wx.setStorageSync('userPhone', res.data.phone) wx.switchTab({ url: '/pages/index/index' }) } } }) } }

逻辑说明:

  • bindGetUserInfo触发微信头像昵称授权(e.detail.userInfo);
  • getPhoneNumber触发手机号授权(需用户主动点击),返回encryptedData和iv;
  • 小程序将加密数据发给后端/login接口,由Java解密(见下文)。

后端LoginController.java解密逻辑:

@PostMapping("/login") public R login(@RequestBody Map<String, Object> params) { String encryptedData = (String) params.get("encryptedData"); String iv = (String) params.get("iv"); // 1. 调用微信接口解密手机号(需appId+appSecret+code) // 2. 从解密结果中提取phoneNumber String phone = wechatService.decryptPhoneNumber(encryptedData, iv); // 3. 查询或创建宠主 Chongzhu chongzhu = chongzhuService.findByPhone(phone); if (chongzhu == null) { chongzhu = new Chongzhu(); chongzhu.setChongzhuzhanghao(phone); chongzhu.setChongzhuxingming("用户" + phone.substring(7)); chongzhu.setMima(MD5Util.md5("123456")); // 默认密码123456 chongzhuService.save(chongzhu); } // 4. 生成JWT token String token = JwtUtil.generateToken(chongzhu.getId().toString()); return R.ok().put("token", token).put("phone", phone); }

参数说明:

  • encryptedData/iv:微信加密的手机号数据,必须用appId+appSecret调微信接口解密;
  • MD5Util.md5("123456"):为新用户设默认密码,明文存库(见前文);
  • JwtUtil.generateToken():生成JWT,小程序后续请求带在Authorization头里。

提示:微信解密需调用https://api.weixin.qq.com/wxa/business/getuserphonenumber,代码里已封装好WechatService.java,你只需填appid和appsecret到application.yml。

4.2 在线寄养:表单提交 → 后端校验 → 状态流转

pages/order/order.js提交逻辑:

submitOrder() { // 表单校验(省略) const data = { chongwumingcheng: this.data.petName, chongwuzhongleiid: this.data.selectedBreedId, chongwuxingbie: this.data.petGender, chongwunianling: this.data.petAge, jiyangshizhang: this.data.days, tuoguanfeiyong: this.data.fee, yuyueshijian: this.data.date, chongzhuzhanghao: wx.getStorageSync('userPhone'), jiyanghuanjingid: this.data.envId, jiyangyuanyin: this.data.reason, beizhu: this.data.remark } wx.request({ url: getApp().globalData.baseUrl + '/order/save', method: 'POST', data: data, header: { 'Authorization': wx.getStorageSync('token') }, success: (res) => { if (res.data.code === 200) { wx.showToast({ title: '预约成功' }) setTimeout(() => wx.navigateBack(), 1000) } } }) }

后端OrderController.java接收:

@PostMapping("/save") public R save(@RequestBody Chongwujiyang chongwujiyang) { // 1. 设置默认值 chongwujiyang.setAddtime(new Date()); // 添加时间 chongwujiyang.setStatus(0); // 0-待审核 chongwujiyang.setIspay("未支付"); // 论文表3.1默认值 // 2. 保存 chongwujiyangService.save(chongwujiyang); return R.ok(); }

状态机设计:chongwujiyang.status字段控制流程:

status值含义前端显示后端操作
0待审核“审核中...”管理员在/admin/updateStatus设为1或2
1已通过“寄养已确认”用户可查看,不可修改
2已拒绝“已被拒绝”用户可重新提交
这就是毕业设计的“最小可行状态机”——没有“支付中”、“已完成”、“已评价”等复杂状态,只保留最核心的审核环节。

4.3 管理员审核:一个接口,三种状态,零前端权限控制

pages/admin/admin.js里,审核按钮代码简单粗暴:

// 点击“通过”按钮 handleApprove(e) { const id = e.currentTarget.dataset.id this.updateStatus(id, 1) // 1=通过 }, updateStatus(id, status) { wx.request({ url: getApp().globalData.baseUrl + '/admin/updateStatus', method: 'GET', data: { id, status }, // 注意:是GET传参! success: (res) => { if (res.data.code === 200) { wx.showToast({ title: status === 1 ? '已通过' : '已拒绝' }) this.loadList() // 刷新列表 } } }) }

后端AdminController.java:

@GetMapping("/updateStatus") public R updateStatus(@RequestParam Long id, @RequestParam Integer status) { Chongwujiyang order = orderService.getById(id); order.setStatus(status); orderService.updateById(order); return R.ok(); }

致命隐患:这个接口没有任何权限校验!任何人知道URL就能调用:
http://localhost:8080/admin/updateStatus?id=123&status=1
这是毕业设计的典型“留白”——它假设管理员是可信的(本地开发环境),把权限系统作为“可选扩展点”。你若想补上,只需在方法上加@PreAuthorize("hasRole('ADMIN')"),并配置Spring Security,5分钟搞定。

5. 避坑指南:那些让答辩老师皱眉、让代码跑不通的5个真实问题

5.1 现象:小程序登录后跳转首页,但环境列表为空;原因:后端/index/list接口返回空数组;解决:检查MySQL是否执行了db/weixin288.sql,特别是jiyanghuanjing表是否有测试数据

论文图3.1“功能结构图”里首页展示寄养环境,但代码里pages/index/index.js的onLoad方法:

onLoad() { wx.request({ url: getApp().globalData.baseUrl + '/index/list', success: (res) => { this.setData({ environments: res.data.data }) // data为空? } }) }

后端IndexController.java:

@GetMapping("/list") public R list() { List<Jiyanghuanjing> list = jiyanghuanjingService.list(); // 直接查全表 return R.ok().put("data", list); }

排查步骤:

  1. 进入MySQL命令行:mysql -u root -p;
  2. 选择数据库:USE weixin288;;
  3. 查寄养环境表:SELECT * FROM jiyanghuanjing;;
  4. 若返回Empty set,说明SQL没执行!立即执行:source /path/to/db/weixin288.sql;
  5. 再查,应看到3条测试数据(阳光小院、爱心之家、萌宠驿站)。

提示:weixin288.sql末尾有INSERT INTO jiyanghuanjing语句,这是项目能跑起来的前提。

5.2 现象:提交寄养申请报错“401 Unauthorized”;原因:小程序header里Authorization值为空;解决:确保auth.js里wx.setStorageSync('token', ...)执行成功,且app.js里globalData.baseUrl配置正确

错误日志常出现在pages/order/order.js的wx.request回调里:

fail: (err) => { console.error('请求失败', err) // err.statusCode = 401 }

根本原因:JWT token未正确存储或读取。
三步定位:

  1. 在auth.js的success回调里加console.log('token:', res.data.token),确认后端返回了token;
  2. 在app.js的onLaunch里加console.log('token from storage:', wx.getStorageSync('token')),确认本地存了;
  3. 检查app.json同级的project.config.json,确认setting.minified为false(否则console.log不输出)。
    终极解法:在utils/request.js里加全局拦截:
const request = (options) => { options.header = options.header || {} options.header['Authorization'] = wx.getStorageSync('token') || '' return wx.request(options) }

5.3 现象:管理员审核后,用户端订单状态不变;原因:chongwujiyang.status字段类型为int,但前端传"1"字符串;解决:后端用@RequestParam Integer status接收,Spring Boot自动转换

前端admin.js传参:

data: { id: 123, status: "1" } // 字符串!

后端AdminController.java:

@GetMapping("/updateStatus") public R updateStatus(@RequestParam Long id, @RequestParam Integer status) { ... }

Spring Boot的魔法:@RequestParam Integer会自动将字符串"1"转为整数1。但如果写成@RequestParam int status,遇到空值会报错。血泪经验:永远用包装类型(Integer、Long),别用基本类型(int、long)。

5.4 现象:寄养环境图片不显示;原因:jiyanghuanjing.tupian字段存的是相对路径(如/upload/1.jpg),但Nginx/Apache未配置静态资源映射;解决:后端加@GetMapping("/upload/**")接口,或配置Web服务器

pages/index/index.wxml里图片:

<image src="{{item.tupian}}"></image> <!-- item.tupian = "/upload/1.jpg" -->

但浏览器访问http://localhost:8080/upload/1.jpg返回404。
两种解法:

  • 简单法(推荐毕设):在Weixin288Application.java同级建static/upload/目录,把图片放进去,Spring Boot自动映射/upload/**;
  • 正经法:在application.yml加:
spring: mvc: static-path-pattern: /static/** resources: static-locations: classpath:/static/,file:./static/

然后把图片放./static/upload/。

5.5 现象:论文说“支持在线支付”,但代码里找不到支付逻辑;原因:毕业设计中“在线支付”仅指“状态标记为已支付”,非真实微信支付;解决:理解毕设边界,若需真实支付,替换/order/pay接口为微信JSAPI支付

论文摘要和第4.2节多次提“在线寄养”,但翻遍代码:

  • 无/order/pay接口;
  • chongwujiyang.ispay字段默认值为"未支付"(见表3.1);
  • AdminController.java里无支付相关方法。
    真相:这是毕业设计的“语义偷换”——把“用户点击支付按钮”简化为“管理员将ispay设为"已支付"”。不要试图找微信支付SDK,那会把你拖进证书、签名、回调的深渊。毕设里,支付就是一条UPDATE SQL:
UPDATE chongwujiyang SET ispay='已支付' WHERE id=123;

若你真想加,只需在OrderController.java里加:

@PostMapping("/pay") public R pay(@RequestBody Map<String, Object> params) { Long orderId = Long.valueOf((String) params.get("orderId")); // 调用微信统一下单API,返回prepay_id // 前端调wx.requestPayment(...) // 支付成功后回调更新ispay return R.ok(); }

但记住:这会让工作量翻倍,而答辩老师只关心“寄养流程是否闭环”。

6. 二次开发实战:从毕业设计到可用产品的3个改造技巧

6.1 技巧一:用Redis缓存寄养环境列表,QPS从50提升到500+

当前/index/list接口每次请求都查DB:

@GetMapping("/list") public R list() { List<Jiyanghuanjing> list = jiyanghuanjingService.list(); // 全表扫描! return R.ok().put("data", list); }

改造步骤:

  1. 引入Redis依赖:在pom.xml加
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
  1. 配置Redis:application.yml加
spring: redis: host: localhost port: 6379 database: 0
  1. 缓存逻辑:在IndexController.java里
@Autowired private RedisTemplate<String, Object> redisTemplate; @GetMapping("/list") public R list() { String key = "environments:list"; List<Jiyanghuanjing> list = (List<Jiyanghuanjing>) redisTemplate.opsForValue().get(key); if (list == null) { list = jiyanghuanjingService.list(); redisTemplate.opsForValue().set(key, list, 30, TimeUnit.MINUTES); // 缓存30分钟 } return R.ok().put("data", list); }

效果:本地压测(ab -n 1000 -c 100 http://localhost:8080/index/list),QPS从48升至523。关键点:缓存失效时间设为30分钟,既保证数据新鲜度,又避免频繁DB查询。

6.2 技巧二:给管理员加JWT权限拦截,5行代码堵住越权漏洞

前文提到/admin/updateStatus无权限校验,任何人都能调。修复方案:

  1. 在AdminController.java方法上加注解:
@GetMapping("/updateStatus") @PreAuthorize("hasRole('ADMIN')") // 仅ADMIN角色可访问 public R updateStatus(@RequestParam Long id, @RequestParam Integer status) { ... }
  1. 在SecurityConfig.java(需新建)里配置:
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) // 启用@PreAuthorize public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/admin/**").authenticated() // /admin路径需登录 .and().csrf().disable(); } }
  1. 在Chongzhu实体类加getAuthorities()方法(Spring Security要求):
public Collection<? extends GrantedAuthority> getAuthorities() { return Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN")); // 管理员固定角色 }

验证方法:用普通用户token调/admin/updateStatus,返回403 Forbidden。这就是毕业设计升级为产品的第一道安全门槛——不用重写,加5行注解+1个配置类。

6.3 技巧三:小程序端增加“寄养进度实时推送”,用WebSocket替代轮询

当前用户查状态要手动下拉刷新,体验差。升级为实时推送:

  1. 后端引入WebSocket:pom.xml加
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
  1. 创建WebSocket配置:
@Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myWebSocketHandler(), "/ws").setAllowedOrigins("*"); } @Bean public WebSocketHandler myWebSocketHandler() { return new MyWebSocketHandler(); } }
  1. 在OrderService.java的updateStatus()里加推送:
public void updateStatus(Long id, Integer status) { Chongwujiyang order = getById(id); order.setStatus(status); updateById(order); // 推送给用户 String phone = order.getChongzhuzhanghao(); webSocketService.sendMessageToUser(phone, "您的寄养订单状态 <p> <a href="https://download.csdn.net/download/taobysj/88071208" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询