ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Spring Boot+Vue+Redis商城项目从环境搭建到联调排错实战

Spring Boot+Vue+Redis商城项目从环境搭建到联调排错实战 简介基于SpringBootVueRedis的前后端分离网上商城项目源码包面向毕业设计、课程作业及Java Web学习者尤其适合计算机科学与技术、人工智能等相关专业快速搭建可演示的电商系统。项目已调试通过包含完整前后端代码与SQL数据库脚本覆盖商品展示、购物车、订单处理、用户管理等核心模块可走通从登录到下单的完整业务闭环。压缩包共2034个文件其中md文档1358个含README等说明js前端业务代码562个json项目配置69个另含docx配套文档、txt、html及shell脚本整体约117.18MB目录层次清晰便于按模块学习。已有124人学习下载。通过该项目可深入理解前后端分离架构下的接口调用方式以及SpringBoot结合Redis实现缓存加速、提升系统响应速度的具体做法。资源仅供学习交流请勿用于商业用途使用前可先查看README或相关文档遇到问题可通过私信与博主沟通。1. 拿到“已调试”的商城项目先别急着解压缺的不是代码是环境与流程我每隔一段时间就会收到类似的问题论坛或网盘下载的 springbootvueredis 前后端分离网上商城项目标着“已调试”附源码和一份 sql 文件但到自己电脑上双击就是起不来。问题往往不是代码本身而是缺了对应的环境、版本和启动顺序。这套商城的角色分配其实很典型Spring Boot 管接口Vue 管页面Redis 管登录态和缓存MySQL 管商品与订单sql 文件则是把别人数据库搬到你本地的唯一线索。拆开它并跑通它适合两类人——拿它做毕设或练手的新手以及想快速二次开发出一个简易商城的一线开发。这篇笔记会把解压、建库、启动前后端、联调和排错串成一条能照做的路线。2. 拆开源码和 SQL先想清楚 Spring Boot、Vue、Redis 各管哪一块2.1 解压后先看这三样pom.xml、application.yml、db 脚本如果你下载到的压缩包带目录结构我一般会先用tree -L 2扫一眼重点不是读完整代码而是确认三个文件在不在后端pom.xml、后端application.yml、根目录或db目录下的.sql脚本。unzip 网上商城项目003.zip cd 网上商城项目003 tree -L 2打开pom.xml的目的有两个看 Spring Boot 的父版本看是不是 2.x 还是 3.x看有没有引入spring-boot-starter-data-redis、mybatis-plus、lombok。Spring Boot 2.x 默认用的 lettuce 连接 Redis3.x 在 Jakarta 依赖上有一批兼容差异这决定了你本机 JDK 和 Redis 版本该怎么配。application.yml里最要紧的是端口、MySQL 连接串和 Redis 的 host/port/password这三项不对后面所有报错都会是灾难现场。sql 脚本则决定了你要准备哪个版本的 MySQL。脚本第一行如果是CREATE DATABASE mall后面跟一堆DROP TABLE IF EXISTS和INSERT INTO那基本就是 MySQL 5.7 的写法如果见到utf8mb4、ENGINEInnoDB就不用犹豫版本问题。另一种常见情况是压缩包里没有建库语句只有表结构和数据那你就得自己先建库再指定库名导入。所以拿到包的第一步永远是确认这三个文件的内容而不是双击 IDEA 跑起来再猜。2.2 把 SQL 灌进 MySQL导入命令与建库约定导入 SQL 是最容易被新手随手糊弄过去的一步。最常见做法是打开 Navicat 直接运行脚本但如果你这台机器上装的是纯命令行客户端或者脚本体积较大我建议用source方式导入错误信息更直观。mysql -u root -p # 登录后先看脚本开头有没有 CREATE DATABASE 语句 show databases; source /path/to/网上商城003.sql; show tables;这里的重点不是执行source这个动作而是执行前先确认脚本开头有没有CREATE DATABASE和USE。很多下载的 sql 文件开头不带建库语句只有CREATE TABLE你直接 source 会把表建进当前默认库后端配置里却写着另一个库名启动时就会出现Table mall.t_user doesnt exist。另外Windows 下source的路径不要带中文MySQL 客户端对中文路径的处理在不同版本里行为不一致翻车概率极高。导入完成后顺手跑一条show tables;看表清单是否完整。典型的商城项目表至少有用户表、商品表、购物车表、订单表、订单明细表这几类。如果发现表里数据量是 0说明这个 sql 脚本可能只含表结构不含初始化商品数据后面前端页面打开会是空列表这不算启动失败但会影响你判断“是否跑通了”。遇到这种情况自己往商品表里插两三行测试数据即可。2.3 先别碰代码把 Redis 准备好版本选择与连通性自测Redis 在这个项目里不是可有可无的装饰品。网上商城这类前后端分离项目登录 token、验证码、购物车临时数据、商品详情缓存通常都压在 Redis 上。如果你跳过后端直接启动Spring Boot 会在启动时尝试创建 Redis 连接工厂连不上轻则日志刷异常重则启动失败具体表现取决于代码里有没有配置懒加载。Windows 下装 Redis 有两个方向一是用 Docker 跑官方镜像二是下载 Redis for Windows 的老版本。老版本在 5.0 之后就不怎么更新了本地开发够用但你要留意它的redis.windows.conf里默认bind 127.0.0.1如果后端部署在 Docker 或远程机器上必须改配置。macOS 用户直接用 Homebrew 最省事brew install redis redis-server另一个终端里执行redis-cli ping返回PONG就说明 Redis 是活的。用 Docker 的方式也常见docker run -d --name redis -p 6379:6379 redis:7启动后不要急着去启动后端先用redis-cli -h 127.0.0.1 -p 6379手工连一次确认端口通、没有密码保护。如果 Redis 设了密码后端application.yml里的spring.redis.password必须同步这里最容易出现的低级错误是本地 Redis 没设密码配置里却写了一串password: 123456Spring Boot 的 lettuce 客户端会直接抛ERR Client sent AUTH, but no password is set。另外多项目共用一台 Redis 时把database配置项从 0 改到 1 或 2能避免商城缓存和别的项目 key 撞车。3. 让 Spring Boot 先跑起来三个配置点与启动日志的读法3.1 三个关键配置MySQL 连接、Redis 连接、服务端口打开后端的application.yml你会发现配置多到让人眼花但真正影响启动成败的只有三块数据源、Redis、服务端口。其他配置项比如mybatis-plus的日志级别、JWT 密钥、文件上传路径启动阶段不报错可以放到后面再调。server: port: 8080 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/mall?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver redis: host: 127.0.0.1 port: 6379 password: database: 0先看 MySQL 连接串。serverTimezoneAsia/Shanghai这一项不能省MySQL 8.x 默认时区与 JDBC 驱动不一致时会直接报The server time zone value йʱ is unrecognized。characterEncodingutf8负责解决中文乱码但前提是数据库本身字符集也是 utf8mb4。再看 Redis四个子项里password最容易写错本地没设密码就留空不要填什么root或123456。database指的是 Redis 的 0~15 号逻辑库商城项目一般用 0但如果你这台机器上 Redis 里已经有别的业务数据最好换个库号隔离。端口方面后端server.port我习惯固定 8080前端开发服务器则放到 8081这样两边互不干扰。很多“已调试”项目下载后被抱怨跑不起来原因不是代码坏了而是下载的人同时启动了另一个占着 8080 的服务。改端口不是不能做但改了端口就必须同步改前端代理等于多引入一个变量。确认配置无误后两种启动方式任选。IDEA 里直接运行Application.java最快但前提是本机 Maven 配置没问题命令行方式更适合复现和排错mvn clean package -DskipTests java -jar target/shop-backend-0.0.1-SNAPSHOT.jar这里有个细节-DskipTests是跳过测试用例编译后的运行不是跳过编译。如果项目里有几个测试类依赖数据库连接不跳过它们会在mvn package阶段卡很久。第一次打包时 Maven 要下载一堆依赖网络差的时候特别容易给人一种“项目坏了”的错觉其实只是没下完。3.2 从启动日志判断是否健康哪些输出意味着可以联调Spring Boot 启动过程会打出一大坨日志新手容易在里面迷路。我一般只看三个信号Tomcat 端口起来没有、Redis 有没有连上、Mapper 有没有加载报错。用java -jar启动后日志里如果出现类似下面的内容说明后端主服务已经站起来Tomcat started on port(s): 8080 (http) Started ShopApplication in 12.34 seconds第一行表示 Web 容器就绪第二行表示整个应用上下文刷新成功。如果日志停在那里不动或者抛APPLICATION FAILED TO START就要往上翻异常栈。Sping Boot 的异常栈很长最容易定位的是最底部那几行Caused by那才是真正的根因不要盯着最上面的Description:反复看。Redis 连接是否成功日志里不一定每次都有显眼提示。spring-boot-starter-data-redis 在启动阶段默认不会主动 ping Redis只有在首次访问 Redis 时才建立连接这就导致一种很隐蔽的情况后端启动成功了但登录时接口直接报 500。所以启动后我建议立刻用 curl 或浏览器探一下登录接口而不是只看启动日志curl -X POST http://localhost:8080/api/user/login \ -H Content-Type: application/json \ -d {username:admin,password:admin123}如果返回 JSON 里有 token 或用户信息说明 Spring Boot 的核心链路、MySQL 和 Redis 都已经通了如果返回 500 且日志里有Unable to connect to Redis那就回头检查 2.3 节里的 Redis 连通性。顺便提一句如果项目里集成了 Swagger 或 Knife4j启动后直接访问/swagger-ui/index.html也能快速验证接口文档是否加载但不代表数据层一定健康。3.3 启动后端时最先遇到的三个报错从异常栈反查配置第一个高频报错是端口被占用。日志里会出现Port 8080 was already in use或Web server failed to start。解决方式不是改 Spring Boot 端口而是找到占用 8080 的进程并处理。Windows 上用netstat -ano | findstr 8080看进程号再进任务管理器结束macOS 上用lsof -i :8080。改端口是最后的选项因为前端代理、CORS 允许来源可能都跟着 8080 写死了。第二个高频报错是 MySQL 连接失败。Cannot create PoolableConnectionException这类异常背后原因通常是三种MySQL 服务没起、用户名密码不对、连接串里的库名不存在。逐个排查先mysql -u root -p手动登一下数据库再show databases;看库在不在。如果手动能连、程序连不上检查driver-class-nameSpring Boot 2.7 之后必须用com.mysql.cj.jdbc.Driver旧写法com.mysql.jdbc.Driver在某些版本下会直接被拒。第三个高频报错是缓存连接异常日志里出现Unable to connect to Redis或Connection refused: /127.0.0.1:6379。这基本就是 Redis 没启动或启动后绑定的端口不对。先用redis-cli ping验证再排查后端配置的 host 和 port。还有一种不常见但这几年越来越多的场景本机装了 Docker Redis 映射了端口但容器没启动docker ps一看全是空的。我的习惯是把检查 MySQL 端口和 Redis 端口写成一个两行的 shell 脚本启动项目前先跑一遍省下大量翻日志的时间。4. 把 Vue 前端跑起来npm、代理与登录态4.1 npm 安装与 Node 版本为什么先卡在这一步后端启动成功不代表你就能看见页面。前端项目通常是frontend或web目录进去第一件事是npm install。这一步是前后端分离项目里最常见的翻车点因为依赖安装的成败高度依赖 Node 版本与依赖包的兼容关系。cd frontend npm install --registryhttps://registry.npmmirror.com npm run dev如果你是拿 Vue2 的老项目package.json里很可能是node-sassNode 16 以下还好说Node 18 以上配合 node-sass 大概率在编译原生模块时报node-gyp错误。这不是你操作的问题是 node-sass 官方对高版本 Node 支持滞后造成的。我一般处理方式是先看package.json里node-sass的版本号去查它对应的 Node 兼容表不想折腾就直接把依赖换成dart-sass但dart-sass在个别写法上有差异比如/deep/选择器不支持。换 Node 版本更省事Windows 上装 nvm-windowsmacOS 用 nvm切到 Node 14 或 16 再npm install多数老项目能一次通过。npm run dev起来之后控制台会打印类似App running at: http://localhost:8081的地址。这里的端口不是你自己定的而是vue.config.js里的devServer.port决定的。如果你打开前端页面后是白屏或者一直转圈先看命令行有没有报编译错误再看浏览器开发者工具的 Console 和 Network。4.2 vue.config.js 里的代理把 /api 转发给 Spring Boot前后端分离的开发模式里前端页面跑在 8081后端接口跑在 8080浏览器直接访问 8081 时如果页面里的请求地址写的是http://localhost:8080/api/...就会出现跨域问题。开发环境最干净的解决方式是走 Webpack Dev Server 的代理而不是在后端写一堆CrossOrigin。// vue.config.js module.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, // spring boot 后端地址 changeOrigin: true, pathRewrite: { ^/api: /api } } } } };这里的pathRewrite是坑最多的地方。如果后端项目的application.yml里有server.servlet.context-path: /api那前端代理就不能把/api去掉pathRewrite写{ ^/api: }反而会导致请求打到后端时路径变成根路径直接 404。反过来如果后端没有 context-path接口本来就带/api前缀那 rewrite 写不写都无所谓。判断依据很简单打开浏览器 F12看请求的实际路径再对照后端的 controller 映射。改完vue.config.js后必须重启npm run dev因为代理配置不会热更新。很多人在改完配置后发现请求还是 404其实不是代码问题而是 dev server 还跑着旧配置。这个细节我在不同项目里踩了至少三次现在改完代理一定会看一眼控制台有没有重新编译的输出。4.3 登录态与 Redistoken 是前后端之间的船前后端分离项目登录的核心链路是这样的用户在登录页输入账号密码前端通过 axios POST 到/api/user/loginSpring Boot 从 MySQL 用户表校验账号密码校验通过后生成一个 token把 token 写入 Redis同时把用户信息返回给前端。前端拿到 token 后存进localStorage之后每一次请求都带上Authorization请求头后端在拦截器里查 Rediskey 存在且未过期就放行。Redis 在这个流程里的作用不是一个可有可无的缓存而是登录态的“状态存储”。因为前后端分离、服务端不存 sessiontoken 只有放进 Redis 才能实现“主动过期”和“强制下线”。商城项目里常见的 key 设计是login:token:{uuid}value 是用户 IDTTL 设两小时。每次请求时后端用 token 查 Redis 拿到用户 ID再决定是不是允许访问订单、购物车这些接口。// 伪代码Spring Boot 拦截器里校验 token String token request.getHeader(Authorization); String userId redisTemplate.opsForValue().get(login:token: token); if (userId null) { response.setStatus(401); return false; }如果 Redis 里没有这个 key说明用户没登录或者 token 已过期返回 401 让前端跳回登录页。这里有个很容易踩的坑前端 vue-router 的路由守卫里会判断本地有没有 token有 token 就放行但本地 token 存在不代表 Redis 里还存在因为可能被管理员踢掉或 TTL 到了。所以前端的登录判断不能只看本地必须在请求真正失败时再跳转登录页。联调时你可以在 Redis Desktop Manager 里实时看到login:token:开头的 key 在登录后出现、过期后消失这种感觉比对着黑匣子猜要踏实得多。5. 网上商城联调避坑实录前端 404、Redis 拒连、编码乱码怎么查5.1 现象后端起来了前端所有接口 404后端明明已经打印出Tomcat started on port(s): 8080前端页面也能打开但登录、商品列表、购物车全部接口返回 404。这种问题十有八九出在代理配置上。原因一是vue.config.js的proxy没生效常见于修改配置后没有重启npm run dev原因二是pathRewrite的改写规则不对例如后端接口路径是/api/user/login代理把/api前缀削掉变成了/user/login而后端实际的 controller 映射是/api/user/login匹配不上就是 404。解决方式是先看浏览器 Network 里请求的完整 URL。如果 URL 是http://localhost:8081/api/user/login说明前端发出的路径没错问题在代理层如果 URL 是http://localhost:8080/api/user/login且报 404那就是代理没生效或目标端口不对。建议在代理配置里临时加一条logLevel: debug重启 dev server看终端输出的转发日志能直接看到请求被转发到了哪个地址。5.2 现象Redis 连接被拒登录接口报 500后端启动正常但点击登录按钮后接口返回 500后端日志里出现Unable to connect to Redis或Connection refused: connect。原因通常是三种Redis 服务根本没启动Redis 启动后bind或端口和 Spring Boot 配置对不上Redis 设置了密码但application.yml里没写或写错。还有一种情况是 Windows 下装了两个 Redis 实例一个占用 6379一个占用 6380后端配置连的是 6379但这个 6379 的实例已经崩溃退出你以为 Redis 在跑实际netstat -ano | findstr 6379什么都查不到。解决方式按顺序排查先redis-cli ping看 Redis 是否存活并返回 PONG再确认后端配置里的 host/port/password 与 Redis 实际运行参数一致最后用 Redis Desktop Manager 或redis-cli -p 端口连接一次排除是 Redis 服务本身不可用还是 Spring Boot 配置问题。相信我这一步五分钟能定位不要直接去翻后端源码。5.3 现象MySQL 中文乱码、时区报错导入 SQL 后前端页面正常显示但商品名称或订单地址全是问号或者后端启动时直接报时区错误。乱码的原因通常是三层中的某一层出了问题数据库或表字符集不是 utf8mb4连接串里没有characterEncodingutf8或者 SQL 文件本身是 GBK 编码但 MySQL 客户端按 UTF-8 解析导入。时区报错则是连接串里缺serverTimezone或者serverTimezoneUTC导致查询出来的时间差八小时。解决时先查数据库字符集show create database mall;和show create table t_goods;看有没有DEFAULT CHARACTER SET utf8mb4。没有就重建库建库语句写成这样CREATE DATABASE mall DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;连接串里characterEncodingutf8和serverTimezoneAsia/Shanghai两个参数必须同时在。如果 SQL 文件导入时就已经乱码删库重新导入导入前用编辑器把文件转成 UTF-8 编码。顺带提一句SQL 文件里如果带中文注释在旧版 MySQL 客户端下有时会把注释误当成 SQL 执行导入前把大的注释块删掉更省心。5.4 现象npm install 卡在 node-gyp / node-sass 编译前端目录执行npm install时长时间停在node-gyp rebuild或下载 node-sass 源码最后报一堆编译错误。原因是 Node 版本和 node-sass 版本不兼容。node-sass 依赖 libsass 原生库Node 大版本升级后没有对应的预编译二进制npm 只能现场编译而编译又依赖 Python 和 C 工具链环境一复杂就失败。解决方式不唯一最直接的是用 nvm 切换 Node 版本老商城项目配合 Node 14/16 最稳不想切版本就把package.json里的node-sass替换成sassdart-sass然后npm install。替换后注意deep选择器写法要改成:deep()。另外node_modules已经装了一半导致后续反复失败时先删掉node_modules和package-lock.json再重装不然残留的依赖会一直干扰。5.5 现象前端和后端同时抢 8080 端口前端npm run dev启动时报Port 8080 is already in use或者后端启动时端口被占。这是因为这个类别的项目里后端默认 8080前端 dev server 默认也可能是 8080两个一起跑必然冲突。解决方式是给前端指定一个不同的端口我一般把vue.config.js的devServer.port设为 8081后端保持在 8080。改完前端端口后登录页或请求地址如果用了硬编码如http://localhost:8080/api也要同步检查。另一种常见情况是 IDEA 里上次运行的后端进程没有完全退出进程还挂在 8080 上特别是用java -jar启动后关掉终端但进程没杀掉。Windows 下netstat -ano | findstr 8080拿到 PID 后直接taskkill /PID xxx /FmacOS 下lsof -ti:8080 | xargs kill -9。这类问题不算项目缺陷属于开发环境自找的坑但确实有大量新手栽在这里。6. 从跑通到改得动把 Redis 用进下单防超卖再验证一条完整链路6.1 用 Redis 做分布式锁把商城从“演示”变成“能用”的第一改跑通整套商城之后如果你想把它当成一个有说服力的项目只展示登录和商品列表是不够的一定要动一动订单和库存。这里面最值得加的改造是下单时的防超卖也就是用 Redis 的setIfAbsent实现分布式锁避免多个请求同时扣减库存时把库存扣成负数。// 下单防超卖的第一版Redis SETNX 分布式锁 String lockKey order:lock: userId : goodsId; Boolean locked redisTemplate.opsForValue() .setIfAbsent(lockKey, 1, Duration.ofSeconds(10)); if (Boolean.TRUE.equals(locked)) { try { // 校验并扣减库存 Integer stock goodsMapper.selectStock(goodsId); if (stock ! null stock 0) { goodsMapper.decreaseStock(goodsId); orderMapper.insert(order); } } finally { // 释放自己持有的锁 redisTemplate.delete(lockKey); } }setIfAbsent就是 Redis 的 SETNX当 key 不存在时写入成功并返回 true相当于拿到了锁写入失败说明别人正在处理这个用户对同一商品的订单。10 秒过期时间是为了防止拿到锁后程序崩溃锁永远不释放形成死锁。这段代码的价值在于把 Redis 从“存 token”升级为“解决并发问题”你已经触及了 redis 分布式锁在实际业务里的用法。想更严谨的话删锁前要判断 value 是不是自己写入的避免锁过期后误删他人锁但这版足够推翻“我只是照着教程敲”的印象。6.2 验证整套方案是否健壮一条下单链路带动前后端和缓存项目改完之后不要只看页面能点要验证一条完整链路的数据变化。我的习惯是打开浏览器开发者工具和 Redis Desktop Manager两边同时盯着操作每一步都有明确预期。步骤操作预期结果登录前端输入账号密码接口返回 tokenRedis 里出现login:token:xxxkey浏览商品打开商品列表页接口返回商品 JSONRedis 中可能出现商品缓存 key添加购物车点击加入购物车购物车接口正常Redis 里有购物车相关 key下单扣库存提交订单库存减一订单表新增记录锁 key 出现后立即消失重启后端停止并重新启动 Spring Boot已登录状态保持Redis 登录态未被清掉下单完之后再用压测工具或脚本并发请求同一个商品的购买接口观察库存扣减是否不超过初始值。如果发现超卖回到 6.1 的代码检查锁的作用域和过期时间设置。我要说的是这类前后端分离商城项目练手价值就在这一条长链路上——从前端路由守卫到 Spring Boot 拦截器从 MySQL 事务到 Redis 缓存治理能把这些串清楚比刷十个 CRUD demo 更接近真实开发。最后说一句我的习惯。以前拿到这种“已调试”项目我第一动作是直接启动结果被端口、编码、Redis 版本这些环境问题折腾到深夜。现在我会先花五分钟把 MySQL、Redis、端口、Node 版本逐个确认再启动后端、再启动前端。这个顺序让我少踩了太多坑希望帮到你。本文还有配套的精品资源点击获取
返回列表