☰
家庭大厨微信小程序全套Java毕设源码:从架构到部署完整解析
2026/10/3 18:00:35 网站建设 项目流程

简介:面向毕业设计场景的微信小程序开发完整资料包,以家庭大厨点餐/菜品管理为业务主线,适合Java方向学生或初级开发者参考学习。项目采用SSM框架+MySQL数据库+微信开发者工具实现,覆盖小程序端与后台管理端,管理员可维护用户、店铺、菜品信息、菜品分类、购买菜品及订单行等模块,店铺和用户登录后可管理菜品与订单,系统具备较强的实用性与完整性。包体共1251个文件,压缩后17.31MB,核心类型包括Java源码、Vue前端页面、JS逻辑、JSON配置、WXML/WXSS小程序页面等,同时包含png/svg/jpg图片素材、SQL数据库脚本、开题报告、论文、PPT及使用说明文档,目录结构清晰便于按模块查阅。目前已有98人学习下载,尤其适合需要完整毕业设计案例、快速搭建运行环境并理解SSM+微信小程序前后端交互流程的读者。

1. 家庭大厨微信小程序,为什么是一套完整的 Java 毕设而不是一个 Demo

家庭大厨微信小程序这个题目,在毕业设计里属于典型的“业务闭环不大、数据表七八张、前端页面十来页”的项目。它不像商城那样要处理复杂的订单流转,也不像博客那样只有增删改查,菜谱展示、分类筛选、收藏、评论、用户登录,刚好把小程序端、Java 后端、MySQL 数据库串成一条能讲清楚的数据链路。标题里标注的是全套 Java 开源毕业设计源码,附带数据库、开题报告、论文、PPT 和使用说明,这套资料的核心价值不在于下载完能跑,而在于代码跟文档能对上。真正到了答辩现场,老师不会照着 PPT 问,只会顺着你演示的功能往下追。所以这篇文章按“小程序端怎么写、Java 后端怎么接、数据库怎么建、部署演示怎么收尾”的顺序,把这个题目背后的一整套方案拆开讲清楚。

2. 微信小程序 + Java 后端的架构:先把数据链路定下来

拿到这套家庭大厨源码,第一件事不是打开微信开发者工具,而是先确认三个端的分工:小程序只负责渲染页面和收集用户操作,Java 后端负责接口和业务逻辑,MySQL 负责落库。这个分工决定了后面所有代码的组织方式,也决定了答辩时你能把项目讲到什么深度。

2.1 为什么选微信小程序而不是 uniapp

选技术栈时,原生微信小程序是这套毕业设计最稳的选择。uniapp 的微信小程序语法上接近 Vue,上手快,但调试时它要经过编译、打包、预览一层转换,报错栈会先落在 uni 的封装层,对不熟悉编译链的同学来说,很难在答辩时把“这一行报错为什么指向这里”讲清楚。原生微信小程序由 WXML、WXSS、JS 三件套组成,页面结构就是 app.json 注册的那几个路由,哪里报错直接指向具体页面文件,演示现场出了状况也容易救回来。

另一个必须留意的点是微信小程序顶部导航栏高度。默认导航栏由微信客户端自己渲染,不同机型高度不一样。如果项目里某个页面用了自定义导航栏,布局就会因为状态栏高度不同而整体错位。常见做法是先执行wx.getMenuButtonBoundingClientRect()拿到胶囊按钮的位置,再动态计算导航栏高度。这是小程序开发里的一个经典坑,也是答辩时容易被追问的细节。

2.2 Spring Boot 是 Java 后端源码的稳妥骨架

后端框架不需要花哨,Spring Boot 是目前 Java 毕业设计里的主流选择。它内嵌 Tomcat,不用打 war 包丢进外部容器,mvn spring-boot:run一条命令就能起服务,演示前省去大量环境配置时间。ORM 层用 MyBatis-Plus,分页、逻辑删除、条件构造器都是现成的,比手写 JDBC 代码量小,也比 Hibernate 更容易向答辩老师解释“SQL 是怎么来的”。

