news 2026/10/8 8:58:06

Spring Boot+Vue二手手机销售系统毕业设计全流程实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot+Vue二手手机销售系统毕业设计全流程实战

做毕设选到这个题目,算是选到了“天胡开局”。Spring Boot + Vue这套前后端分离组合,是当前Java方向毕业设计里最稳、最主流、最容易出活儿的技术栈之一,而二手手机销售系统这个业务场景,又比那些烂大街的“图书管理”“学生管理”更有商业味道,需求很容易说圆,Demo演示也有看点。这篇文章不搞虚的,我会把整个项目的核心设计思路、数据库怎么建、后端怎么写、Vue怎么调、答辩怎么讲、以及调试时容易踩的坑,全部按实操顺序捋一遍。源码、SQL脚本、文档这些配套材料基础好的同学可以直接跑,但我建议大家一定把自己扔进代码里走一遍,把每个模块为什么这么设计讲清楚,这才是拿高分的关键。

1. 项目整体设计思路与技术选型

1.1 为什么选Spring Boot + Vue组合,它到底好在哪

可以先明确一个结论:在毕业设计这个尺度上,Spring Boot + Vue几乎就是最优解,没有之一。

先看后端。Spring Boot不是一个新的框架,它是对Spring全家桶的一次“封装革命”。传统SSH(Struts + Spring + Hibernate)或SSM(Spring + SpringMVC + MyBatis)时代,最折磨人的是那一堆web.xml、applicationContext.xml配置文件,光是让一个HellWorld跑起来都要折腾半天。Spring Boot把自动配置(AutoConfiguration)做到了极致,你只需要一个spring-boot-starter-web依赖,加一个@SpringBootApplication注解,一个内嵌的Tomcat就帮你把HTTP服务跑起来了。这对毕设来说太关键了——时间要花在业务代码上,不是花在“让服务器起来”上。

再看前端。Vue的核心优势是“渐进式”和“组件化”。vue-cli或vite一行命令就能拉出一个标准工程,Element UI或Element Plus组件库让你不用自己写CSS就能拼出后台管理界面。做毕设的人最怕的就是前端样式写得像“上世纪的政府网站”,用Vue + Element这套组合,颜值分基本稳了。

加上MySQL做数据持久化,这套技术栈的学习资料、踩坑记录、开源项目多到看不完。哪怕你某个点卡住了,搜索引擎随便一翻就能找到答案。这种“生态红利”是你在答辩时能蒙混过关(不是)……是能高效解决问题的基础。

1.2 系统核心需求拆解:你必须说清楚“做的是什么东西”

很多同学拿到题目的第一反应是“不就是商品增删改查嘛”,这个理解太浅了。二手手机销售系统,核心不是手机,是交易流程。

站在用户(买家)角度:要能浏览在售手机、看详情(成色、价格、配置)、加入购物车、下单购买。站在卖家(管理员)角度:要能发布手机信息、管理库存、处理订单、审核上下架。还有一层容易被忽略的是用户角色——如果整个系统只有一个大而全的界面,那答辩时老师说一句“你这个没有权限区分”,你就很难受了。

所以,我给这个系统定下的核心模块是:

  • 前台用户模块:注册登录、浏览商品、商品搜索、购物车、订单管理、个人信息维护
  • 后台管理模块:商品管理(发布/编辑/上下架)、用户管理、订单管理、公告/新闻管理
  • 公共模块:轮播图、分类导航、系统数据统计

这样拆分后,一个标准的“前台展示 + 后台管理”双子系统就出来了。技术栈上对应的是Vue Router做路由分离,Spring Boot按Controller层做模块划分。后面的数据库设计、接口设计、页面设计都围绕这个结构展开。

1.3 技术栈版本选择:别用太老也别用太新

选版本这件事看着不起眼,实际坑很多。我的建议是:

