☰
SpringBoot+微信小程序+uni-app农产品交易平台全栈项目实战解析
2026/10/13 19:34:57 网站建设 项目流程

做这个基于SpringBoot的微信小程序农产品交易平台,前后花了大概两个月时间。整套项目包含SpringBoot后端、基于Vue语法的uni-app小程序端、Vue3管理后台,源码、文档、SQL脚本、调试说明都整理齐了,本地跑通也就一天的事。这篇文章我就拿这套项目当例子,把从设计思路到落地实现的全过程拆开讲,重点说说那些网上资料很散、实际一跑就踩坑的环节——微信登录的会话密钥、跨域配置、小程序真机调试、支付回调的幂等处理。不管你是做毕设,还是想完整学习前后端分离的全栈项目,或者对农产品电商这个方向有兴趣,这篇内容应该能帮你少走不少弯路。

1. 项目定位:这套系统到底在解决什么问题

1.1 农产品交易的核心痛点拆解

先聊一个最核心的问题:为什么农产品需要单独的电商平台,而不是简单套一个通用商城?

农产品的交易场景跟工业品差别很大。首先是商品非标准化,同一批土豆,有大有小有破损,没法像手机一样用固定SKU描述。其次信息不对称严重,消费者不知道产地、新鲜度、有没有打药,农户找不到稳定销路,中间商层层加价,两端都不满意。再者物流时效要求高,生鲜品类从采摘到消费者手里,时间窗口很短,订单流转效率直接决定损耗率。

这套平台的设计目标就是围绕这几个痛点展开的:农户或者商家通过管理后台发布商品,把产地、规格、单位、检测信息都填清楚;买家在小程序端浏览、搜索、下单、支付;平台方在后台处理订单、管理商品、做基础的数据统计。三个角色各干各的事,业务闭环就完整了。

1.2 为什么选SpringBoot + 微信小程序 + Vue这套组合

这个技术组合不是拍脑袋定的,而是基于项目自身特点做的取舍。

后端用SpringBoot,最大理由是生态成熟、配置少、社区资料极其丰富。一个农产品交易平台,核心业务不外乎用户、商品、购物车、订单、支付这几块,SpringBoot + MyBatis Plus这套组合可以非常高效地把CRUD和复杂查询撑起来,遇到问题搜一下基本都有现成答案,对新手极其友好。

前端拆成两端,小程序端选uni-app,理由也很直接:它基于Vue语法,会Vue的人上手几乎没有学习成本,而且一套代码可以同时编译到微信小程序、H5、App,将来想扩展终端不用重写。管理后台用Vue3 + Element Plus,做表格、表单、弹窗这些后台管理界面非常顺手。所以标题里写的"vue"其实覆盖了两个地方——小程序端的uni-app和后台管理的Vue3,这个后面展开讲。

前后端分离则是从协作和迭代角度考虑的。后端只提供RESTful接口,不关心页面渲染;前端专注交互和展示,通过axios发请求拿数据。两边职责边界清晰,后端可以独立测试,前端可以本地Mock,联调阶段出了问题也能快速定位是接口的锅还是页面的锅。

1.3 项目功能地图与角色权限

整个系统按角色划分成三大块:

角色使用端核心功能
买家微信小程序商品浏览搜索、加入购物车、下单支付、订单查询、地址管理、商品收藏
商家管理后台商品发布与管理、库存维护、订单发货、查看销售数据
管理员管理后台用户管理、商品审核、分类管理、轮播图配置、订单监管、平台统计

订单状态流转是交易系统的核心线索,设计时要一次想清楚。这套项目里订单状态是这么设计的:待付款 -> 待发货 -> 待收货 -> 已完成,中间穿插退款和取消。前端展示订单列表时,直接按状态值切分Tab,后端接口根据状态字段查数据,非常简单直白。

2. 后端核心实现:从数据库到接口的完整链路

2.1 工程结构怎么组织才不乱

一个农产品交易平台的后端虽然不算大,但如果代码全堆在一起,后期维护和扩展会很难受。这套项目的工程结构按照经典的三层架构来划分,同时用Maven多模块保持职责清晰。

