news 2026/10/14 19:08:30

从零搭建校园二手交易系统:Vue2 + SpringBoot 4.x 全栈实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零搭建校园二手交易系统:Vue2 + SpringBoot 4.x 全栈实战

文章目录

    • 📖 前言
    • 🎯 项目介绍
      • 核心功能
      • 界面预览
    • 🛠 技术栈
    • 🏗 系统架构
      • 项目结构
    • 💾 数据库设计
      • user 用户表
      • product 商品表
      • orders 订单表
    • 🔧 关键技术点
      • 1. 组件化开发
      • 2. Vue Router 路由守卫
      • 3. Axios 二次封装
      • 4. Spring Data JPA 方法名自动生成 SQL
      • 5. 统一响应结果
      • 6. 全局异常处理
    • 🐛 踩坑记录
      • 坑 1:SpringBoot 4.x 不支持 MyBatis-Plus
      • 坑 2:MySQL 保留字 order
      • 坑 3:Git 子模块问题
      • 坑 4:Vue Router 部署到 Pages 后刷新 404
      • 坑 5:JPA 分页页码从 0 开始
    • 🚀 部署方案
      • 后端
      • 前端
    • 📊 项目总结
      • 完成度
      • 学到的
      • 后续计划
    • 🔗 项目地址

📖 前言

最近花了一周时间做了一个校园二手交易系统,从数据库设计到前端 UI,从后端接口到部署上线,完整走了一遍前后端分离的开发流程。这篇文章记录一下整个项目的技术选型、架构设计和踩坑经验,希望能给做类似项目的同学一些参考。

项目地址:

  • 🌐 GitHub:https://github.com/dxiangwiki/campus-trade
  • 🚀 在线演示:https://dxiangwiki.github.io/campus-trade/

🎯 项目介绍

一个面向校园场景的二手物品交易平台,支持用户注册登录、商品发布、在线下单、订单管理等功能。

核心功能

  • 👤用户模块:注册、登录、个人中心
  • 📦商品模块:发布商品、商品列表、关键词搜索、分页展示
  • 🛒订单模块:在线下单、订单列表、状态管理
  • 🔒权限控制:Vue Router 路由守卫,未登录自动跳转

界面预览



🛠 技术栈

分类技术
前端框架Vue 2.6 + Vue Router 3
UI 组件库ElementUI 2.15
HTTP 客户端Axios 1.x
后端框架SpringBoot 4.1 + Spring Data JPA
数据库MySQL 9.4
工具库Lombok
部署GitHub Pages + GitHub Actions

🏗 系统架构

┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 浏览器 │ HTTP │ SpringBoot │ JPA │ MySQL │ │ (Vue2 SPA) │ ──────► │ 后端服务 │ ──────► │ 数据库 │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ ElementUI │ Controller │ Vue Router │ Service │ Axios │ Repository

项目结构

campus-trade/ ├── campus-trade-backend/ # 后端 │ └── src/main/java/com/campus/trade/ │ ├── common/ # 通用(Result、异常处理) │ ├── config/ # 配置(跨域) │ ├── controller/ # 接口层 │ ├── dto/ # 数据传输对象 │ ├── entity/ # 实体类 │ ├── repository/ # 数据访问层 │ └── service/ # 业务逻辑层 └── campus-trade-frontend/ # 前端 └── src/ ├── api/ # 接口封装 ├── components/ # 复用组件 ├── router/ # 路由配置 ├── utils/ # 工具(Axios 封装) └── views/ # 页面

💾 数据库设计

user 用户表

字段类型说明
idBIGINT主键
usernameVARCHAR(50)用户名(唯一)
passwordVARCHAR(100)密码
nicknameVARCHAR(50)昵称
phoneVARCHAR(20)手机号
create_timeDATETIME注册时间

product 商品表

字段类型说明
idBIGINT主键
titleVARCHAR(100)商品标题
descriptionVARCHAR(500)描述
priceDECIMAL(10,2)价格
categoryVARCHAR(50)分类
statusTINYINT0在售 1已售
seller_idBIGINT卖家 ID
create_timeDATETIME发布时间

orders 订单表

字段类型说明
idBIGINT主键
order_noVARCHAR(50)订单号(唯一)
product_idBIGINT商品 ID
buyer_idBIGINT买家 ID
seller_idBIGINT卖家 ID
amountDECIMAL(10,2)金额
statusTINYINT0待付款 1已付款 2已完成
create_timeDATETIME下单时间

💡踩坑:订单表名用orders而不是order,因为order是 MySQL 保留字,用 JPA 会报错。


🔧 关键技术点

1. 组件化开发

前端拆分为 7 个页面 + 1 个复用组件:

views/ # 页面级组件 ├── Layout.vue # 主布局(顶栏 + 内容区) ├── Login.vue # 登录页 ├── Register.vue # 注册页 ├── ProductList.vue # 商品列表 ├── ProductPublish.vue # 发布商品 ├── OrderManage.vue # 订单管理 └── UserCenter.vue # 个人中心 components/ # 复用组件 └── ProductCard.vue # 商品卡片

ProductCard.vue通过props接收商品数据,通过$emit触发购买事件,在多处复用。

2. Vue Router 路由守卫

router.beforeEach((to,from,next)=>{constuser=localStorage.getItem('user')constpublicPaths=['/login','/register']if(!publicPaths.includes(to.path)&&!user){next('/login')// 未登录跳登录}else{next()}})

3. Axios 二次封装

统一处理请求拦截、响应错误、Loading 状态:

// 请求拦截:开启 Loading + 带用户 IDservice.interceptors.request.use(config=>{loadingInstance=Loading.service({fullscreen:true})constuser=JSON.parse(localStorage.getItem('user')||'null')if(user)config.headers['X-User-Id']=user.idreturnconfig})// 响应拦截:统一处理错误 + 解包 dataservice.interceptors.response.use(res=>{loadingInstance&&loadingInstance.close()constdata=res.dataif(data.code!==200){Message.error(data.msg)returnPromise.reject(newError(data.msg))}returndata.data})

4. Spring Data JPA 方法名自动生成 SQL

Repository 只需声明方法名,JPA 自动生成 SQL:

publicinterfaceProductRepositoryextendsJpaRepository<Product,Long>{// 自动生成:SELECT * FROM product WHERE status=? ORDER BY create_time DESC LIMIT ...Page<Product>findByStatusOrderByCreateTimeDesc(Integerstatus,Pageablepageable);// 自动生成:SELECT * FROM product WHERE status=? AND title LIKE %?% ORDER BY create_time DESCPage<Product>findByStatusAndTitleContainingOrderByCreateTimeDesc(Integerstatus,Stringtitle,Pageablepageable);}

一行 SQL 都不用写,方法名就是 SQL 语义。

5. 统一响应结果

@DatapublicclassResult<T>{privateIntegercode;privateStringmsg;privateTdata;publicstatic<T>Result<T>success(Tdata){Result<T>r=newResult<>();r.code=200;r.msg="success";r.data=data;returnr;}publicstatic<T>Result<T>error(Stringmsg){Result<T>r=newResult<>();r.code=500;r.msg=msg;returnr;}}

6. 全局异常处理

@RestControllerAdvicepublicclassGlobalExceptionHandler{@ExceptionHandler(RuntimeException.class)publicResult<?>handleRuntime(RuntimeExceptione){returnResult.error(e.getMessage());}}

Service 层直接throw new RuntimeException("商品不存在"),前端收到的就是{code: 500, msg: "商品不存在"}。


🐛 踩坑记录

坑 1:SpringBoot 4.x 不支持 MyBatis-Plus

现象:用 Spring Initializr 生成项目时,最低只能选 SpringBoot 4.x,但 MyBatis-Plus 3.5.x 只支持到 SpringBoot 3.x。

解决:改用Spring Data JPA(SpringBoot 官方亲儿子),比 MyBatis-Plus 更贴合 4.x。

坑 2:MySQL 保留字 order

现象:实体类@Table(name = "order")启动报错。

解决:表名改成orders,实体类用@Table(name = "orders")。

坑 3:Git 子模块问题

现象:在 monorepo 里推送后,GitHub Actions 报No url found for submodule path。

原因:子目录里残留了.git文件夹,被 Git 误判为子模块。

解决:删除子目录的.git,并git rm --cached后重新git add。

坑 4:Vue Router 部署到 Pages 后刷新 404

解决:路由模式改成hash(URL 带#),Pages 静态托管就能正确处理。

坑 5:JPA 分页页码从 0 开始

现象:前端传pageNo=1,JPA 显示的还是第一页(其实是第 0 页)。

解决:Service 层做pageNo - 1,前端始终从 1 开始,用户无感。


🚀 部署方案

后端

SpringBoot 打包成 jar,java -jar xxx.jar运行,或部署到云服务器。

前端

GitHub Pages + GitHub Actions 自动化部署:

每次git push到 main 分支,GitHub Actions 自动:

  1. 检出代码
  2. 安装依赖
  3. npm run build
  4. 上传 dist 到 Pages

工作流配置(.github/workflows/deploy-pages.yml):

name:Deploy to GitHub Pageson:push:branches:[main]jobs:build:runs-on:ubuntu-lateststeps:-uses:actions/checkout@v4-uses:actions/setup-node@v4with:{node-version:'18'}-run:npm installworking-directory:./campus-trade-frontend-run:npm run buildworking-directory:./campus-trade-frontend-uses:actions/upload-pages-artifact@v3with:path:./campus-trade-frontend/distdeploy:needs:buildruns-on:ubuntu-latestenvironment:name:github-pagessteps:-uses:actions/deploy-pages@v4

📊 项目总结

完成度

  • ✅ 用户注册 / 登录
  • ✅ 商品发布 / 列表 / 搜索 / 分页
  • ✅ 在线下单 / 订单管理
  • ✅ 统一异常处理
  • ✅ 跨域配置
  • ✅ GitHub Pages 自动化部署

学到的

  1. 前后端分离:RESTful API 设计,Axios 统一封装
  2. Vue 组件化:props 传递 + $emit 事件
  3. JPA 方法命名:优雅地避免写 SQL
  4. GitHub Actions:CI/CD 自动化部署
  5. Monorepo:前后端一个仓库,管理方便

后续计划

  • JWT 登录态(替代 localStorage 明文)
  • 图片上传(本地磁盘 / 阿里云 OSS)
  • 订单状态流转(付款 / 收货 / 完成)
  • WebSocket 实时消息通知
  • 卖家视角(我的发布 / 卖出订单)
  • ECharts 数据看板

🔗 项目地址

  • GitHub:https://github.com/dxiangwiki/campus-trade
  • 在线演示:https://dxiangwiki.github.io/campus-trade/
  • 技术栈:Vue2 + ElementUI + Axios + SpringBoot 4.x + JPA + MySQL

如果这个项目对你有帮助,欢迎给个 ⭐ Star!也欢迎在评论区交流。


作者:dxiangwiki
日期:2026-10

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 19:07:36

Android Recovery与OTA安装机制深度解析:从启动链路到差分升级

1. 从一次OTA升级失败说起&#xff1a;Recovery到底在干什么很多人第一次接触Recovery&#xff0c;都是因为设备OTA升级失败卡在开机界面&#xff0c;或者手动进入恢复模式后不知道那些菜单项背后发生了什么。我最早接触这块是在一个定制设备项目上&#xff0c;当时系统推送了一…

作者头像 李华
网站建设 2026/10/14 19:07:30

什么样的标识可以申请注册商标?注册商标需要具备什么核心条件?

商标注册的准入标准、禁用红线&#xff0c;核心都源于《中华人民共和国商标法》的基础条款。什么样的标识可以申请注册商标&#xff1f;注册商标需要具备什么核心条件&#xff1f;哪些标志是法律明确禁止使用的&#xff1f;这些商标实务中最基础的问题&#xff0c;答案都在以下…

作者头像 李华
网站建设 2026/10/14 19:07:25

算力机房建设:从规划到落地的完整指南

1. 引言随着人工智能、大数据和云计算技术的快速发展&#xff0c;算力已成为数字经济的核心生产力。算力机房作为承载算力基础设施的重要载体&#xff0c;其建设质量直接关系到上层业务的稳定运行和扩展能力。本文将从选址规划、机房设计、供配电系统、制冷系统、网络架构、安全…

作者头像 李华
网站建设 2026/10/14 19:06:42

C语言运算符优先级与结合性详解:避坑指南与记忆技巧

1. 为什么运算符优先级值得单独拎出来讲刚接触C语言那会儿&#xff0c;我总觉得运算符优先级这东西属于“查表就行”的知识点&#xff0c;没必要花时间深究。直到有一次写一个状态机的判断逻辑&#xff0c;代码大概长这样&#xff1a;if (a & b c) {// 期望是 (a & b)…

作者头像 李华
网站建设 2026/10/14 19:06:35

尊界V800公布制动踏板第三方检测结果;马斯克回应“中国分马”:14亿人肯定有人像我,想同台;Meta发布最新AI模型Muse Wonder | 极客头条

「极客头条」—— 技术人员的新闻圈&#xff01;CSDN 的读者朋友们好&#xff0c;「极客头条」来啦&#xff0c;快来看今天都有哪些值得我们技术人关注的重要新闻吧。&#xff08;投稿或寻求报道&#xff1a;zhanghycsdn.net&#xff09;整理 | 郑丽媛出品 | CSDN&#xff08;I…

作者头像 李华
网站建设 2026/10/14 19:06:34

版本控制工具的常见误配置:六项上线前必须回查

上线前一晚才发现问题的团队&#xff0c;往往不是没配版本控制工具&#xff0c;而是配了没生效。主分支的保护开关是开着的&#xff0c;开发同学仍能直接推送&#xff1b;发布分支叫 release/2026.10&#xff0c;规则却只匹配了单层路径&#xff1b;CI 用的访问令牌&#xff0c…

作者头像 李华