新闻详情

新闻详情

首页 / 资讯中心 / 详情

SpringBoot+Vue+MySQL全栈实战:雪具销售系统搭建与二次开发指南

发布时间:2026/9/30 15:45:13来源:尧图网络
SpringBoot+Vue+MySQL全栈实战:雪具销售系统搭建与二次开发指南
1. 为什么选雪具销售系统做全栈练手项目这套源码我拿到的第一反应是总算碰到一个不是图书管理或学生管理的课设模板了。雪具销售系统听起来窄但它恰好覆盖了信息管理系统里最典型的一整条业务线——商品有分类和规格、库存有变动、订单有状态流转、用户有角色和登录态而这些恰恰是企业里做管理系统时最高频的需求组合。1.1 业务场景并不小众反而特别适合展示完整逻辑雪具销售不是只卖一件雪板那么简单它通常包含单板、双板、固定器、雪鞋、护具、雪镜等多个品类每个品类规格差异很大价格跨度也宽甚至很多门店还会同时做租赁业务。这就意味着一个像样的系统至少要管住三件事商品信息怎么维护、库存变动怎么记录、订单流程怎么走通。这套源码解决的正是这三个核心问题。后端由 SpringBoot 提供接口前端由 Vue 渲染页面数据统一落在 MySQL 里。拿它做课程设计或者个人项目时答辩能讲的东西非常多商品模块可以讲分页搜索、分类关联订单模块可以讲主表和明细表的事务关系用户模块可以讲登录鉴权和角色权限。几乎把框架、数据库、前端交互该有的点都覆盖到了。1.2 三层技术栈的核心分工三端配合的流程并不复杂我用一句话概括MySQL 负责存SpringBoot 负责算Vue 负责展示和交互。具体到一次请求比如用户在前端点了一页商品列表Vue 发出 HTTP 请求SpringBoot 接收到之后从 MySQL 查出数据再封装成 JSON 返回给前端渲染成表格。层次技术职责关键产物前端Vue 2/3 Element UI页面渲染、路由跳转、表单交互views 页面组件、router 路由表、axios 接口封装后端SpringBoot MyBatis-Plus鉴权、业务逻辑、数据聚合Controller、Service、Mapper、实体类数据库MySQL 5.7/8.0持久化存储、事务保障建表 SQL、初始化数据脚本如果你手头正好在纠结选什么技术栈做管理系统这套组合是目前市面上资料最多、遇到问题最好搜到答案的方案没有之一。1.3 什么人群最适合拿来直接用在校学生需要课程设计或毕业设计但不想从零搭建前后端分离工程想直接拿到能跑的通的项目再改业务。刚转行的前端同学想了解 Vue 和 SpringBoot 是怎么协作的需要一个真实接口联调场景。后端想补前端知识的同学这套系统中的 Vue 部分足够简单清晰适合拆开看 router 和 axios。这套项目的打开方式不是让你照着抄代码而是先把它完整跑起来再按自己的需求做二次开发。把骨架跑通这件事本身就是很多人跨不过去的一道坎。2. SpringBoot 后端骨架依赖选型与接口设计逻辑后端部分的核心价值不在于代码量多大而在于分层方式清晰。我拆开讲几个关键点拿到源码后你重点看的位置也就这几个。2.1 依赖组合怎么选才不踩版本坑一个能直接运行的 SpringBoot 工程pom.xml 里的依赖不会太多但每一个都得选得恰到好处。这套系统常见依赖组合大概是dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies其中最容易出问题的是 SpringBoot 版本和 MySQL 驱动版本的匹配。我建议优先使用 SpringBoot 2.7.x 系列配合 MySQL 8.0 驱动com.mysql.cj.jdbc.Driver这是目前兼容性很稳的组合。如果你拿到源码发现是 SpringBoot 3.x就要注意 JDK 版本必须 17 以上且原来的javax.*包名要换成jakarta.*很多新手在这里直接被编译错误劝退。2.2 为什么是 MyBatis-Plus 而不是 JPA放在三年前我会推荐 JPA 试水但现在的信息管理系统MyBatis-Plus 几乎是更稳妥的选择。它的优势很实在单表 CRUD 不需要写 XMLBaseMapper里已经内置了selectById、selectPage、insert、updateById这类方法多表查询可以继续写 SQL可控性比 JPA 好很多。比如商品分页接口代码基本是这样的逻辑Service public class ProductService { Resource private ProductMapper productMapper; public PageResultProduct pageProducts(int page, int size, String keyword, Long categoryId) { PageProduct pageParam new Page(page, size); LambdaQueryWrapperProduct wrapper new LambdaQueryWrapper(); wrapper.like(StringUtils.hasText(keyword), Product::getName, keyword) .eq(categoryId ! null, Product::getCategoryId, categoryId) .orderByDesc(Product::getCreateTime); PageProduct result productMapper.selectPage(pageParam, wrapper); return PageResult.of(result.getRecords(), result.getTotal()); } }这里有几个设计意图值得注意分页参数统一下发到Page查询条件用LambdaQueryWrapper构造而不是拼字符串 SQL排序字段固定成创建时间倒序。这套写法是现在后端项目里的主流风格你照着这个习惯写后续功能基本不会跑偏。2.3 统一返回体与异常处理的设计价值看后端源码时先找一个叫Result或R的类它通常长这样public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.code 200; result.message success; result.data data; return result; } public static T ResultT fail(String message) { ResultT result new Result(); result.code 500; result.message message; return result; } }所有 Controller 的接口都返回这个Result对象前端拦截器也好、页面判断也好都只需要看code是否为 200。这样做最大的收益是接口风格统一前端不需要每个接口单独处理异常格式。再配合一个RestControllerAdvice全局异常处理器把参数校验异常、业务异常统一兜住接口层就会非常清爽。2.4 登录鉴权的实现思路雪具销售系统既然分用户和管理员登录鉴权就一定存在。常见的做法是登录成功后返回一个 token前端保存在 localStorage后续每次请求在请求头携带token字段。后端用一个拦截器统一校验核心逻辑大致是public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); if (token null || !TokenUtil.verify(token)) { response.setStatus(401); return false; } return true; } }这种拦截器方案比给每个接口重复写校验代码要优雅得多。再配合角色字段区分管理员和普通用户就能做到商品管理接口必须管理员才能访问普通用户只能访问浏览和下单接口。如果你拿到的源码用的是 JWT核心机制一样只是 token 的生成和解析用了io.jsonwebtoken库。3. Vue 前端结构路由、页面组件与接口请求的串联方式前端部分对后端同学来说往往是最陌生的。我拆解这套系统时看到目录结构的感受是它没有滥用状态管理也没有过度设计组件而是用最直接的方式把后台管理页面的套路完整呈现了一遍。3.1 前端工程是怎么初始化出来的当前 Vue 项目主流有两种形态Vue 2 Element UI Vue CLI以及 Vue 3 Element Plus Vite。这套源码如果是早些时候的课设大概率是前者。两者的核心区别在于创建命令不同# Vue 2 经典方式 npm install -g vue/cli vue create ski-sales-front # Vue 3 更快的 Vite 方式 npm create vitelatest ski-sales-front -- --template vue拿到源码后不要纠结是 Vue 2 还是 Vue 3先看package.json里依赖版本再动手。vue-router是 3.x 就是 Vue 2是 4.x 就是 Vue 3。这个判断方法比看任何文档都直接。3.2 页面目录与路由设计前端src下的结构通常是这样的src ├── api # 接口请求封装 │ ├── product.js │ ├── order.js │ └── user.js ├── router │ └── index.js # 路由表 ├── views │ ├── Login.vue │ ├── product │ │ ├── ProductList.vue │ │ └── ProductEdit.vue │ └── order │ └── OrderList.vue ├── utils │ └── request.js # axios 实例 └── App.vue路由表里会看到类似下面的配置它定义了一个带侧边栏布局的父路由子页面都是懒加载方式引入const routes [ { path: /layout, component: () import(/layout/Layout.vue), children: [ { path: product, component: () import(/views/product/ProductList.vue) }, { path: order, component: () import(/views/order/OrderList.vue) } ] }, { path: /login, component: () import(/views/Login.vue) } ]建议你自己动手画一下路由跳转关系图登录页是入口登录成功后跳转到布局页布局页左侧菜单绑定了商品管理、订单管理、用户管理等子页面。把这个关系理清楚后续加页面就往children里加一项而已。3.3 axios 封装为什么必须统一处理请求和响应在一个前后端分离项目里axios 不能直接裸用。这套系统的request.js做了两件关键事情请求拦截时把 token 加到请求头响应拦截时统一解包Result并处理 401 和业务错误。import axios from axios const request axios.create({ baseURL: process.env.VUE_APP_BASE_URL || http://localhost:8080, timeout: 10000 }) request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization token } return config }) request.interceptors.response.use( response response.data, error { if (error.response error.response.status 401) { location.href /login } return Promise.reject(error) } ) export default request这种封装最大的好处是业务页面里不用关心 token 是哪里来的也不用每次判断 HTTP 状态码。写一个接口调用就只管一行export function getProductPage(params) { return request.get(/api/product/page, { params }) }3.4 表格页和编辑弹窗的复用套路后台管理系统写得多了就会发现90% 的页面都是同一个套路顶部一个搜索栏中间一个表格右侧一个新增/编辑按钮打开一个弹窗表单。雪具销售系统的商品页也是如此代码上你重点看el-table里的prop怎么和实体字段对应el-form里表单校验规则怎么写el-form :modelform :rulesrules refformRef label-width100px el-form-item label商品名称 propname el-input v-modelform.name placeholder请输入商品名称 / /el-form-item el-form-item label分类 propcategoryId el-select v-modelform.categoryId placeholder请选择分类 el-option v-foritem in categoryList :keyitem.id :labelitem.name :valueitem.id / /el-select /el-form-item el-form-item label售价 propprice el-input-number v-modelform.price :min0 :precision2 / /el-form-item /el-form看到这个套路之后你可以像填空一样扩展新页面先建一个views/xxx/List.vue复制表格页再改接口路径和字段名基本能应付大多数管理页面的开发。4. MySQL 数据表设计从建表脚本看业务关系数据库脚本是这套源码里最容易被忽略却最值得细看的部分。很多人拿到项目第一件事就是source执行 SQL执行完能跑就完事了但表结构为什么这么设计才是课程设计答辩时老师爱问的问题。4.1 核心表结构与业务关联雪具销售系统的表通常不会少于六张我把常见的表列出来表名用途核心字段user用户表id、username、password、role、phonecategory商品分类表id、name、sortproduct雪具商品表id、category_id、name、price、stock、image、statusorder订单主表id、order_no、user_id、total_price、status、create_timeorder_item订单明细表id、order_id、product_id、quantity、pricestock_log库存变动日志id、product_id、change_count、type、create_time订单主表和订单明细表拆分是典型的一主多明细设计目的是让一次订单能包含多件雪具同时在主表存总价、明细表存每件数量方便统计和分析。库存日志表属于加分项它让库存每次变动都有据可查面试时能多聊好几句话。4.2 字段类型选择里藏着哪些讲究关于字段设计我从这套项目里总结出几个容易踩坑的点金额字段不要用float或double必须用decimal(10,2)否则浮点误差会在累计金额时露馅。库存字段用int就够了但建议加一个unsigned约束防止负库存的脏数据。状态字段用tinyint而不是char比如商品状态 0 下架、1 上架订单状态 0 待支付、1 已支付、2 已发货、3 已完成后端用常量类统一管理。时间字段建议datetime而不是timestamp避免 2038 年问题也方便直接展示。建表脚本里还有个容易忽略的地方是字符集。我建议显式写成CREATE TABLE product ( id bigint NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL, price decimal(10,2) NOT NULL, stock int unsigned NOT NULL DEFAULT 0, category_id bigint NOT NULL, status tinyint NOT NULL DEFAULT 1, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_category (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT雪具商品表;utf8mb4是必须的不然商品描述里出现生僻字或者 emoji 时直接报错。ON UPDATE CURRENT_TIMESTAMP能省掉在代码里手动维护update_time的功夫。4.3 初始化数据该预置什么一个直接运行的项目SQL 脚本里至少要有这些预置数据管理员账号一条用户名密码别太复杂方便登录测试分类数据若干条比如单板、双板、固定器、雪鞋、护具每种分类下若干条商品数据价格、库存要有区分度两条样例订单数据方便打开订单列表时有东西可看。如果你拿到手的 SQL 脚本里没有这些数据建议先把这些基础数据补上再启动项目否则前端页面空荡荡你根本不知道接口到底跑没跑通。5. 从零到跑通的完整操作手册这部分是帮忙解决可直接运行这四个字的最后一公里。我按正常拿到源码后的顺序从头到尾写一遍每一步都附带我踩过的坑。5.1 环境准备清单在没把所有环境装齐之前不要急着启动项目否则会陷入缺啥装啥的循环里。先对照这张表检查软件推荐版本用途检查命令JDK8 或 11SpringBoot 2.x17SpringBoot 3.x编译和运行后端java -versionMaven3.6后端依赖管理mvn -vMySQL5.7 或 8.0数据库mysql --versionNavicat / DBeaver任意执行 SQL 脚本无Node.js14/16Vue218Vue3前端依赖安装和运行node -vnpm / cnpm跟随 Node前端包管理npm -v这里最容易被忽略的是 Node 版本和前端项目不匹配。Vue 2 的老项目用的是node-sass时Node 版本太高会直接编译失败如果是sass包则没有这个问题。我的建议是电脑上装一个nvm随时切换 Node 版本。5.2 初始化数据库并启动后端第一步操作数据库。用 Navicat 或 DBeaver 新建一个数据库名字建议和源码配置文件里一致通常叫ski_sales字符集选utf8mb4。然后在工具里找到运行 SQL 文件功能把源码路径下doc/sql/init.sql或类似脚本执行一遍。执行完之后检查三件事表是否建全了、数据是否进去了、密码字段是否已经加密过。很多课设源码为了避免新手踩密码加密的坑会直接存明文你能在表里看到密码就说明脚本没问题。第二步改配置。打开后端工程下的src/main/resources/application.ymlserver: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/ski_sales?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver然后进入后端工程目录执行mvn spring-boot:run看到类似Tomcat started on port(s): 8080的日志就说明后端启动成功了。如果你想在服务器上跑也可以打成 jar 包mvn clean package -DskipTests java -jar target/ski-sales-backend.jar5.3 启动前端并验证登录前端和后端是独立进程必须分别启动。进入前端目录npm install --registryhttps://registry.npmmirror.com这一步是最容易卡住的速度慢或者报错基本都是网络问题。npmmirror是国内镜像源能解决绝大多数下载失败。安装完依赖后npm run serve如果启动成功日志会输出访问地址通常是http://localhost:8081或http://localhost:3000。打开浏览器访问这个地址看到登录页输入预置的管理员账号密码。登录成功后跳转到管理后台数据能正常显示整条链路就算通了。5.4 前后端联调时的 URL 关系很多新手的困惑在于前端访问的是 8081后端在 8080数据是怎么通到一起的答案在前端的vue.config.js或者.env配置里最常见的方案是使用代理转发module.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } }也就是说前端 axios 请求的/api/product/page在开发环境下会被代理到http://localhost:8080/api/product/page。浏览器地址栏里看到的还是 8081但实际请求已经转发到了后端。理解了这一点就理解了整个前后端分离联调的基本原理。6. 启动过程中最常见的几个坑这套项目我前前后后跑过好几遍也帮人远程排查过不少问题。把所有杂七杂八的报错归纳一下高频问题基本不超过下面这几类。6.1 MySQL 连接报错SSL、时区和驱动全没对上最经典的报错是Access denied for user rootlocalhost这是密码和账号问题重新确认application.yml里的配置就行。真正麻烦的是 MySQL 8.0 的 SSL 连接报错The server time zone value йʱ is unrecognized以及Public Key Retrieval is not allowed。解决办法就是连接串里加三个参数useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue记住不要只从网上复制一段连接串就完事要结合你本地 MySQL 的实际情况确认username和password。另外如果你装的是 MySQL 8.0 但驱动用的还是老旧的com.mysql.jdbc.Driver同样会报警告换成com.mysql.cj.jdbc.Driver即可。6.2 端口被占用怎么办后端启动时如果日志显示Port 8080 was already in use说明有别的进程占着端口。Linux 或 Mac 上用lsof -i:8080Windows 上用netstat -ano | findstr 8080找到占用进程的 PID 之后确认不是你正在用的服务就直接结束它或者干脆改后端端口。如果改了端口前端vue.config.js里的代理目标地址也要同步改否则联调失败。6.3 前端请求接口跨域提示浏览器控制台报No Access-Control-Allow-Origin header is present是跨域问题。这个通常因为你没有用代理而是直接把后端地址写成了http://localhost:8080导致浏览器拦截了不同端口之间的请求。解决思路有两套首选使用 5.4 中的代理方式开发环境不需要后端做任何额外配置次选在后端增加一个 CORS 配置类允许特定来源跨域访问。我强烈建议第一套方案。代理配置只在开发环境生效部署时用 Nginx 反代更合理而后端开启 CORS 会暴露接口给所有来源安全性差一些。6.4 Maven 依赖下载慢和 node-sass 编译失败Maven 慢的直接解决方案是给settings.xml配置阿里云镜像mirror idaliyunmaven/id mirrorOf*/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirrornpm 依赖下载慢就用前面提到的--registryhttps://registry.npmmirror.com。node-sass编译失败通常表现为一长串gyp ERR!最快的修复方式不是去补编译环境而是把package.json里的node-sass替换成sass然后删掉node_modules重新安装。大多数情况下语法是兼容的这个方案省时省力。6.5 只有打包好的 jar怎么反编译回项目有人在群里问过拿到一个 jar 包怎么恢复成源码。说实话jar是编译产物用jd-gui或IDEA的反编译插件可以还原出大部分 Java 类的逻辑但application.yml、前端页面、资源文件这些并不必然在 jar 里即使反编译出来能跑通的比例也很低。我的建议是如果你只是学习某个功能的实现思路反编译看class文件里的关键逻辑是没问题的但如果你需要继续维护还是要找到原始源码否则后续改造成本会高得离谱。这也提醒一句自己的项目源码一定要用 Git 管理别等丢了才想办法反编译。写在最后的几个建议整套项目跑通之后我建议按下面这个顺序做二次学习先把登录、商品、下单这条主链路完整走一遍弄清楚每个请求从前端发出到后端入库的过程中经过了哪些类然后找一张业务表对应代码里的 Mapper、Entity、Service把 MyBatis-Plus 的几个常用方法手动敲一遍最后再试着加一个小功能比如给商品加库存预警改动不大但能帮你把整条链路重新打通一次。如果你想拿这个项目去面试或答辩重点不是背代码而是能讲清为什么这么设计——为什么订单拆成主表和明细表为什么统一返回体为什么前端要封装 axios 拦截器。这套源码恰恰每个点都有对应的实践场景这是它比纯理论教程更适合入门的地方。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