controller层只做参数接收和结果封装,service层放业务逻辑,mapper层操作数据库,entity对应表结构,dto接收前端请求参数,vo返回给前端展示,config放配置类(跨域、拦截器、微信参数),common放统一返回结果和异常处理。

module模块划分上也做了区分:auth模块管登录注册和token校验,product模块管商品分类和商品信息,order模块管购物车、订单、支付回调,user模块管地址和收货信息,admin模块管后台管理接口。每个模块自己维护一套controller、service、mapper,互不干扰,后面要加功能只需要横向扩展模块就行。

2.2 微信登录与会话鉴权是怎么设计的

微信小程序登录跟传统账号密码登录完全不同,这是很多第一次做小程序项目的开发者最懵的地方。

整个流程是这样的:小程序端调用wx.login()拿到一个临时凭证code,这个code的有效期只有五分钟,而且只能用一次。前端把这个code传给后端,后端拿着code加上小程序的appid和secret,去微信的接口换session_key和openid。openid是用户在当前小程序下的唯一标识,相当于用户的身份证号。后端拿到openid后查数据库,查不到就自动注册一个新用户,查到就直接走登录逻辑。

拿到openid之后,要解决的问题是后续请求怎么鉴权。项目里用的是JWT方案,把userId和角色信息加密签成一个token返回给前端,小程序端把token存到storage里,之后的每次请求都在请求头里带上。后端用一个拦截器统一校验token,校验不过直接返回401,前端收到401就跳转登录页。

// 登录接口核心逻辑(已简化) @PostMapping("/login") public Result<String> login(@RequestBody LoginDTO dto) { // 1. 用code换openid Map<String, String> wxResult = wxService.code2Session(dto.getCode()); String openid = wxResult.get("openid"); // 2. 查用户,不存在则注册 User user = userService.findByOpenid(openid); if (user == null) { user = userService.register(openid, dto.getNickname(), dto.getAvatar()); } // 3. 签发token String token = jwtUtil.generateToken(user.getId(), user.getRole()); return Result.success(token); }

这里有个非常容易踩的坑:小程序端换code的操作要在登录页面加载时完成,但如果用户的微信授权被拒绝,头像和昵称可能拿不到。项目中采用了二次授权的策略,第一次用wx.login拿code静默登录,用户进入个人中心后如果想完善资料再调用getUserProfile接口。实际开发中这个降级方案非常实用。

2.3 农产品商品的数据建模,跟普通电商有什么区别

商品表是交易系统的地基,这块设计得好,后面所有功能都顺畅。

农产品有别于标准工业品,建模时我特意加了一些字段:unit字段表示单位,可以是斤、箱、件、提;origin表示产地,让买家一眼知道东西从哪来;tags用逗号分隔的字符串存标签,比如"现摘"、"预售"、"坏果包赔";detail用富文本存详情,可以插入图片和文字排版的介绍;detect_img存检测报告图片的URL,增强买家信任感。