家庭大厨源码里如果给的是 Spring Boot 工程,通常会带一个application.yml,核心配置如下:

server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/family_chef?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0

server.port是后端服务端口,小程序端 request 的 URL 必须和它对上。数据库 URL 里用了utf8mb4字符集和Asia/Shanghai时区,前者是为了能存 emoji 和生僻字,后者避免日期时间字段在 JDBC 层出现 8 小时偏移。逻辑删除这一段是 MyBatis-Plus 的特性:deleted字段默认 0 正常、1 删除,菜谱被删除之后数据还在表里,查询时框架自动带上deleted = 0条件,不用每个 SQL 都手工拼接。这套毕设里所有表都应该预留这个字段,答辩时老师问“删除怎么做”可以直接拿它回答。

2.3 数据链路:一次点击怎么变成一条 SQL

整个家庭大厨小程序的请求路径可以归纳成一句话:小程序wx.request发请求,Nginx 转发,Spring Boot 的 Controller 接住,Service 处理业务,Mapper 操作 MySQL,数据再按原路返回。不用流程图也能讲清楚:微信开发者工具里的 Network 面板看到的是小程序到后端的 HTTP 请求,后端日志里看到的是一条条 MyBatis 打印的 SQL,把这两头对上了,整个链路的调试就完成了一半。

按业务模块划分,这套项目的接口和数据表大概是下面这个对应关系:

业务模块数据表核心接口对应小程序页面
用户登录userPOST /api/user/login登录页
菜谱分类categoryGET /api/category/list首页分类入口
菜谱列表recipeGET /api/recipe/list菜谱列表页
菜谱详情recipeGET /api/recipe/detail详情页
收藏favoritePOST /api/favorite/do详情页操作
评论commentGET/POST /api/comment详情页评论区

这个表格就是整个开源源码的骨架。做毕设的时候不要拿着一页页代码去背,先记住这张表:每张数据表对应一个 Java 实体类,每个接口对应一个 Controller 方法,每个页面绑定一组请求。后面看源码、改代码、写论文,都是围绕这张表展开。

3. 小程序端从 app.json 到菜谱页面的落地

搭建微信小程序的流程,入门第一步永远是app.json。它是全局配置文件,决定小程序启动后先打开哪个页面、底部有哪些 tab、窗口呈现什么样式。家庭大厨的页面骨架并不复杂,典型的首页、菜谱列表、菜谱详情、个人中心四块。

3.1 app.json 配置页面路由与 tabBar

一个最小可运行的app.json长这样:

{ "pages": [ "pages/index/index", "pages/recipe/list", "pages/recipe/detail", "pages/user/profile", "pages/user/login" ], "window": { "navigationBarTitleText": "家庭大厨", "navigationBarBackgroundColor": "#f6f6f6", "navigationBarTextStyle": "black", "backgroundColor": "#f6f6f6" }, "tabBar": { "color": "#999999", "selectedColor": "#ff6b35", "list": [ { "pagePath": "pages/index/index", "text": "首页" }, { "pagePath": "pages/recipe/list", "text": "菜谱" }, { "pagePath": "pages/user/profile", "text": "我的" } ] }, "style": "v2", "sitemapLocation": "sitemap.json" }

pages数组的第一个元素是启动页,这套项目里就是首页。tabBar里配置的页面必须已经存在pages中,否则编译直接报错。selectedColor是 tab 选中态的颜色,家庭大厨这类美食主题的项目,一般用暖橙色或者食欲色,避免用纯黑配红这种冲突感很强的组合。如果不想设计 tab 图标,直接纯文字 tab 也是允许的,少一套图标资源,界面依然干净。

3.2 封装 request 工具:把 wx.request 变成 Promise

原生wx.request是回调写法,每个页面都写 success/fail 会非常啰嗦。我一般会在utils/request.js里把它包成 Promise,顺带统一处理 token 和错误提示:

