农产品商城小程序源码跑通指南:Java+小程序+MySQL电商闭环实战 简介这是一套面向计算机专业学生与初学者的农产品商城微信小程序毕业设计源码包采用Java后端加小程序前端的经典架构适合用于毕业设计、课程设计或小程序入门实战。压缩包共1241个文件约19.59MB包含131个Java源文件、226个JavaScript脚本、148个Vue组件以及49套wxml与wxss页面样式另有png、svg、jpg等图片素材和sql数据库脚本前后端代码与数据库文件齐全。项目基于JDK1.8、MySQL5.7、Maven3.3与Tomcat7构建后端可用eclipse或idea导入小程序端配合hbuildx或微信开发者工具调试并附有项目说明文档便于理解架构设计与功能模块划分。目前已有91人学习关注。通过这套源码读者可完整走通商品展示、用户交互到数据库读写的开发流程掌握前后端接口对接与部署方法是快速上手小程序项目开发的实用参考材料。1. 农产品商城小程序从一份毕设源码里拆出能跑通的电商骨架每年毕业季后台被问得最多的一类问题就是「农产品商城小程序源码java小程序mysql拿到手了怎么让它在我电脑上跑起来」。这个标题背后其实是一套非常典型的电商最小闭环微信小程序做前端展示与下单Java 后端提供接口MySQL 存商品、订单、用户三类核心数据。它解决的不是「做一个淘宝」而是让一个没有电商项目经验的人能在本地把「浏览商品 → 加购物车 → 下单 → 后台看到订单」这条链路完整走一遍。适合谁适合正在做毕设、需要一套能讲清楚分层架构和接口设计的同学也适合想从零理解小程序前后端如何对接的初级开发者。下面我按自己带人复现这类项目的顺序把选型、建库、接口、联调和踩坑一次讲透。2. 先想清楚技术选型为什么是 Java 小程序 MySQL 这套组合拿到一份农产品商城的源码第一件事不是急着npm install或者点运行而是先判断这套技术栈为什么长这样。想不明白选型理由后面改一个字段都会牵一发动全身。2.1 三端各自的职责边界小程序端只负责渲染和交互它不直接连数据库所有数据都通过 HTTPS 请求后端接口拿。Java 后端是唯一能碰 MySQL 的角色负责鉴权、业务校验、事务。MySQL 负责持久化商品、订单、用户、购物车这些表之间的关系决定了后端接口怎么写。这个边界一旦模糊最常见的翻车就是有人图省事在小程序里直接拼 SQL 或者把数据库账号写进前端配置。小程序代码是能被反编译的账号泄露等于数据库裸奔。所以看到源码里前端出现jdbc、datasource这类字样第一反应应该是警惕而不是觉得方便。农产品这个场景还有它的特殊性商品有季节性、有产地、有规格比如五斤装、十斤装库存波动大。这意味着商品表不能只设计成「名称价格图片」至少要留出规格、产地、单位、库存预警这些字段。很多通用商城模板直接套用跑起来没问题但一讲业务就露馅。2.2 后端框架与目录结构怎么读常见的 Java 后端有两种Spring Boot 单体或者 SSMSpring SpringMVC MyBatis。毕设类项目里 Spring Boot 占多数因为配置少、启动快。拿到源码先看根目录有没有pom.xml有就是 Maven 项目再看src/main/resources下有没有application.yml或application.properties数据库连接、端口、文件上传路径基本都在这。一个健康的目录结构大致是这样src/main/java/com/xxx/ ├── controller/ 接口层接收小程序请求 ├── service/ 业务逻辑 ├── mapper/ 数据库操作接口 ├── entity/ 实体类和表一一对应 └── config/ 跨域、拦截器、文件上传配置如果controller里塞满了 SQL 和业务判断说明分层没做好这种代码能跑但没法维护答辩时也容易被追问。读源码时优先看controller的注解RequestMapping、PostMapping决定了小程序该请求哪个地址。2.3 数据库表设计的最小集合农产品商城跑通闭环至少需要这几张表表名作用关键字段user用户信息id、openid、nickname、phoneproduct商品id、name、price、stock、origin、covercategory分类id、name、parent_idcart购物车id、user_id、product_id、numorders订单主表id、user_id、total、status、create_timeorder_item订单明细id、order_id、product_id、num、priceopenid是小程序登录后微信返回的用户唯一标识不要用昵称当主键昵称会变。orders和order_item拆开是标准做法一个订单多个商品拆开才能正确记录每个商品下单时的价格——注意是下单时的价格不是当前价格否则商品调价后历史订单金额就错了。提示建表时金额字段用decimal(10,2)不要用float浮点数算钱会出现0.10.20.30000000000000004这种玄学问题。3. 本地把项目跑起来环境、建库、启动的完整命令选型清楚了接下来是动手。这一章的目标是让你在本地看到接口返回数据别急着连小程序先把后端跑通。3.1 环境准备与版本对齐需要装的东西JDK 8 或 11看pom.xml里的java.version、Maven、MySQL 5.7 或 8.0、一个能发 HTTP 请求的工具。版本不对齐是新手第一大坑JDK 17 跑 JDK 8 编译的项目报错能看半天。先确认版本java -version mvn -v mysql --version三条命令输出正常再往下。如果mvn提示找不到命令说明环境变量没配先把MAVEN_HOME/bin加进 PATH。3.2 导入数据库并核对字符集源码里一般有个sql文件夹里面是.sql文件。导入命令# 登录 MySQL mysql -u root -p # 创建数据库字符集必须是 utf8mb4否则农产品名称里的生僻字会乱码 CREATE DATABASE farm_mall DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 退出后用命令行导入 exit mysql -u root -p farm_mall ./sql/farm_mall.sql导入完进去核对一下USE farm_mall; SHOW TABLES; SELECT COUNT(*) FROM product;如果product表是空的说明源码只给了结构没给数据你得自己插几条测试数据否则小程序首页一片空白会误以为接口坏了。3.3 改配置文件并启动后端打开application.yml重点改这几项server: port: 8080 # 后端端口被占用就换 8081 spring: datasource: url: jdbc:mysql://localhost:3306/farm_mall?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的密码 servlet: multipart: max-file-size: 10MB # 商品图片上传大小限制serverTimezone必须写不写 MySQL 8 会报时区错误。改完启动mvn clean package -DskipTests java -jar target/xxx.jar看到Started Application in x seconds就算起来了。用浏览器访问http://localhost:8080/product/list具体路径看 controller能返回 JSON 就说明后端通了。3.4 小程序端配置与联调小程序端用微信开发者工具打开找到请求封装文件通常在utils/request.js或config.js// 本地调试时指向本机后端 const BASE_URL http://localhost:8080; function request(url, method, data) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL url, method: method, data: data, header: { content-type: application/json }, success: res resolve(res.data), fail: err reject(err) }); }); }逻辑说明所有接口请求都走这个封装改地址只改一处。参数说明BASE_URL本地调试用localhost但真机预览时手机访问不到电脑的localhost得换成电脑局域网 IP并且开发者工具里要勾选「不校验合法域名」。注意小程序正式环境要求 HTTPS 且域名备案本地调试阶段先在开发者工具里关闭域名校验别在这上面卡太久。4. 核心接口怎么读怎么写商品、购物车、订单三条链路后端跑通只是开始真正决定这套源码能不能用的是三个核心接口的设计。这一章我按「读源码 → 理解逻辑 → 自己改」的顺序讲。4.1 商品列表与详情接口商品列表接口通常长这样GetMapping(/product/list) public Result list(RequestParam(defaultValue 1) Integer page, RequestParam(defaultValue 10) Integer size, RequestParam(required false) Integer categoryId) { PageHelper.startPage(page, size); ListProduct list productService.listByCategory(categoryId); return Result.success(list); }逻辑说明PageHelper.startPage是分页插件紧跟其后的第一条查询会自动分页。参数说明page当前页size每页条数categoryId分类筛选为空则查全部。这里有个容易忽略的点——分页插件必须紧挨着查询语句中间插了别的查询分页就会作用到错误的 SQL 上。农产品场景建议在列表接口里加上「产地」和「是否当季」的筛选参数这是和通用商城拉开差距的地方答辩时也是加分项。4.2 购物车接口的并发问题购物车加购接口看着简单其实藏着并发坑PostMapping(/cart/add) public Result add(RequestBody CartDTO dto) { // 先查该用户购物车里是否已有该商品 Cart exist cartService.findByUserAndProduct(dto.getUserId(), dto.getProductId()); if (exist ! null) { exist.setNum(exist.getNum() dto.getNum()); cartService.update(exist); } else { Cart cart new Cart(); cart.setUserId(dto.getUserId()); cart.setProductId(dto.getProductId()); cart.setNum(dto.getNum()); cartService.insert(cart); } return Result.success(); }逻辑说明先查后改存在就累加数量不存在就新增。参数说明userId从登录态取不要信前端传的productId和num由前端传。这段代码在单机低并发下没问题但同一用户快速点两次加购可能两条请求都查到「不存在」然后插入两条记录。解决办法是给(user_id, product_id)建唯一索引插入冲突时改成更新。这是典型的血泪经验测试时不点快一点根本发现不了。4.3 下单接口与事务边界下单是整个项目最不能出错的地方库存扣减和订单写入必须在同一个事务里Transactional(rollbackFor Exception.class) public Result createOrder(Long userId, ListOrderItemDTO items) { BigDecimal total BigDecimal.ZERO; for (OrderItemDTO item : items) { // 扣库存带库存判断防止超卖 int affected productMapper.reduceStock(item.getProductId(), item.getNum()); if (affected 0) { throw new RuntimeException(库存不足 item.getProductId()); } Product p productMapper.selectById(item.getProductId()); total total.add(p.getPrice().multiply(new BigDecimal(item.getNum()))); } // 写订单主表和明细表 Orders order new Orders(); order.setUserId(userId); order.setTotal(total); order.setStatus(0); // 0 待付款 orderMapper.insert(order); // ... 写 order_item return Result.success(order.getId()); }逻辑说明Transactional保证扣库存和写订单要么全成功要么全回滚。参数说明rollbackFor Exception.class让所有异常都触发回滚默认只回滚运行时异常受检异常不回滚这是个经典坑。扣库存的 SQL 要写成UPDATE product SET stock stock - #{num} WHERE id #{id} AND stock #{num}用数据库的行锁保证不超卖而不是先查库存再判断再更新后者在并发下必然超卖。5. 避坑与排查这类毕设源码最容易翻车的五个地方带人复现这类项目翻车点高度集中。下面五条按「现象 → 原因 → 解决」写遇到问题先对照排查。现象一小程序请求全部失败报「不在以下 request 合法域名列表中」。原因开发者工具默认校验域名本地localhost或 IP 不在白名单。 解决开发者工具右上角「详情 → 本地设置」勾选「不校验合法域名、web-view、TLS 版本以及 HTTPS 证书」。真机预览时把BASE_URL换成电脑局域网 IP手机和电脑连同一个 WiFi。现象二后端启动报「Access denied for user rootlocalhost」。原因application.yml里的数据库密码和本机 MySQL 密码不一致或者 MySQL 没启动。 解决先用命令行mysql -u root -p确认能登录再核对配置文件密码。MySQL 8 还要注意caching_sha2_password认证插件老版本驱动连不上要么升级驱动要么改用户认证方式。现象三商品图片上传成功但小程序显示裂图。原因后端把图片存到了本地磁盘但没配置静态资源映射或者小程序请求的图片地址拼错了。 解决在后端加静态资源映射配置把上传目录暴露成可访问的 URL 路径小程序端确认图片地址是完整 URL 而不是相对路径。现象四下单后订单列表查不到但数据库里明明有数据。原因查询订单时按user_id过滤但下单时写入的user_id和登录态里的对不上常见于前端传了错误的 userId。 解决下单接口的userId必须从后端登录态token 或 session里取绝不接受前端传参。这是安全底线也是数据一致性的前提。现象五中文商品名在数据库里显示成问号。原因建库或建表时字符集用了latin1或utf8不是utf8mb4。 解决重建库表用utf8mb4连接 URL 里加characterEncodingutf8。已经乱码的数据改不回来只能重新导入。提示排查接口问题先看后端控制台有没有异常堆栈再看浏览器 Network 或开发者工具 Network 里的请求地址、参数、返回码。90% 的问题在这两处就能定位。6. 让这套源码从「能跑」变成「能讲」三个进阶改造点跑通只是及格线毕设要拿得出手得有自己的东西。分享三个我一般会建议加的改造点成本不高但效果明显。第一个是给商品加「当季推荐」标签。在product表加一个is_seasonal字段后端列表接口支持按这个字段筛选小程序首页做一个「当季鲜品」专区。改动量小但把农产品商城的业务特点讲出来了比通用商城模板有说服力。第二个是把下单接口的库存扣减改成乐观锁版本号方案或者用 Redis 预扣库存。前者适合讲并发控制原理后者适合讲缓存与数据库一致性。选一个你能讲清楚的就行别贪多。我一般让学生先做乐观锁因为不引入额外中间件代码改动集中在product表和扣减 SQL。第三个是加一个简单的订单状态机。订单状态从「待付款 → 已付款 → 已发货 → 已完成」每次状态变更校验前置状态防止「待付款」直接跳到「已完成」。用一个枚举加一个校验方法就能实现public enum OrderStatus { UNPAID(0), PAID(1), SHIPPED(2), FINISHED(3), CANCELLED(9); private final int code; OrderStatus(int code) { this.code code; } public int getCode() { return code; } // 校验状态流转是否合法 public static boolean canTransfer(int from, int to) { if (from UNPAID.code (to PAID.code || to CANCELLED.code)) return true; if (from PAID.code to SHIPPED.code) return true; if (from SHIPPED.code to FINISHED.code) return true; return false; } }逻辑说明canTransfer定义合法流转路径状态更新前先校验。参数说明from当前状态码to目标状态码。这段代码在答辩时能直接讲「如何防止订单状态被非法篡改」比单纯 CRUD 有深度。最后说个我自己的习惯每改一个功能先在纸上画出数据从哪张表流到哪张表再动手写代码。这套农产品商城源码的价值不在于它多完整而在于它给了你一个能拆、能改、能讲清楚的骨架。把它跑通再挑一两个点改出自己的东西这个方向就值得投入。希望帮到你。本文还有配套的精品资源点击获取