UltraEdit 安装时请注意:环境变量与 TaoToken 配置避坑指南 2026/9/30 19:33:06

UltraEdit 安装时请注意:环境变量与 TaoToken 配置避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
2025年人工智能十大趋势 - 智能行动者的崛起:TaoToken 统一 Key 接入 AI Agent 实战 2026/9/30 19:33:06

2025年人工智能十大趋势 - 智能行动者的崛起:TaoToken 统一 Key 接入 AI Agent 实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
芯片焊接工艺包选型:订单碎片化后要盯住的4个硬指标 2026/9/30 19:33:06

芯片焊接工艺包选型:订单碎片化后要盯住的4个硬指标

跟一位做功率器件的朋友吃饭,他吐槽最近半年的采购清单:芯片焊接工艺包从过去一年谈一次,变成一个季度来三单,每一单的焊料类型、焊接方式、装片数量都不一样,数量从八千颗一路砍到六百颗。他问我,这种碎单…

阅读更多 →
一条停水通知花了几小时,TaoToken 能不能把它压缩到几秒? 2026/9/30 19:32:59

一条停水通知花了几小时,TaoToken 能不能把它压缩到几秒?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
初识MCP(Model Context Protocol):从零搭建一个可用的MCP Server 2026/9/30 19:32:59

初识MCP(Model Context Protocol):从零搭建一个可用的MCP Server

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
【Bug已解决】npm error code ENOTEMPTY: directory not empty, rename claude-code 解决方案:用 TaoToken 统一 Key 通道修 2026/9/30 19:32:53

【Bug已解决】npm error code ENOTEMPTY: directory not empty, rename claude-code 解决方案:用 TaoToken 统一 Key 通道修

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