const BASE_URL = 'http://localhost:8080'; function request({ url, method = 'GET', data = {} }) { return new Promise((resolve, reject) => { const token = wx.getStorageSync('token'); wx.request({ url: BASE_URL + url, method, data, header: { 'Content-Type': 'application/json', 'Authorization': token ? `Bearer ${token}` : '' }, success(res) { if (res.statusCode === 200 && res.data.code === 200) { resolve(res.data.data); } else if (res.statusCode === 401) { wx.removeStorageSync('token'); wx.navigateTo({ url: '/pages/user/login' }); reject(new Error('登录过期')); } else { wx.showToast({ title: res.data.msg || '请求失败', icon: 'none' }); reject(new Error(res.data.msg)); } }, fail(err) { wx.showToast({ title: '网络异常', icon: 'none' }); reject(err); } }); }); } module.exports = request;

BASE_URL是后端服务地址,本地开发用localhost:8080,真机调试时改成电脑的局域网 IP,不然手机访问不到。Authorization字段是后端识别用户身份的凭证,token 在登录成功后写入本地缓存。401 表示登录态失效,直接清掉本地 token 跳登录页,这是小程序里最常见的会话处理方式。后端返回的数据结构约定为{ code, msg, data },code === 200才走到成功分支,这样业务错误和网络错误可以分开处理。

3.3 菜谱列表页:下拉刷新、上拉加载、搜索一起做

菜谱列表页是本套源码里最值得复用的页面,它同时涉及分页、搜索、刷新三个高频操作。核心逻辑放在fetchList方法里:

const request = require('../../utils/request'); Page({ data: { list: [], page: 1, size: 10, hasMore: true, keyword: '' }, onLoad() { this.fetchList(); }, onPullDownRefresh() { this.setData({ page: 1, hasMore: true, list: [] }); this.fetchList(() => wx.stopPullDownRefresh()); }, onReachBottom() { if (this.data.hasMore) { this.setData({ page: this.data.page + 1 }); this.fetchList(); } }, fetchList(callback) { request({ url: '/api/recipe/list', data: { page: this.data.page, size: this.data.size, keyword: this.data.keyword } }).then((res) => { const list = this.data.page === 1 ? res.records : this.data.list.concat(res.records); this.setData({ list, hasMore: this.data.page < res.pages }); callback && callback(); }); } });

page和size是后端约定的分页参数,res.records和res.pages对应后端 MyBatis-Plus 分页返回的 JSON 字段。onReachBottom翻页时用concat追加而不是替换,避免用户滚到下面内容突然跳变。onPullDownRefresh重置分页条件再重新拉第一页,这里必须调用wx.stopPullDownRefresh()关闭顶部刷新动画,否则加载指示器会一直转。搜索功能不单独写逻辑,只是把keyword传给后端,由 Java 后端拼模糊查询条件。

页面要支持下拉刷新,还需要在pages/recipe/list.json里开启:

{ "usingComponents": {}, "enablePullDownRefresh": true, "backgroundTextStyle": "dark" }

backgroundTextStyle只有dark和light两个值,控制下拉刷新时顶部小圆点的颜色,深色背景配 dark 才看得清。

4. Java 后端源码与 MySQL 数据库,核心模块怎么搭

后端部分如果把每个类都过一遍,很容易陷进去。作为数据库课程设计视角来看,最先应该看的是建表语句和三层结构:MySQL 里表怎么建,Java 里 Controller、Service、Mapper 怎么分层,微信登录的 token 怎么签发。

4.1 建表:recipe 和 comment 两张核心表

菜谱表是家庭大厨的心脏,设计时要考虑后面查询和扩展:

CREATE TABLE `recipe` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', `title` varchar(100) NOT NULL COMMENT '菜名', `cover` varchar(255) DEFAULT '' COMMENT '封面图URL', `category_id` bigint DEFAULT NULL COMMENT '分类ID', `ingredients` text COMMENT '食材列表,JSON数组', `steps` text COMMENT '步骤列表,JSON数组', `difficulty` tinyint DEFAULT 1 COMMENT '难度:1简单 2中等 3困难', `view_count` int DEFAULT 0 COMMENT '浏览量', `user_id` bigint DEFAULT NULL COMMENT '发布人ID', `deleted` tinyint DEFAULT 0 COMMENT '逻辑删除:0正常 1删除', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_category_id` (`category_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜谱表';