角色推荐版本说明
JDK1.8 或 11很多公司的老项目还在用JDK8,毕设用JDK8兼容性最好,别上17/21给自己找麻烦
Spring Boot2.7.x稳定,第三方教程多,很多开源项目都是这个版本
Vue2.6.x + Element UI 或 3 + Element Plus如果你不熟Vue,选2更稳,教程多到爆炸;想折腾可以上3
MySQL5.7 或 8.05.7最经典,8.0也行,注意驱动依赖不一样
MyBatisMyBatis-Plus 3.5.x强烈建议用Plus,代码量直接少一半
Node.js14/16/18运行Vue工程用,装LTS版本就行

有人问为什么不用MyBatis而用MyBatis-Plus,因为后者在CRUD上太友好了:BaseMapper里已经有selectById、selectList、insert这些方法,你连SQL都不用写就能完成80%的单表操作。毕设的重心在业务逻辑上,不在写重复的<insert>标签上。这点想清楚,后面效率完全不一样。

2. 数据库设计:二手手机交易系统的地基

2.1 核心表结构规划

数据库表设计决定了系统的上限。毕设评分的重点之一,就是看你的ER图是否合理、表之间关联是否清楚、字段命名是否规范。二手手机销售系统的表不需要太多,但每张表都得“有话说”。

我建议的核心表如下:

  • 用户表(sys_user):id,username,password,phone,email,avatar,role,status,create_time。其中role区分管理员和普通用户,可以用0/1或ROLE_ADMIN/ROLE_USER。

  • 手机商品表(phone_info):id,title,brand,model,price,original_price,condition_level(成色等级,例如99新/95新/有划痕),description,cover_image,detail_images,stock,sales_volume,shelf_status,create_time,update_time。这是整个系统的信息中心,字段尽量给全,图片路径用URL字符串存储。

  • 购物车表(cart_item):id,user_id,phone_id,quantity,checked,create_time,update_time。这里注意一点,购物车要不要建表取决于你的设计理念,用localStorage也能做购物车,但既然要做数据库设计亮点,还是建表更规范,而且方便后续扩展订单逻辑。

  • 订单表(order_info):id,order_no(唯一订单号),user_id,phone_id,quantity,total_amount,status(0待付款/1已付款/2已发货/3已完成/4已取消),create_time,pay_time,deliver_time,complete_time。建议再拆出一个订单明细表来记录商品快照(商品名称、下单时价格、图片),因为商品信息会变,但订单得保留下单那一刻的真实数据。

  • 公告/新闻表(news_info):id,title,content,cover,create_time。后台发布公告用,前台首页展示。

  • 轮播图表(banner_info):id,image_url,link_url,sort,status。前台首页轮播图数据。

这六张表已经能撑起整个系统了。如果想让功能更丰满,可以再加收货地址表、手机品牌分类表、收藏表。但核心记住一个原则:表不在多,而在于能否支撑核心业务流程闭环。

2.2 关系设计中的关键考量与反范式技巧

设计表关系时要讲得清“为什么”,这是答辩加分点。

用户表和订单表是1:N;购物车表和用户表是1:N;订单表和商品表本质上是N:M,通过订单明细表来解除。这个逻辑绝大多数同学都懂,但有一个细节容易被忽略——商品表要不要存冗余字段sales_volume。

我的建议是:存。因为每次查询都去订单表COUNT(*)太浪费性能了,而且对毕设系统来说,数据量根本达不到需要严格规范化的级别。稍微冗余一点,换查询效率,这叫“反范式设计”,可以在文档里专门写一节,评委看到你懂这个会很加分。

另一个容易忽略的地方是订单明细表为什么要存商品快照。二手手机价格波动大,同一个型号的手机可能今天卖1500明天卖1400,如果订单只关联商品表的id,用户打开历史订单时看到的却是当前价格,这就出问题了。快照字段虽然在表结构上看着“重复”,但它是交易系统的基本常识。

2.3 建表SQL关键写法参考