CREATE TABLE `product` ( `id` int NOT NULL AUTO_INCREMENT, `category_id` int NOT NULL COMMENT '分类ID', `name` varchar(100) NOT NULL COMMENT '商品名称', `cover` varchar(255) DEFAULT NULL COMMENT '封面图', `images` text COMMENT '轮播图,逗号分隔', `price` decimal(10,2) NOT NULL COMMENT '价格', `original_price` decimal(10,2) DEFAULT NULL COMMENT '划线价', `unit` varchar(20) DEFAULT NULL COMMENT '单位:斤/箱/件', `stock` int NOT NULL DEFAULT '0' COMMENT '库存', `sales` int NOT NULL DEFAULT '0' COMMENT '销量', `origin` varchar(100) DEFAULT NULL COMMENT '产地', `tags` varchar(255) DEFAULT NULL COMMENT '标签,逗号分隔', `detect_img` varchar(255) DEFAULT NULL COMMENT '检测报告图', `status` tinyint DEFAULT '1' COMMENT '1上架 0下架', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

数据库的seed数据也要下功夫。一套好的演示数据能让项目启动后立刻有内容可看,而不是空荡荡的。当时我准备了大概六个分类、二十个商品,每个商品都配上真实的产地信息和一张风格统一的配图,演示效果好了,后面做界面联调也顺畅得多。

2.4 订单与支付回调,如何保证数据不出错

订单系统的设计核心是状态机和数据一致性。

下单的逻辑是:前端提交商品ID和数量,后端先查商品当前库存够不够,够就扣减库存并生成订单主表和订单明细表,不够就返回"库存不足"。这里有个并发问题——如果两个用户同时买最后一个商品怎么办?最简单可靠的做法是数据库层面的乐观锁,更新库存的SQL语句里带上stock > 0条件,影响行数为0说明卖完了。

-- 乐观锁扣减库存 UPDATE product SET stock = stock - #{quantity} WHERE id = #{productId} AND stock >= #{quantity}

支付环节是毕设和真实项目差距最大的地方。真实环境需要商户号、API证书、回调域名,审核流程长,调试成本高。我在项目里做了模拟支付加真实回调的双通道设计。开发调试时走模拟支付,直接调回调接口把订单状态改成已支付;上线时替换成真实的微信支付配置,业务代码不用改。支付回调的处理必须做幂等——同一个回调通知可能会发多次,所以先查订单状态,已经是已支付就直接返回成功,不再重复处理。

3. 前端落地:小程序端与管理后台的实现细节

3.1 小程序端基于uni-app的页面架构

小程序端的目录结构是标准的uni-app风格。pages目录按业务模块分:首页、分类、购物车、订单、个人中心这几个主Tab;subpackages目录放次级页面,比如商品详情、确认订单、地址编辑、订单列表等。

首页是门面,设计上分了四块:搜索框、轮播图、分类快捷入口、推荐商品列表。轮播图数据从后端的banner接口拉取,管理员可以在后台配置图片和跳转链接。推荐商品列表用商品分页接口的前几条填充,后端排序规则是销量降序加创建时间倒序。这个页面虽然逻辑不复杂,但要注意图片尺寸的统一,轮播图建议用750x300比例的图,商品封面统一用正方形,否则界面会乱。

网络请求封装在一个api.js文件里,统一设置baseURL、超时时间和请求头。

// utils/request.js 关键封装 const BASE_URL = 'http://192.168.1.100:8080/api'; export function request(config) { return new Promise((resolve, reject) => { uni.request({ url: BASE_URL + config.url, method: config.method || 'GET', data: config.data || {}, header: { 'token': uni.getStorageSync('token') || '', 'Content-Type': 'application/json' }, success: (res) => { if (res.data.code === 200) { resolve(res.data); } else if (res.data.code === 401) { // 登录态过期,跳转登录页 uni.navigateTo({ url: '/pages/login/login' }); reject(new Error('未登录')); } else { uni.showToast({ title: res.data.msg, icon: 'none' }); reject(new Error(res.data.msg)); } }, fail: (err) => reject(err) }); }); }

这个小程序设计上遵循了字段命名与后端保持一致的习惯,下单、购物车、收藏这些接口直接按后端字段来了,前端展示时省掉了字段转换的麻烦,各有取舍吧。实际来看联调效率确实高了不少。

3.2 管理后台:Vue3 + Element Plus的快速开发

管理后台用的是Vue3 + Vite + Element Plus。从工程脚手架搭建到界面实现非常高效,主要原因就是Element Plus的组件覆盖了后台管理几乎所有的交互场景。

后台的框架结构是典型的侧边栏加顶部栏布局,侧边栏用Vue Router的meta信息自动生成菜单,顶部放折叠按钮和用户徽标。功能页面包括:商品列表(支持上下架、编辑、删除)、商品编辑(表单加图片上传)、分类管理、订单列表(查看详情、发货操作)、用户列表、轮播图配置、数据概览。

商品编辑页是表单最复杂的页面,涉及基本信息、价格库存、详情图片、检测报告上传。图片上传单独封装了一个Upload组件,统一对接文件上传接口,返回图片URL后回填到表单。数据概览页面用卡片加图表展示商品数、订单数、销售额、用户数,图表用ECharts的Vue封装实现,刷新频率不用设太高,每天早上看一次就行。

3.3 前后端接口规范与联调的关键约定

前后端分离最容易出问题的不是功能实现,而是接口规范不一致。这套项目在开发前就定死了几个约定。

接口前缀统一是/api,后端通过server.servlet.context-path配置。后端所有返回结构统一是Result对象:code=200表示成功,code=401表示未登录,code=500表示业务异常,msg描述具体信息。分页请求统一用pageNum和pageSize参数,分页响应统一是{ records, total }结构。时间格式统一用"yyyy-MM-dd HH:mm:ss"字符串,前端不做额外解析。

这些约定看着简单,但真的能让联调效率翻倍。之前我带的一个项目,前后端各写各的,字段命名一个用驼峰一个用下划线,时间一个传时间戳一个传字符串,联调阶段光改字段就花了一周。规范定在前面,后面就是纯逻辑对接了。

跨域问题的处理也很关键。小程序端本身没有跨域限制,但管理后台跑在浏览器里,访问后端接口会触发CORS。所以后端统一加了CorsFilter配置,允许所有来源和所有HTTP方法,开发阶段先放开,上线时再收紧到指定域名。

3.4 本地联调时逃不开的四个关键点

本地联调是整个项目从"源码躺在硬盘里"到"跑起来能用"的关键一步,实际操作中这四个点避不开。

第一个是后端监听的IP地址。SpringBoot默认监听localhost,小程序开发者工具在电脑上访问没问题,但真机预览时手机访问不到。改成server.address=0.0.0.0,让后端监听所有网卡,真机才能通过局域网IP访问到。

第二个是baseURL的配置。小程序端请求地址不能写localhost,要写电脑的局域网IP,比如http://192.168.1.100:8080。而且这个IP会变,建议做一个配置文件集中管理。

第三个是小程序开发者工具的域名校验。微信小程序上线后必须配置HTTPS合法域名,但本地开发阶段可以勾选"不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书"这个选项,不然本地请求会被拦截,页面一片空白。

第四个是手机和电脑必须处于同一个WiFi网络。真机调试时手机和电脑在同一局域网,手机访问电脑的局域网IP才能通。如果公司或宿舍网络开启了AP隔离,手机和电脑虽然连同一个WiFi但互相访问不了,这时候可以开手机热点给电脑连,再让手机访问电脑的局域网IP。

4. 从零到一:项目搭建与运行调试全流程

4.1 环境准备清单

在跑通这个项目之前,先把环境准备齐了,能省掉后面很多莫名其妙的报错:

工具版本说明用途
JDK1.8或以上运行SpringBoot后端
Maven3.6以上管理后端依赖
MySQL5.7或8.0存储数据
IDEA任意版本开发调试后端
微信开发者工具最新稳定版运行小程序端
HBuilderX最新版编译uni-app项目
Node.js16以上运行Vue管理后台

后端工程导入IDEA后,Maven会自动下载依赖,国内网络环境建议先配置阿里云镜像源,否则依赖下载慢到怀疑人生。

4.2 后端工程启动步骤

后端启动是整个链路的第一环,按这几步走基本不会出问题:

  1. 在MySQL中创建数据库,库名用项目文档里约定的名称,比如farm_db。
  2. 导入项目自带的farm_db.sql脚本,包含建表语句和初始化数据。
  3. 打开application.yml,修改数据库连接的用户名和密码。
  4. 检查appid和secret配置,如果没有正式的微信小程序账号,可以先留空,登录接口走测试模式。
  5. 运行FarmApplication的主类,看到Spring Boot启动成功的日志说明后端已经起来了。

启动过程中常见的报错基本就两类:数据库连接失败(检查用户名密码和库名对不对)和端口被占用(默认8080端口被别的进程占用了,改一下server.port配置即可)。

4.3 小程序端与后台的启动步骤

小程序端的启动分两种情况。如果直接用微信开发者工具导入小程序源码目录,需要确认目录里有project.config.json配置文件,然后工具会识别出这是一个小程序项目。在工具里修改utils/request.js中的baseURL为电脑的局域网IP,编译预览即可。

如果是uni-app工程,先用HBuilderX打开,执行npm install安装依赖,然后运行到微信开发者工具。HBuilderX会自动调用微信开发者工具并打开页面。如果没反应,检查一下工具菜单里有没有配置微信开发者工具的路径,这是常见问题。

管理后台的启动就是纯前端流程:npm install安装依赖,npm run dev启动开发服务,浏览器访问提示的地址。首次启动后会跳转登录页,用后台预置的管理员账号登录即可。

4.4 真机预览与功能走查

真机预览比模拟器能发现更多问题。在微信开发者工具里点预览按钮,会生成一个二维码,用微信扫码就能在真实手机上打开小程序。

真机上面重点检查三个事:图片加载速度、页面滚动流畅度、按钮点击区域。图片一定要压缩,几兆的图片在手机上加载非常慢,商品图统一压缩到几百KB以内。按钮尺寸不能太小,微信小程序默认的可点击区域建议不小于44x44像素。还有就是真机上的baseURL必须可访问,这一点前面已经说过了。

整个项目提供源码和配套文档,但最终还是要自己动手跑一遍,把每一步涉及的代码和业务映射起来,才能有更深的理解。文档里写的数据库设计、接口说明、部署指南配合教程,加上亲手操作,即可达到"看懂、能讲、会改"的状态。

5. 踩坑实录与排查速查

5.1 本地调试时的常见问题

我把实际开发中遇到的典型问题整理成了一个速查表,按问题、原因、解决方式三列来放,排查时可以对照着看:

问题原因解决方式
小程序请求后端超时baseURL写了localhost或127.0.0.1改为电脑局域网IP
登录接口返回401token未传,或拦截器未放行登录接口检查请求头配置,检查拦截器白名单
真机访问不到后端手机与电脑不在同一网络连同一WiFi或用手机热点
管理后台接口跨域报错后端未配置CORS添加CorsFilter或@CrossOrigin
图片上传失败文件上传目录没有创建确保上传目录存在且有写权限
支付回调处理了两次微信或模拟回调重复通知回调接口做幂等处理
数据库中文乱码连接串未指定utf8URL加characterEncoding=utf8
小程序预览白屏域名校验未关闭或debug模式开启关闭域名校验,检查控制台报错

这些坑基本都是实际踩过的,有时候一坐一下午就卡在某一个上面。最典型的就是baseURL的问题,本地模拟器正常,二维码扫出来一片空白,后来发现是手机访问不了电脑的局域网IP。这个排查思路可以记一下:先看小程序开发者工具里的Network面板请求是否发出,再看后端控制台有没有收到请求,定位到是哪一环断了再对症下药。

5.2 部署上线前的检查清单

项目如果要从本地调试状态走向正式部署,有几件事必须提前确认:

服务器环境准备好JDK、MySQL、Nginx,MySQL初始化数据库脚本,后端打jar包丢到服务器,Nginx配置反向代理到8080端口的后端服务,同时把vue打包后的dist目录指给前端静态文件访问,微信小程序端的baseURL改为HTTPS域名并在官方后台配置合法域名。

小程序发布前要走提交审核的流程:功能截图、测试账号、类目选择都准备好,审核周期一般一到七天。这里特别注意,微信的合法域名必须是HTTPS,并且域名不能带端口号,证书要有效。支付要用的商户号如果没有申请,审核时可以用功能性占位,但上线后如果需要真实交易,是绕不开这一步的。

5.3 做这类项目的一些个人体会

老实说,这类全栈项目技术上没有什么"高精尖"的部分,最考验人的是耐心和对业务细节的把控。我接到这套代码后,自己又从零梳理了两遍才完全吃透:第一遍跑通流程,第二遍在关键节点加注释、改掉几处不合理的逻辑。

做农产品交易平台,一定要理解这个行业的特殊之处:商品的非标准化、物流的时效性、买家的信任问题,这些东西驱动了设计上的很多细节。比如商品可以填产地和检测报告,比如订单状态流转中要预留"卖家发货"这个环节而不是买家下单后直接跳到收货,这些都不是技术问题,而是业务理解问题。

最后再分享一个小技巧:如果你准备在这个项目基础上做二次开发,优先做数据统计模块。农产品交易平台如果能按商品销量、地区分布、价格趋势这几个维度做一些可视化统计,无论是提升项目实战感,还是作为管理后台的亮点功能,投入产出比都很高。遇到卡壳的地方,耐心看报错信息、查看运行日志,一步步缩小排查范围,老问题折腾几次就有感觉了。

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

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

立即咨询