简介:这是一套面向高校计算机相关专业学生与初学者的农产品商城微信小程序毕业设计源码包,采用Java作为后端开发语言,配合小程序前端与MySQL数据库,适合用于毕业设计、课程设计或小程序入门实战练习。压缩包共1241个文件,约19.59MB,涵盖131个Java后端源码、226个JavaScript脚本、148个Vue组件、49个wxml与49个wxss小程序页面样式,以及278张png图片、40张jpg素材和1个sql数据库文件,另附项目说明文档与构建脚本,前后端与数据库资源齐全。项目基于JDK1.8、MySQL5.7、Maven3.3与Tomcat7搭建,前端可用hbuildx或微信开发者工具调试,后端支持eclipse或idea导入运行。目前已有91人学习关注。读者可借此完整理解农产品商城的商品展示、用户交互与前后端数据交互流程,掌握从数据库设计到接口联调、再到小程序部署的整套开发思路,是一份可直接参考复用的实践材料。
1. 农产品商城小程序:一份能跑通前后端的 Java 毕业设计源码
每年到了毕设选题季,总有一批同学卡在“想做个电商类小程序,但后端不知道从哪下手”这一步。这份农产品商城小程序源码,走的是 Java 后端 + 微信小程序前端 + MySQL 存储的经典三件套路线,正好命中“小程序 java 毕业设计 课程设计 源码”这个高频检索组合。它解决的不是“从零教你写代码”的问题,而是给你一套结构完整、能本地跑起来、能改能交差的工程骨架。适合谁?适合已经学过 Java Web 基础、能看懂 Controller 和 Service 分层、但没独立做过完整项目的大三大四学生,也适合需要快速搭一个商城 Demo 做课程设计验收的开发者。下面我按“先跑通、再拆解、后避坑”的顺序,把这份源码从环境配置到二次开发讲透。
2. 环境搭建与工程结构:把项目从压缩包跑到浏览器
拿到一个.zip源码包,最忌讳的就是双击解压后直接开 IDE 乱点。农产品商城这类项目,前后端是分离的,小程序端和后端服务各自独立,必须先把后端跑起来,再用开发者工具连前端。这一章把环境版本、目录职责、启动顺序讲清楚,照着做基本能避开 80% 的“启动即报错”。
2.1 后端技术栈与版本对齐
这份源码后端是标准的 Spring Boot + MyBatis + MySQL 组合,这是目前 Java 毕设里最稳的选型,资料多、报错好搜。但版本不对齐是新手翻车的重灾区,我一般会先确认三件事:JDK 版本、Maven 依赖、MySQL 驱动。
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 1.8 或 11 | 源码里若用了javax包,优先 1.8 |
| Maven | 3.6+ | 用于拉取依赖,注意配置国内镜像 |
| MySQL | 5.7 或 8.0 | 8.0 需注意驱动类名和时区参数 |
| Spring Boot | 2.x | 与 JDK 1.8 兼容性最好 |
先别急着改代码,第一步是确认pom.xml里的 Spring Boot 父版本。如果父版本是 2.7.x,JDK 就别用 17,否则编译期就可能因为反射限制报错。MySQL 8.0 的连接串必须带serverTimezone=Asia/Shanghai,否则启动时大概率抛时区异常。
<!-- pom.xml 关键依赖片段,确认版本是否匹配本机环境 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.6</version> <!-- 与 JDK 1.8 搭配稳定 --> </parent> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> <!-- 8.0 驱动,连接串需加时区 --> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> </dependencies>上面这段依赖里,mysql-connector-java的版本决定了连接串写法。用 8.0 驱动时,url要写成jdbc:mysql://localhost:3306/farm_mall?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false。useSSL=false在本地开发时能省掉证书警告,但上线必须开。MyBatis-Plus 的版本影响分页插件配置,3.5.x 用MybatisPlusInterceptor,老版本用PaginationInterceptor,改错直接导致分页失效。
2.2 数据库导入与配置修改
源码包里通常有一个sql文件夹,里面是建表语句和初始数据。导入顺序不能乱:先建库,再导表,最后核对字段。
# 1. 登录 MySQL 并创建数据库,字符集必须 utf8mb4 mysql -u root -p CREATE DATABASE farm_mall DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 2. 退出后导入 sql 文件,注意路径替换成实际解压位置 mysql -u root -p farm_mall < /path/to/sql/farm_mall.sql # 3. 验证表是否导入成功 mysql -u root -p -e "USE farm_mall; SHOW TABLES;"导入完成后,打开后端项目的application.yml,把数据库账号密码改成自己本机的。这里有个血泪经验:很多同学本机 MySQL 密码是空的或者123456,但源码里写的是root,启动时连接池直接报Access denied。改完配置后,还要检查mapper文件里的字段映射,农产品商城常见的表有product(商品)、order(订单)、user(用户)、category(分类),如果导入后字段名和实体类对不上,查询会返回null。
2.3 启动后端并验证接口
配置改完后,用 Maven 打包或直接在 IDE 里跑Application主类。启动成功的标志是控制台出现Started Application in x seconds,且没有Communications link failure。
# 在项目根目录执行,跳过测试类避免因环境问题卡住 mvn clean package -DskipTests # 启动 jar 包,指定配置文件为本地 java -jar target/farm-mall-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev启动后别急着开小程序,先用浏览器或 Postman 测一个接口。比如商品列表接口通常是GET /api/product/list,如果返回 JSON 里有数据,说明后端和数据库已经通了。这一步是整个流程的“地基”,地基没打好,小程序端连上来也是白屏。
3. 小程序端对接:从开发者工具到真机预览
后端跑通只是完成了一半,小程序端才是用户真正看到的部分。这一章讲微信开发者工具的项目导入、请求封装、以及如何把本地后端地址配到小程序里。很多同学卡在“请求失败”上,其实问题往往出在域名校验和端口上。
3.1 导入项目与目录说明
打开微信开发者工具,选择“导入项目”,目录指向源码包里的小程序文件夹(通常叫miniprogram或wx-app)。AppID 可以先用测试号,或者填自己的。导入后先看目录结构:
pages/:页面目录,农产品商城一般有首页、分类、购物车、订单、个人中心utils/:工具函数,重点看request.js,里面封装了wx.requestconfig/:有些项目会把后端地址放在这里,方便统一修改
导入后如果工具提示“找不到 app.json”,说明目录选错了,要选到包含app.json的那一层。这一步看似简单,但每年都有人把整个压缩包根目录导进去,结果工具直接报错。
3.2 请求地址配置与本地调试
小程序默认只能请求 HTTPS 域名,但本地开发时后端是http://localhost:8080,所以必须在开发者工具里勾选“不校验合法域名”。这个选项在“详情 → 本地设置”里,勾上之后本地请求才能通。
// utils/request.js 里通常有这样的封装,重点看 baseUrl const baseUrl = 'http://localhost:8080/api'; // 本地调试地址 function request(url, method = 'GET', data = {}) { return new Promise((resolve, reject) => { wx.request({ url: baseUrl + url, method: method, data: data, header: { 'content-type': 'application/json' }, success: (res) => { if (res.data.code === 200) { resolve(res.data.data); // 后端统一返回结构 } else { wx.showToast({ title: res.data.msg || '请求失败', icon: 'none' }); reject(res.data); } }, fail: (err) => { console.error('网络请求失败', err); reject(err); } }); }); }这段代码里,baseUrl是核心参数。如果你后端跑在 8080,就写 8080;如果改了端口,这里必须同步。header里的content-type决定了后端能不能正确解析 JSON,漏了可能收到415错误。success回调里判断code === 200是常见约定,但有些源码用code === 0,改之前先看后端返回结构。
3.3 真机预览与常见连接问题
在开发者工具里点“预览”,用手机扫码就能真机查看。但真机预览时,localhost是不通的,因为手机和电脑不在同一个“localhost”上。这时候有两种做法:一是把后端部署到局域网 IP(比如192.168.x.x),二是用内网穿透工具。局域网方案更简单,把baseUrl改成电脑的局域网 IP,手机连同一个 WiFi 即可。
提示:真机预览时如果图片加载不出来,检查图片路径是相对路径还是绝对路径。小程序里图片一般用
https或本地静态资源,http图片在真机上可能被拦截。
另外,农产品商城的商品图片通常存在后端服务器或第三方图床,如果源码里图片地址写的是localhost,真机上必然裂图。改法是批量替换成局域网 IP 或图床地址。这一步没有捷径,只能全局搜索替换。
4. 核心业务模块拆解:商品、订单、购物车怎么串起来
跑通之后,如果只是交个作业,其实已经够了。但如果你想在答辩时讲出东西,或者想改点功能,就得理解业务模块之间的数据流。这一章拆三个核心模块:商品展示、购物车、订单生成。它们之间的调用关系,是面试和答辩的高频追问点。
4.1 商品列表与分类查询
商品模块的入口在首页,通常按分类展示。后端接口一般有两个:/product/list查全部,/product/category/{id}按分类查。前端用wx:for渲染列表,点击跳详情。
// pages/index/index.js 商品列表加载逻辑 Page({ data: { products: [], categories: [] }, onLoad() { this.loadCategories(); this.loadProducts(); }, loadProducts() { request('/product/list', 'GET').then(res => { this.setData({ products: res }); // res 是后端返回的数组 }); }, loadCategories() { request('/category/list', 'GET').then(res => { this.setData({ categories: res }); }); } });这里setData是小程序更新视图的唯一方式,直接改this.data.products不会触发渲染。onLoad里两个请求是并行的,如果后端响应慢,页面会先白屏再出内容。优化做法是加wx.showLoading,但毕设阶段不强制。
4.2 购物车的数据结构设计
购物车是农产品商城里最容易出 bug 的模块,因为它涉及本地存储和服务端同步。常见做法是:未登录时用wx.setStorageSync存本地,登录后同步到后端cart表。
| 字段 | 类型 | 说明 |
|---|---|---|
| cartId | int | 购物车记录主键 |
| userId | int | 用户 ID,未登录为 0 |
| productId | int | 商品 ID |
| quantity | int | 数量,不能为 0 |
| checked | tinyint | 是否选中,1 选中 0 未选 |
本地存储的结构通常是数组,每个元素包含productId和quantity。加入购物车时先查本地有没有该商品,有就数量加一,没有就 push。这个逻辑写在utils/cart.js里,页面调用即可。
// utils/cart.js 本地购物车操作 function addToCart(product) { let cart = wx.getStorageSync('cart') || []; const index = cart.findIndex(item => item.productId === product.id); if (index > -1) { cart[index].quantity += 1; // 已存在则数量加一 } else { cart.push({ productId: product.id, quantity: 1, checked: true }); } wx.setStorageSync('cart', cart); wx.showToast({ title: '已加入购物车', icon: 'success' }); }findIndex是 ES6 方法,小程序基础库支持,但老版本工具可能报错,升级工具即可。checked字段用于结算时筛选,如果漏了,结算页会全选或全不选。
4.3 订单生成与库存扣减
订单模块是后端逻辑最重的地方。用户点“提交订单”后,后端要做三件事:生成订单记录、扣减商品库存、清空购物车。这三步必须在一个事务里,否则会出现“订单生成了但库存没扣”的脏数据。
// OrderServiceImpl.java 下单核心逻辑 @Transactional public Order createOrder(Integer userId, List<CartItem> items) { Order order = new Order(); order.setUserId(userId); order.setOrderNo(UUID.randomUUID().toString()); // 订单号 order.setStatus(0); // 0 待支付 orderMapper.insert(order); for (CartItem item : items) { // 扣库存,update 语句带 stock >= quantity 条件防止超卖 int rows = productMapper.reduceStock(item.getProductId(), item.getQuantity()); if (rows == 0) { throw new RuntimeException("库存不足"); // 触发回滚 } orderItemMapper.insert(new OrderItem(order.getId(), item.getProductId(), item.getQuantity())); } cartMapper.deleteByUserId(userId); // 清空购物车 return order; }@Transactional注解保证异常时回滚。reduceStock的 SQL 必须是UPDATE product SET stock = stock - #{quantity} WHERE id = #{id} AND stock >= #{quantity},这样在并发下也不会扣成负数。很多毕设源码漏了这个条件,答辩时被问到“超卖怎么处理”就答不上来。
5. 避坑与排查:那些让项目跑不起来的细节
这一章是我拆这类源码时踩过的坑,按“现象 → 原因 → 解决”整理。每一条都对应真实报错,照着排查能省不少时间。
5.1 启动报错:Communications link failure
现象:后端启动时控制台抛Communications link failure,或Access denied for user。原因:数据库没启动、账号密码不对、或 MySQL 8.0 没配时区。解决:先确认 MySQL 服务在运行,再用命令行登录验证账号密码。如果是 8.0,连接串加serverTimezone=Asia/Shanghai,驱动类用com.mysql.cj.jdbc.Driver。
5.2 小程序请求失败:不在以下 request 合法域名列表中
现象:开发者工具控制台报“不在以下 request 合法域名列表中”,请求发不出去。原因:没勾选“不校验合法域名”,或baseUrl写的是https但本地是http。解决:详情 → 本地设置 → 勾选“不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书”。真机预览时改用局域网 IP。
5.3 图片不显示:路径拼接错误
现象:商品列表有数据,但图片全是裂图。原因:后端返回的图片路径是相对路径,前端没拼域名;或路径里带了localhost,真机访问不到。解决:在后端返回图片字段时拼上完整域名,或前端用baseUrl + imagePath。真机调试时把localhost换成局域网 IP。
5.4 分页失效:MyBatis-Plus 插件没配
现象:商品列表接口返回全部数据,limit不生效。原因:MyBatis-Plus 分页插件没注册,或版本不对应。解决:在配置类里注册MybatisPlusInterceptor并添加PaginationInnerInterceptor。3.5.x 版本必须用新写法,老写法已废弃。
5.5 订单重复提交:前端没做防抖
现象:用户快速点两次“提交订单”,生成两条订单记录。原因:前端按钮没禁用,或后端没做幂等。解决:前端点击后立即setData({ submitting: true })禁用按钮;后端用订单号唯一索引或 Redis 锁做幂等。毕设阶段前端禁用就能应付。
6. 二次开发与答辩加分:把源码改成自己的东西
源码跑通只是起点,真正拉开差距的是你能改出什么。这一章给几个低成本、高回报的改造方向,以及答辩时怎么讲清楚技术选型。
6.1 加一个“农产品溯源”字段
农产品商城的天然优势是“溯源”概念。你可以在product表加origin(产地)、harvest_date(采摘日期)两个字段,前端详情页展示。这个改动小,但答辩时能讲出“结合农产品特性”的故事。
-- 在 product 表增加溯源字段 ALTER TABLE product ADD COLUMN origin VARCHAR(100) COMMENT '产地'; ALTER TABLE product ADD COLUMN harvest_date DATE COMMENT '采摘日期';改完表结构后,同步改实体类Product.java和 Mapper XML 的resultMap,否则查询返回null。前端在detail.wxml里加两行展示即可。
6.2 用 Redis 缓存商品分类
如果答辩想体现“性能优化”,可以引入 Redis 缓存分类数据。分类变动少,适合缓存。在CategoryServiceImpl里加@Cacheable注解,或手动用RedisTemplate。
| 改造点 | 成本 | 答辩收益 |
|---|---|---|
| 加溯源字段 | 低 | 中,体现业务理解 |
| Redis 缓存 | 中 | 高,体现技术深度 |
| 订单超时取消 | 高 | 高,但耗时 |
6.3 答辩时怎么讲技术选型
被问到“为什么用 Spring Boot 不用 SSM”时,别背概念。我一般会说:Spring Boot 内嵌 Tomcat,省了配 web.xml;起步依赖把版本冲突管住了,毕设周期短,稳定优先。被问到“小程序为什么不用 uni-app”时,答:原生小程序对微信生态兼容最好,调用wx.login、wx.requestPayment没有中间层损耗,调试也直接。
从那以后我每次拆这类源码,都强制自己先跑通再改,绝不一边跑一边改。希望帮到你。
本文还有配套的精品资源,点击获取