ingredients和steps用 JSON 字符串存储,而不是拆成食材子表、步骤子表。原因是每道菜的食材数量和步骤数不固定,拆表意味着每次查询都要 JOIN 两到三张表,代码量翻倍。用 JSON 存,Java 后端读出来用 Jackson 解析成 List,小程序端拿到数组直接渲染,简单直接。deleted字段对应 2.2 节的逻辑删除配置,所有业务表都保留它。idx_category_id是分类查询的索引,没有这个索引,分类筛选会全表扫描。

评论表比菜谱表简单得多:

CREATE TABLE `comment` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', `recipe_id` bigint NOT NULL COMMENT '菜谱ID', `user_id` bigint NOT NULL COMMENT '评论用户ID', `content` varchar(500) NOT NULL DEFAULT '' COMMENT '评论内容', `deleted` tinyint DEFAULT 0 COMMENT '逻辑删除', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_recipe_id` (`recipe_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评论表';

注意这里没有真正创建FOREIGN KEY外键约束,只用普通索引关联。这不是偷懒,而是很多公司实际开发中默认不用物理外键:外键约束在删除主表记录时会阻止操作或级联误删,性能也有损耗。业务层面的关联靠 Java 代码维护,这也是答辩时值得主动讲出来的一点。

4.2 Controller-Service-Mapper:以一个菜谱列表接口为例

家庭大厨的后端三层结构很标准。Controller 只负责接收参数和返回结果,Service 写业务逻辑,Mapper 操作数据库。以菜谱列表接口为例:

@RestController @RequestMapping("/api/recipe") public class RecipeController { @Autowired private RecipeService recipeService; @GetMapping("/list") public Result list(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size, @RequestParam(required = false) String keyword, @RequestParam(required = false) Long categoryId) { LambdaQueryWrapper<Recipe> wrapper = new LambdaQueryWrapper<>(); wrapper.like(StringUtils.hasText(keyword), Recipe::getTitle, keyword) .eq(categoryId != null, Recipe::getCategoryId, categoryId) .orderByDesc(Recipe::getCreateTime); return Result.ok(recipeService.page(new Page<>(page, size), wrapper)); } }

LambdaQueryWrapper是 MyBatis-Plus 的条件构造器,like第一个参数是布尔表达式,为 false 时该条件不生效,这样搜索关键字为空时不会拼出多余的WHERE。.eq同理。Page对象封装了当前页和每页条数,返回结果里自带records、pages、total等字段,正好对应 3.3 节小程序端用到的字段名。

Service 实现类里不写复杂 SQL,更多是简单的字段更新逻辑:

@Service public class RecipeServiceImpl extends ServiceImpl<RecipeMapper, Recipe> implements RecipeService { @Override public void addViewCount(Long id) { Recipe recipe = this.getById(id); if (recipe != null) { recipe.setViewCount(recipe.getViewCount() + 1); this.updateById(recipe); } } }

getById和updateById都是 MyBatis-Plus 内置方法,updateById只更新非 null 字段,不会把create_time等字段覆盖掉。view_count浏览量在用户打开详情页时调用一次,虽然并发下会有精度损失,但毕业设计这个量级完全够用。如果老师追问并发问题,可以说生产环境会改用 Redis 计数再异步落库,这个回答可以体现知识面。

4.3 wx.login 换 openid,再签发自己的 token

微信登录是这套毕设里最容易被追问的环节。流程是:小程序wx.login拿到临时code,传给后端,后端拿 code 去微信接口换openid,再用自己的 token 机制给小程序发一张登录凭证。

Java 后端核心实现:

@PostMapping("/login") public Result login(@RequestBody Map<String, String> body) { String code = body.get("code"); String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code"; String wxResponse = restTemplate.getForObject(url, String.class); JSONObject jo = JSON.parseObject(wxResponse); String openid = jo.getString("openid"); User user = userMapper.selectByOpenid(openid); if (user == null) { user = new User(); user.setOpenid(openid); user.setNickname("微信用户"); userMapper.insert(user); } String token = UUID.randomUUID().toString().replace("-", ""); tokenStore.put(token, user.getId()); return Result.ok(token); }

code是小程序wx.login返回的临时凭证,5 分钟有效且只能使用一次,所以小程序端要尽快把它发给后端。jscode2session接口返回openid和session_key,其中openid是用户在当前小程序下的唯一标识。第一次登录的用户自动注册,后续每次登录都复用同一条 user 记录,这样就完成了“微信授权登录”的最小实现。签发 token 之后,后续请求通过拦截器从Authorization头里解析出用户 ID,鉴权问题闭环。

这套源码里如果配置了家庭成员的偏好,比如口味选择,小程序端可以用radio-group收集单选项,提交到后端的 profile 接口,对应一张user_profile表。这个功能虽然不大,但数据表、接口、页面三个维度都齐全,很适合写进论文的功能模块里。

5. 部署、验证与答辩演示:让开源毕设源码跑成作品

源码下载是一回事,在自己电脑上跑起来是另一回事。这一步把环境错误全部暴露出来,也顺便把使用说明里描述不清的地方补齐。

5.1 本地跑通的最小命令顺序

拿到源码后按下面的顺序操作,每一步确认通过再进下一步:

# 第一步:导入数据库 mysql -uroot -p family_chef < docs/sql/family_chef.sql # 第二步:启动 Java 后端 cd family-chef-server mvn spring-boot:run # 第三步:微信开发者工具导入 miniprogram 目录

数据库导入失败时,先确认 MySQL 版本和 root 密码,application.yml里的password必须和本机一致。后端启动失败时,看控制台第一行报错,九成是端口被占用或者数据库连接被拒。这一步涉及的 JDK 环境变量配置、Maven settings 镜像,都是在给后面的答辩排雷——环境越干净,演示越不容易翻车。

5.2 真机预览时的网络边界

开发者工具里能通,不代表手机能通。本地调试时,在微信开发者工具的“详情-本地设置”里勾选“不校验合法域名”,才能访问http://localhost:8080。真机调试时,把request.js里的BASE_URL从localhost改成电脑局域网 IP,两者必须在同一个 Wi-Fi 下。

提示:不校验合法域名只用于开发调试。小程序正式上线,后端接口必须配置 HTTPS 域名,并且把域名加入微信公众平台的服务器域名白名单。

如果项目部署到了云服务器,常见做法是用 Nginx 做反向代理,把/api/前缀转发到本机的 Java 服务:

server { listen 443 ssl; server_name api.familychef.example.com; location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

这段配置的意思是:所有以/api/开头的请求都转发到本机 8080 端口,小程序端只需要把BASE_URL改成https://api.familychef.example.com,不需要关心后端跑在哪台机器上。答辩现场如果网络条件不允许真机演示,可以提前录一段演示视频作为备份,很多学校的答辩环境网络受限,这是最保险的方案。

5.3 答辩演示路线与高频追问

演示不要从头到尾把页面点一遍,要有侧重。推荐按下面的顺序走,每个演示动作背后都藏着一个技术知识点:

演示动作演示内容答辩可能追问
1. 微信登录点击登录进入首页openid 怎么获取,token 过期怎么办
2. 搜索菜谱输入关键字点搜索分页参数怎么定的,为什么用 JSON 存步骤
3. 打开详情并评论浏览详情、写一条评论评论表怎么设计,删除是物理删除还是逻辑删除
4. 收藏操作点收藏再看收藏列表favorite 表怎么关联 recipe 和 user

这些追问基本和 Java 面试题、小程序八股高度重合,答好一个模块比背完整篇论文有用得多。演示后记得在开发者工具的 Network 面板里截图一张 login 请求的响应数据,论文中放进去,能直观展示“小程序-后端-数据库”的完整链路已打通。

本文还有配套的精品资源,点击获取

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

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

立即咨询