简介:这是一套基于Java与uniapp开发的智能小程序商城系统源码,面向具备一定Java与前端基础的开发者、计算机专业学生及需要搭建多角色电商平台的团队。项目涵盖管理员、商家、用户三类角色,后端采用Java搭配MySQL,前端基于uniapp实现小程序端与后台管理界面,可解决商品发布、订单流转、用户权限与图片资源管理等典型商城业务需求。压缩包共1449个文件,约23.86MB,以vue组件、js脚本、svg与png图片、json配置、java后端代码为主,另含wxss、wxml小程序样式与结构文件、sql建库脚本及yml配置文件,目录层次完整,便于按模块阅读与二次开发。资源已有36人学习,适合作为课程设计、毕业设计或中小型电商项目的参考底稿,读者可从中获取多角色权限设计、前后端接口组织、数据库配置与图片上传路径处理等具体实现思路。
1. 一套 Java + uniapp 的小程序商城源码,拿到手先别急着跑
很多做 Java 后端的同学,第一次接触「小程序商城」这类项目,第一反应是打开 IDE 点运行,结果卡在数据库连不上、前端编译报错、登录拿不到 code 这三件事上,一卡就是一下午。这套基于 Java 和 uniapp 的智能小程序商城系统,本质上是「Spring Boot 后端 + uniapp 多端前端 + 微信小程序宿主」的三层结构,后端管商品、订单、用户、支付,前端一套代码同时编译到微信小程序和 App。它适合两类人:一是想拿一套完整电商链路练手的 Java 工程师,二是需要快速搭一个商城 Demo 去验证业务的小团队。这篇不吹架构多先进,只讲怎么把它在本地跑通、参数怎么配、哪些地方最容易翻车,让你少走我当年踩过的弯路。
2. 先看清这套商城系统的分层:Java 后端和 uniapp 前端各自管什么
拿到源码压缩包,别急着解压乱翻。先建立一张「谁负责什么」的脑图,后面所有报错你都能快速定位到是哪一层的问题。这套系统的分层其实很典型,但新手容易把「小程序端」和「uniapp 端」混为一谈,导致改错文件。
2.1 后端 Spring Boot 的职责边界
后端是整个商城的大脑,通常基于 Spring Boot + MyBatis-Plus 这套组合。它对外暴露 REST 接口,小程序端所有数据都通过 HTTP 请求拿。核心模块一般包括:用户模块(微信登录、手机号绑定)、商品模块(分类、SKU、库存)、订单模块(下单、支付回调、退款)、营销模块(优惠券、秒杀)。
MyBatis-Plus 在这里的价值是省掉大量 CRUD 样板代码。很多源码里你会看到实体类上挂着@TableName、@TableId注解,这就是 MyBatis-Plus 的约定。有个热词叫「mybatisplus 根据 java 实体类生成创建表的 sql 语句」,这在调试阶段特别有用——当你怀疑数据库表结构和实体类对不上时,可以用它反推建表语句。
// 实体类示例:商品 SKU @Data @TableName("pms_sku") public class PmsSku { @TableId(type = IdType.AUTO) private Long id; private Long productId; // 关联商品 ID private String skuCode; // SKU 编码,唯一 private BigDecimal price; // 售价 private Integer stock; // 库存 }这段代码的关键在@TableName和@TableId:前者告诉 MyBatis-Plus 这张表叫什么,后者声明主键策略。IdType.AUTO表示用数据库自增,如果你换成ASSIGN_ID就是雪花算法生成。参数上最容易错的是skuCode这种业务唯一键,源码里如果没加唯一索引,并发下单会出现重复 SKU,这是后话。
2.2 uniapp 前端的目录结构和编译目标
uniapp 端是「一套代码,多端编译」。目录里pages放页面,static放静态资源,components放公共组件,manifest.json是全局配置,pages.json管路由和导航栏。热词里「uniapp manifest 配置」和「uniapp 微信小程序打包」是高频问题,因为这两个文件直接决定你能不能编译成功。
manifest.json里要填appid(微信小程序的)、appName、版本号,还要配置各端的特有参数。pages.json里每个页面的navigationBarTitleText就是小程序顶部标题,热词「小程序动态设置标题」说的就是运行时用uni.setNavigationBarTitle改它。
{ "pages": [ { "path": "pages/index/index", "style": { "navigationBarTitleText": "商城首页", "enablePullDownRefresh": true } } ], "globalStyle": { "navigationBarBackgroundColor": "#ffffff", "navigationBarTextStyle": "black" } }enablePullDownRefresh开启下拉刷新,商城首页几乎必开。navigationBarTextStyle只能是black或white,写错编译不报错但真机显示异常,这种玄学问题最耗时间。
2.3 小程序宿主层:微信登录和手机号获取
小程序端最特殊的是登录链路。用户点授权,前端调uni.login拿到临时code,传给后端,后端拿code+appid+secret去微信服务器换openid和session_key。热词「微信小程序登录获取手机号」是另一条链路:前端用button open-type="getPhoneNumber"拿到加密数据,后端解密。
// uniapp 端微信登录 uni.login({ provider: 'weixin', success: (res) => { // res.code 是临时凭证,5 分钟有效 uni.request({ url: 'https://your-api.com/auth/wxLogin', method: 'POST', data: { code: res.code }, success: (r) => { uni.setStorageSync('token', r.data.token); } }); } });res.code只能用一次,且有效期极短,所以后端换openid必须立刻执行。很多源码把appid和secret硬编码在后端配置文件里,你本地跑必须换成自己的测试号,否则登录永远失败。
3. 本地跑通的最小路径:从数据库到小程序预览
这一章是全文最干的部分,按顺序做,别跳步。我一般把「跑通」拆成四步:建库导数据、起后端、配前端、编译预览。每一步都有明确的成功标志,卡住了就对照排查。
3.1 数据库建库与 SQL 导入
源码包里通常有个sql目录,里面是.sql文件。先建库,字符集用utf8mb4,否则商品名里的 emoji 会变问号。
# 登录 MySQL 后执行 CREATE DATABASE mall_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE mall_db; SOURCE /path/to/mall.sql;utf8mb4是关键,utf8在 MySQL 里是残缺的,存不了四字节字符。导入后检查表数量,一般商城系统在 30 到 60 张表之间。如果导入报外键错误,先SET FOREIGN_KEY_CHECKS=0;再导,导完记得改回来。
3.2 后端配置文件的四个必改项
Spring Boot 的配置文件一般是application.yml或application-dev.yml。必改的有四处:数据库连接、Redis 连接、微信 appid/secret、文件上传路径。
spring: datasource: url: jdbc:mysql://127.0.0.1:3306/mall_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password redis: host: 127.0.0.1 port: 6379 database: 0 wx: appid: wx1234567890abcdef secret: your_secret_hereserverTimezone=Asia/Shanghai不加会报时区错误,这是 Java 连 MySQL 8 的经典坑。Redis 如果源码里用来存 token 或购物车,不启动 Redis 后端会启动失败,别以为是代码问题。
3.3 uniapp 端配置与微信开发者工具联调
前端用 HBuilderX 打开,先改manifest.json里的appid,再改请求基地址。请求基地址一般在utils/request.js或config.js里。
// utils/request.js const BASE_URL = 'http://127.0.0.1:8080'; // 本地后端地址 export const request = (options) => { return new Promise((resolve, reject) => { uni.request({ url: BASE_URL + options.url, method: options.method || 'GET', data: options.data || {}, header: { 'Authorization': uni.getStorageSync('token') || '' }, success: (res) => { if (res.data.code === 401) { uni.navigateTo({ url: '/pages/login/login' }); } resolve(res.data); }, fail: reject }); }); };Authorization头带 token 是标准做法,后端拦截器校验。注意本地调试时微信开发者工具要勾选「不校验合法域名」,否则127.0.0.1会被拦。热词「uniapp 微信小程序开发者工具插件」指的就是在 HBuilderX 里配置开发者工具路径,实现一键编译预览。
3.4 编译预览与真机调试的差异
模拟器跑通不代表真机没问题。真机上127.0.0.1指向手机自己,必须换成局域网 IP,比如192.168.1.100:8080,且手机和电脑同一 WiFi。另外真机请求 HTTPS 才稳定,本地 HTTP 调试要在开发者工具里开「调试模式」。
| 环境 | 请求地址 | 域名校验 | 备注 |
|---|---|---|---|
| 模拟器 | 127.0.0.1 | 需关闭 | 最快 |
| 真机预览 | 局域网 IP | 需关闭 | 同 WiFi |
| 体验版 | 公网 HTTPS | 需配置 | 要备案域名 |
这张表建议截图存着,每次换环境对照改,能省大量「为什么模拟器好好的真机不行」的困惑。
4. 商城核心链路的参数与接口:商品、订单、支付怎么串
跑通之后,你要理解业务链路,否则改需求时无从下手。商城最核心的是「浏览商品 → 加购物车 → 下单 → 支付 → 回调改状态」这条线,每一环都有参数陷阱。
4.1 商品列表分页与 SKU 库存扣减
商品列表接口一般带page、size、categoryId、keyword参数。分页用 MyBatis-Plus 的Page对象,注意size别设太大,小程序一次渲染几百条会卡。
库存扣减是电商最经典的并发问题。错误做法是「先查库存再更新」,正确做法是用 SQL 原子更新:
UPDATE pms_sku SET stock = stock - #{num} WHERE id = #{skuId} AND stock >= #{num};AND stock >= #{num}是灵魂,它保证库存不足时更新影响行数为 0,后端据此判断扣减失败。如果源码里写的是先SELECT再UPDATE,高并发下必然超卖,这是血泪经验。
4.2 订单创建的事务边界
下单要同时做几件事:扣库存、生成订单、清购物车、可能还要锁优惠券。这些必须在同一个事务里,否则会出现「库存扣了订单没生成」的脏数据。
@Transactional(rollbackFor = Exception.class) public OrderVO createOrder(Long userId, List<CartItem> items) { // 1. 校验库存并扣减 for (CartItem item : items) { int affected = skuMapper.deductStock(item.getSkuId(), item.getNum()); if (affected == 0) { throw new BizException("库存不足"); } } // 2. 生成订单 Order order = buildOrder(userId, items); orderMapper.insert(order); // 3. 清购物车 cartMapper.deleteByUserId(userId); return convert(order); }rollbackFor = Exception.class必须写,默认只回滚运行时异常,受检异常不回滚。这是 Java 事务的经典坑,很多源码漏写。
4.3 支付回调的幂等处理
支付回调是外部系统调你,可能重复调。必须做幂等:用订单号查状态,已支付就直接返回成功,别再改一次。
public String handlePayCallback(String orderNo, String tradeNo) { Order order = orderMapper.selectByOrderNo(orderNo); if (order == null) return "FAIL"; if (order.getStatus() == OrderStatus.PAID) { return "SUCCESS"; // 幂等:已处理直接返回 } order.setStatus(OrderStatus.PAID); order.setTradeNo(tradeNo); orderMapper.updateById(order); return "SUCCESS"; }回调接口返回的字符串格式由支付平台规定,微信要求返回SUCCESS的 XML 或 JSON,返回错格式会一直重试。
5. 避坑与排查:这套源码最容易翻车的五个地方
下面五条都是我实际调试时踩过的,按「现象 → 原因 → 解决」写,你对号入座。
5.1 小程序编译报 source size 超限
现象:编译报source size 2612kb exceed max limit 2mb。原因是微信小程序主包限制 2MB,源码里图片、字体、大 JSON 都塞主包了。解决:把非首屏资源移到分包,pages.json里配subPackages,图片改走 CDN 或压缩。
5.2 登录一直提示 code 无效
现象:前端拿到 code 传后端,换 openid 报invalid code。原因通常是 code 被用了两次,或者 appid 和 secret 不匹配。解决:确认后端只调一次微信接口,且 appid/secret 是同一小程序的。测试号和小程序正式号的 secret 不通用。
5.3 真机请求全部失败但模拟器正常
现象:模拟器接口通,真机全 404 或超时。原因是请求地址还是127.0.0.1。解决:改成电脑局域网 IP,手机和电脑同网段,防火墙放行 8080 端口。
5.4 订单金额和商品总价对不上
现象:下单金额比商品总价少几分钱。原因是浮点数计算用了double。解决:金额一律用BigDecimal,且数据库字段用decimal(10,2),别用float。
5.5 uniapp 打包 App 后定位/后台功能失效
现象:小程序正常,打包成 App 后定位不工作。原因是 App 端权限要在manifest.json里单独声明,且热词里提到的plus.geolocation.watchPosition这类 API 只在 App 端有效。解决:在 manifest 的 App 模块配置里勾选定位权限,代码里用条件编译#ifdef APP-PLUS区分。
6. 把这套源码用出价值:二次开发与上架前的三个技巧
跑通只是起点,真正有价值的是改造成你自己的东西。分享三个我常用的技巧。
第一个是接口 mock 提速。后端没写完时,前端可以在request.js里加一层开关,命中 mock 直接返回假数据,前后端并行开发。第二个是数据库索引自查,商城系统慢查询八成出在order、product表,给user_id、order_no、category_id加索引,用EXPLAIN看执行计划。第三个是上架前的合规检查,热词里「uniapp 上架安卓应用市场」提到的隐私政策、权限说明必须补齐,小程序端则要确认getPhoneNumber等敏感接口已在微信后台申请权限。
// 条件编译示例:只在 App 端执行 // #ifdef APP-PLUS plus.geolocation.getCurrentPosition((pos) => { console.log('定位成功', pos.coords); }, (err) => { console.error('定位失败', err); }); // #endif条件编译是 uniapp 多端的核心技巧,#ifdef和#endif之间的代码只在指定平台编译。善用它,一套代码能干净地适配小程序和 App,而不是到处写if判断。
最后说个习惯:我每次拿到新源码,第一件事不是跑,而是花二十分钟把pom.xml、manifest.json、application.yml这三个文件通读一遍,把版本号、依赖、配置项列出来。这一步能提前发现 80% 的环境问题,比出错了再回头翻高效得多。这套 Java + uniapp 商城源码值得投入,但前提是你先把它跑起来、再谈改造。希望帮到你。
本文还有配套的精品资源,点击获取