CREATE TABLE `phone_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(255) NOT NULL COMMENT '商品标题', `brand` varchar(50) DEFAULT NULL COMMENT '品牌', `model` varchar(50) DEFAULT NULL COMMENT '型号', `price` decimal(10,2) NOT NULL COMMENT '售价', `original_price` decimal(10,2) DEFAULT NULL COMMENT '原价', `condition_level` varchar(20) DEFAULT '99新' COMMENT '成色等级', `description` text COMMENT '商品描述', `cover_image` varchar(500) DEFAULT NULL COMMENT '封面图', `detail_images` text COMMENT '详情图,可存多张逗号分隔', `stock` int(11) DEFAULT '0' COMMENT '库存', `sales_volume` int(11) DEFAULT '0' COMMENT '销量', `shelf_status` tinyint(1) DEFAULT '1' COMMENT '上架状态 1上架 0下架', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='二手手机商品表';

两个细节:一是price用decimal(10,2)而不是float,金额字段用浮点类型会出现精度丢失的问题,这在支付场景是绝对的禁忌。二是字符集用utf8mb4而不是utf8,因为utf8在MySQL里存不了emoji和部分生僻字,虽然毕设里不一定用到,但这是一个专业习惯。

3. 后端核心实现:Spring Boot业务落地

3.1 项目分层结构与代码组织

后端工程结构给人的第一印象很重要。推荐这样建包:

com.example.secondhand ├── controller # 接收前端请求,返回JSON ├── service # 业务逻辑层,接口+实现 ├── mapper # MyBatis数据访问层 ├── entity # 数据库实体类 ├── common # 统一返回结果、异常处理、常量 └── config # 配置类(跨域、拦截器等)

分层的目的不是为了好看,而是为了降低耦合。Controller不写SQL,Service只处理业务,Mapper只管数据访问。答辩被问“你系统怎么保证可维护性”的时候,直接说“我严格按照分层架构设计,每层职责单一”,就是及格线以上的回答。

统一返回结构是后端设计里很加分的细节。我习惯于定义这样一个返回体:

{ "code": 200, "message": "操作成功", "data": { ... } }

前端Axios拦截器统一处理code,当code不是200时弹出错误提示。这么做之后,Controller每一层返回数据都不需要再自己包一层Result.ok(data)之外的特殊逻辑,代码整洁度立刻上了一个档次。

3.2 登录鉴权:JWT还是Session

做毕设时最纠结的往往不是业务,而是“登录状态怎么保存”。

两种主流方案:Session和JWT。Spring Security + JWT在真实项目中很常见,但配置过程偏复杂,对毕设来说有点重。我的建议是:用拦截器 + Token(或简单Session)的方案。

如果用的是JWT,核心流程是:

  1. 用户登录时后端校验用户名密码,成功后生成一个带过期时间的Token返回给前端;
  2. 前端把Token存到localStorage,每次请求时在Authorization请求头带上;
  3. 后端写一个LoginInterceptor,拦截除了登录接口以外的请求,校验Token有效性。
public class JwtInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { // 放行预检请求 if ("OPTIONS".equals(request.getMethod())) { return true; } String token = request.getHeader("Authorization"); if (token == null || !JwtUtil.verify(token)) { response.setStatus(401); response.getWriter().write("{\"code\":401,\"message\":\"未登录或登录已过期\"}"); return false; } return true; } }

这个方案的优点是:前端能明确感知登录失效,接口安全性在毕设层面绝对够用。讲项目的时候你可以提一句“用户凭证无状态校验,服务端不保存会话状态,天然支持水平扩展”——这比“我用Session”听起来专业得多。

3.3 商品与订单模块的业务闭环设计

商品模块没什么特殊的,无非是Controller接收分页参数,Service调用MyBatis-Plus的分页查询,返回给前端。真正考验业务设计能力的是订单模块。

一个完整的“立即购买”接口,后端要走这些步骤:

  1. 校验用户登录状态,获取userId;
  2. 根据phoneId查出商品,校验是否上架、库存是否大于0;
  3. 生成唯一订单号(可用时间戳+随机数,或数据库雪花ID),把商品信息写入订单明细快照;
  4. 扣减库存,增加销量;
  5. 返回订单号和待支付金额。

这里我强烈建议把“创建订单”和“扣库存”放到一个@Transactional事务里。因为如果扣库存成功后订单创建失败,会导致数据不一致——商品库存没了,但订单却不存在。一旦出现问题,事务回滚让两边数据都复原。

这个细节看起来简单,但很多同学的代码里根本没加事务注解。我见过太多“库存莫名其妙少了”的案例,最后发现是并发下事务缺失导致的。@Transactional非常轻量,但它在答辩时价值极高,因为老师一定会问“你如何保证数据一致性”。

3.4 后端与前端联调时不得不说的跨域问题

每个做前后端分离项目的同学,100%会遇到跨域(CORS)报错。具体现象是:前端Vue启动在localhost:8080,后端Spring Boot启动在localhost:8081,前端发请求过去,浏览器拦截说“No 'Access-Control-Allow-Origin' header is present on the requested resource”。

这是浏览器的同源策略导致的。解决方案有两种:

一种是在后端加全局CORS配置:

@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } }

另一种是前端配合后端配置代理。Vue CLI项目的vue.config.js里:

module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8081', changeOrigin: true } } } }

这两种方案各有利弊。后端CORS配置简单粗暴,适合快速联调;前端代理是生产环境的常见做法之一,但需要前端去适应。我个人的建议是:开发阶段用第一种,打包部署后你其实不需要CORS配置了,因为前端静态文件会被Spring Boot托管到同一个端口下,同源就不存在跨域问题。

4. 前端核心实现:Vue页面与交互

4.1 工程目录设计与路由划分

Vue前端工程,我见过太多人把所有页面堆在一个views文件夹里,毫无结构。问题在于:你做个毕设无所谓,但答辩老师问“你前端怎么组织”时,你说“随便放的”就尴尬了。

一个清晰的前端结构长这样:

src ├── api # 所有请求接口定义 ├── assets # 静态资源(图片、样式) ├── components # 公共组件(轮播图、商品卡片、分页组件) ├── router # 路由配置 ├── store # Vuex状态管理 ├── views │ ├── home # 前台首页 │ ├── goods # 商品列表、详情 │ ├── cart # 购物车 │ ├── order # 订单确认、订单列表 │ ├── user # 个人中心、登录注册 │ └── admin # 后台管理页面

路由配置上,前台和后台建议分开。后台管理页面用meta: { requiresAuth: true }标记需要登录才能访问,配合Vue Router的beforeEach导航守卫做登录拦截:

router.beforeEach((to, from, next) => { const token = localStorage.getItem('token') if (to.matched.some(record => record.meta.requiresAuth) && !token) { next({ path: '/login' }) } else { next() } })

4.2 Axios封装与接口调用的正确姿势

直接在每个页面里写axios.get('/api/phone/list')也能跑,但一旦接口地址变动或需要统一处理登录过期,你就会痛苦到想砸电脑。我把Axios封装成一个request.js模块,统一处理三件事:请求头加Token、响应拦截、错误提示。

import axios from 'axios' import { Message } from 'element-ui' const request = axios.create({ baseURL: '/api', 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 => { const res = response.data if (res.code !== 200) { Message.error(res.message || '请求失败') return Promise.reject(new Error(res.message)) } return res.data }, error => { if (error.response && error.response.status === 401) { localStorage.removeItem('token') router.push('/login') } Message.error('网络异常,请稍后重试') return Promise.reject(error) } ) export default request

这样封装后,页面里调用接口就非常干净了:

import request from '@/utils/request' export function getPhoneList(params) { return request({ url: '/phone/list', method: 'get', params }) }

页面里直接getPhoneList({ page: 1, size: 10 }).then(res => { this.list = res.rows }),所有公共逻辑全部收敛。写的时候多花10分钟,后面一整个项目的开发体验都会起飞。

4.3 商品列表、购物车与订单流程的页面实现要点

前台页面的核心场景有三个,做得好不好直接决定演示效果。

商品列表页:用卡片网格布局展示手机商品,每个卡片显示封面图、标题、成色、价格。顶部加分类筛选和关键词搜索框。分页用Element组件的el-pagination。这里一个小细节:图片建议用固定比例裁剪好的图,否则卡片会忽高忽低,看上去非常业余。

商品详情页:头部是图片轮播(用el-carousel),下面是商品信息、成色描述、库存数量、购买按钮。购买按钮有两种逻辑:直接下单和加入购物车。建议这两个按钮都做,形成完整业务链路。

购物车与结算页:购物车列表用表格或卡片展示,右侧是结算栏(合计金额、去结算按钮)。点击结算后跳转订单确认页,需要填写收货人信息,然后提交订单。

后端交互上,购物车加减数量后要及时调用更新接口;提交订单成功后清空购物车对应项;订单列表页按状态Tab切换(待付款/已发货/已完成)。

4.4 后台管理界面的搭建思路

后台管理页面重点不是炫酷,是“功能完整 + 操作顺手”。

左侧菜单用el-menu,顶部是标题栏和退出按钮。内容区嵌套路由切换不同管理页面。

商品管理页:表格展示所有商品,支持上下架切换、编辑、删除。新增/编辑商品用el-dialog弹窗,里面用el-form做表单校验——手机名称必填、价格必须大于0、图片上传用Element的上传组件,上传成功后把返回的URL存到表单字段里。

订单管理页:表格展示所有订单,按订单状态筛选。管理员可以发货(将订单状态从“已付款”变成“已发货”)。

用户管理页:表格展示注册用户,支持禁用/启用账号。禁用后该用户登录要提示“账号已被禁用”。

如果想让后台更亮眼,可以在首页加一个简单的统计面板:商品总数、用户总数、订单总数、今日新增订单数,别看只是几个COUNT(*)查询,视觉加分非常明显。

5. 部署调试流程:从源码到可演示Demo

5.1 本地开发环境搭建全流程

这一节写给那些第一次在自己电脑上跑项目就心态爆炸的同学。

第一步:装JDK。下载JDK 8,配置JAVA_HOME环境变量,在命令行运行java -version验证成功。

第二步:装MySQL。Windows下直接用安装包,记住你设置的root密码。如果对安装没有把握,可以用集成环境PhpStudy或小皮面板,一键启动MySQL服务。安装完成后用Navicat新建一个数据库,然后导入项目里附带的.sql文件。

第三步:装Maven。把Maven解压后配置MAVEN_HOME环境变量,配置阿里云镜像源(在conf/settings.xml里改),这样下载依赖会快很多。然后打开后端工程,IDEA会自动识别Maven项目并下载依赖。如果下载慢,检查镜像是否配置正确。

第四步:装Node.js。同样LTS版本一路下一步。然后在Vue项目根目录执行:

npm install

如果npm install太慢,设置淘宝镜像源:

npm config set registry https://registry.npmmirror.com

依赖装完后执行npm run serve启动开发服务器。正常情况下终端会显示App running at: http://localhost:8080。

第五步:改配置。打开后端工程的application.yml,把MySQL的用户名密码改成自己的,数据库名改成你导入时的库名。然后启动后端Application类。看到“Started Application in X seconds”就是成功了。

5.2 代码打包与联合部署(前端放进后端)

开发阶段是前后端两个服务独立跑,但最终提交或演示时通常要打包成一个整体。

先在前端工程目录执行:

npm run build

执行完后会生成一个dist目录,里面是index.html和static/静态资源。把dist目录里的所有文件复制到后端工程的src/main/resources/static目录下。重新打包后端:

mvn clean package -DskipTests

生成的.jar文件在target目录下,执行:

java -jar second-hand.jar

这个时候Spring Boot已经把前端页面当作静态资源托管了,直接访问http://localhost:8080就能看到系统首页,前后端完全同源,没有任何跨域问题。这个部署方式非常好讲,也是真实项目中最常见的“单体外壳”部署方案。

5.3 十分钟跑通演示的核心链路检查清单

每年答辩,总有人现场演示时翻车:“登录进去了但列表加载不出来”、“图片裂了”、“点下单没反应”。大部分问题都能提前排查。我提供一个自检清单,演示前按顺序过一遍:

  • 后端是否启动成功,application.yml数据库密码是否正确
  • 前端是否已打包并放进后端static目录,还是前端单独跑在8080端口
  • 数据库是否已导入,三个业务基础数据(管理员账号、普通用户账号、至少5条商品数据)是否存在
  • 图片路径是否能访问,如果图片存在本地,确认目录路径是否存在
  • 浏览器控制台是否有红色报错,确认所有接口返回code: 200

这套清单跑完,基本能保障演示时不会出大问题。

6. 常见问题与排查技巧实录(踩坑合集)

6.1 依赖下载失败或IDEA报红

最经典的问题。pom.xml里的依赖全部标红,或者在Maven面板里一直报Cannot resolve symbol 'springframework'。

排查顺序是:IDEA的Maven设置里检查是否用了自己配置的settings.xml->检查settings.xml里镜像是否配好->点击IDEA右侧Maven面板的刷新按钮强制重新加载->删掉本地仓库中对应依赖的文件夹重新下载。绝大多数情况是网络问题,配好阿里云镜像就解决了。

6.2 数据库连接报错:Access denied or Unknown database

“Access denied for user 'root'@'localhost'”说明用户名密码不对;“Unknown database 'xxx'”说明指定的数据库不存在。前一个去改application.yml,后一个去重新导入SQL文件。还有一个很隐蔽的问题:MySQL 8.0的驱动类名和5.7不一样,8.0要用com.mysql.cj.jdbc.Driver,并且URL需要指定时区参数serverTimezone=Asia/Shanghai。

6.3 前端页面空白或404

npm run serve启动成功但页面空白,按F12看控制台报错。如果是Cannot find module 'xxx',说明缺依赖,npm install重装;如果是路由404,检查后端接口前缀和前端baseURL是否匹配。一个常见的前坑:后端Controller映射是/phone/list,前端请求却是/api/phone/list,这时需要在后端加server.servlet.context-path=/api或前端把baseURL改成空。

6.4 MyBatis-Plus分页查不出数据

selectPage返回的total为0或者records为空,但数据库明明有数据。多数原因有两个:一是分页拦截器没配置,二是表名或字段名对不上。MyBatis-Plus默认开启驼峰映射,但数据库字段如果叫condition_level而实体属性叫conditionLevel是可以自动映射的,前提是字段命名规范。分页插件配置如下:

@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }

少加这个是高频问题,一定要检查。

6.5 上传的图片无法显示

检查是不是防盗链问题,图片URL能不能在浏览器直接访问。如果前端页面和图片服务不同端口,有些本地图片会被浏览器拦截。最简单的做法是:图片上传后通过后端接口返回,统一存到一个磁盘目录,后端配置静态资源映射:

spring: web: resources: static-locations: file:D:/upload/,classpath:/static/

6.6 修改端口号的正确姿势

开发阶段想改后端端口,在application.yml加:

server: port: 8081

改前端端口在vue.config.js:

module.exports = { devServer: { port: 3000 } }

改完之后重启各自服务即可。注意改了前端端口后,后端CORS配置里的allowedOriginPatterns要对应加上新端口,否则会跨域。

7. 答辩讲解加分点:从“做了系统”到“讲透系统”

7.1 演示节奏建议

我见过很多人演示时“唰唰唰”把页面点完,老师还没看清界面,演示就结束了。错误的演示方式等于自废武功。建议按这样的节奏:先讲背景与需求(30秒)-> 讲系统架构与角色(1分钟)-> 演示前台“用户视角”完整买手机流程(3分钟)-> 演示后台“管理员视角”商品管理与订单处理(3分钟)-> 最后讲技术亮点(1分钟)。

7.2 老师最爱问的问题清单

提前把这几个问题想好,答辩基本稳了一大半:

  • “你这个系统的角色权限是怎么控制的?” 答:登录后签发Token,Token里包含用户角色,后端拦截器校验接口权限,前端路由做页面权限控制。
  • “购物车和订单的数据一致性怎么保证?” 答:创建订单和扣减库存放在同一个事务里,失败会回滚。
  • “你的数据库为什么这么设计?” 答:按业务模块拆表,订单明细做了快照冗余,商品表加了销量冗余字段提升查询效率。
  • “项目里你觉得最难的点是什么?” 答:可以说前后端联调时的跨域问题、订单模块事务问题、多个状态流转的订单设计问题。

7.3 设计文档的配合要点

文档不是给老师看的摆设,是你答辩时的提词器。在文档里一定要含:系统架构图、功能架构图、业务流程图(特别是购物和订单流程)、ER图、数据库表设计说明、核心接口说明。每个图在答辩前自己对着讲一遍,讲顺了,整个演示基本不会卡壳。

8. 写在最后的一点经验

做完这个项目,我最大的体会是:二手手机销售系统这个选题,真正考验人的不是技术,而是对业务链路的完整理解。很多人的系统只做到了“商品CRUD”就停了,根本没走到订单闭环。但恰恰是这个从“浏览商品”到“提交订单”再到“后台发货”的完整流程,才让整个系统显得成熟、有商业价值。

从0到1把项目做一遍,比对着视频敲十遍代码有用得多。我强烈建议你拿一份源码之后,先从数据库脚本开始看,搞清楚每张表的作用;然后跑起来,对着代码断点走一遍“用户下单”的完整链路;最后再自己动手改几个功能——哪怕只是给商品加一个“品牌筛选”,你也会对这套前后端交互有完全不同的理解。

如果你在搭建环境或者跑通项目的过程中遇到实在绕不过去的坑,欢迎把这篇文章翻出来再对照一遍。我踩过的坑,你大概率还能再踩一遍——但至少现在,你已经知道每个坑长什么样了。

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

DeepSeek+Mermaid自动化图表生成:从原理到实战的完整指南

简介&#xff1a;这份文档面向具备一定编程基础的研发人员、项目经理与数据分析师&#xff0c;聚焦如何借助DeepSeek与Mermaid实现可视化图表的自动化生成。内容从DeepSeek的发展历程、MoE架构与多场景应用切入&#xff0c;系统讲解Mermaid的文本语法及流程图、时序图、甘特图等…

作者头像 李华
网站建设 2026/10/8 8:57:31

Flutter iOS模拟器报No such process?M1/M2 Mac七步排查与修复

M1/M2 Mac 上用 Flutter 跑 iOS 模拟器&#xff0c;最磨人的不是编译报错&#xff0c;而是这种“查无可查”的运行时故障。Xcode 构建明明显示成功&#xff0c;模拟器也正常开机&#xff0c;App 装上之后眼看就要跑起来了&#xff0c;控制台却甩给你一句No such process&#x…

作者头像 李华
网站建设 2026/10/8 8:53:40

Obsidian 加 Gitee 零成本搭建笔记自动同步方案

我折腾 Obsidian 和 Gitee 这套笔记方案的时间不算短了&#xff0c;从最开始把笔记散落在本地文件夹里&#xff0c;到后来尝试各种网盘、同步工具&#xff0c;最后才定下“Obsidian 做笔记、Gitee 做云端仓库、Git 插件做自动同步”这个组合。很多朋友问过我为什么不用现成的云…

作者头像 李华
网站建设 2026/10/8 8:53:40

3分钟自建RSSHub:插件化架构打造全网信息订阅与监控体系

前阵子群里有人吐槽&#xff1a;“现在想盯一个网站的内容更新&#xff0c;怎么这么难&#xff1f;要么天天手动刷&#xff0c;要么开一堆 App 被推送轰炸。”我回了一句&#xff1a;“你缺的是一个 RSS 订阅体系。”然后顺手把 RSSHub 加浏览器插件那套东西丢过去。十分钟后他…

作者头像 李华
网站建设 2026/10/8 8:53:04

Java课程设计:飞翔的小鸟游戏源码与实现详解

简介&#xff1a;这是一份面向Java初学者与在校学生的飞翔的小鸟游戏完整实现源码&#xff0c;配套详细开发教程&#xff0c;适合用作期末大作业、课程设计或毕业设计参考。项目采用Java语言编写&#xff0c;代码注释清晰&#xff0c;新手也能看懂&#xff0c;部署简单&#xf…

作者头像 李华