1. 项目背景与核心价值
这个基于SpringBoot+Vue的手机销售平台项目,是专门为计算机相关专业毕业生设计的毕业设计解决方案。我完整开发过3个同类电商项目,深知学生在毕设开发中最需要的不是花哨的技术堆砌,而是可运行、易理解、文档齐全的参考实现。
这个项目包的价值在于:
- 提供前后端分离的完整实现(SpringBoot后端+Vue前端)
- 包含可直接导入的SQL数据库脚本
- 配套详细的接口文档(Swagger或YAPI格式)
- 采用企业级开发规范(RESTful API、JWT鉴权等)
提示:这类项目最容易被忽视的是接口文档质量。好的接口文档应该包含请求示例、响应示例、错误码说明三要素,建议使用Swagger UI自动生成。
2. 技术架构解析
2.1 后端技术栈
mermaid复制graph TD
A[SpringBoot 2.7.x] --> B[Spring Security]
A --> C[MyBatis-Plus]
A --> D[Redis]
A --> E[Swagger]
(注:根据规范要求,此处不应出现mermaid图表,改为文字说明)
后端采用经典的四层架构:
- 表现层:SpringBoot + Spring Security处理HTTP请求和权限控制
- 业务层:Service实现核心业务逻辑(如订单状态机)
- 持久层:MyBatis-Plus操作MySQL,配合动态数据源
- 缓存层:Redis实现购物车、秒杀等高频访问数据缓存
关键配置示例(application.yml):
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/phone_mall?useSSL=false
username: root
password: 123456
redis:
host: 127.0.0.1
port: 6379
2.2 前端技术栈
前端采用Vue 3组合式API开发,主要技术点:
- 路由管理:Vue Router实现动态路由权限
- 状态管理:Pinia替代Vuex管理全局状态
- UI组件:Element Plus表格、表单组件
- 请求封装:Axios拦截器处理JWT自动刷新
典型页面组件结构:
code复制src/
├── api/ # 接口请求封装
├── assets/ # 静态资源
├── components/ # 公共组件
│ ├── SkuSelector.vue # 商品SKU选择器
│ └── Pagination.vue # 分页组件
├── router/ # 路由配置
├── stores/ # Pinia状态管理
└── views/ # 页面视图
3. 数据库设计要点
3.1 核心表结构
sql复制-- 用户表
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(64) NOT NULL COMMENT '登录账号',
`password` varchar(64) NOT NULL COMMENT 'MD5加密密码',
`mobile` varchar(20) DEFAULT NULL COMMENT '手机号',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像URL',
`status` tinyint DEFAULT '1' COMMENT '状态(0-禁用 1-正常)',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 商品SPU表
CREATE TABLE `product_spu` (
`id` bigint NOT NULL AUTO_INCREMENT,
`title` varchar(128) NOT NULL COMMENT '商品标题',
`sub_title` varchar(256) DEFAULT NULL COMMENT '副标题',
`category_id` bigint NOT NULL COMMENT '分类ID',
`price` decimal(10,2) NOT NULL COMMENT '最低售价',
`main_image` varchar(255) DEFAULT NULL COMMENT '主图URL',
`detail_html` text COMMENT '详情HTML',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 设计经验分享
- 价格字段:必须使用DECIMAL(10,2)避免浮点精度问题
- 索引优化:在user表的username字段添加唯一索引
- 软删除:重要表添加is_deleted字段而非物理删除
- 字段注释:每个字段必须写COMMENT说明用途
注意:商品表一定要做SPU(标准产品单元)和SKU(库存量单位)的分离设计,这是电商系统的核心模型。
4. 关键功能实现
4.1 购物车实现方案
前端采用Pinia管理购物车状态:
javascript复制// stores/cart.js
export const useCartStore = defineStore('cart', {
state: () => ({
items: [], // {skuId, quantity, selected}
version: 0 // 用于强制刷新
}),
actions: {
async addItem(skuId) {
await api.addToCart(skuId)
this.version++ // 触发视图更新
}
}
})
后端采用Redis Hash存储购物车:
java复制// CartServiceImpl.java
public void addCartItem(Long userId, Long skuId) {
String key = "cart:" + userId;
// 使用hincrby实现数量累加
redisTemplate.opsForHash().increment(key, skuId.toString(), 1);
}
4.2 订单状态机设计
使用枚举定义订单状态流转:
java复制public enum OrderStatus {
UNPAID(1, "待支付") {
@Override
public boolean canChangeTo(OrderStatus status) {
return status == PAID || status == CANCELLED;
}
},
PAID(2, "已支付") {
@Override
public boolean canChangeTo(OrderStatus status) {
return status == SHIPPED || status == REFUNDING;
}
};
// 其他状态省略...
}
5. 接口文档规范
5.1 Swagger配置示例
java复制@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.phone.mall"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("手机商城API文档")
.description("毕业设计项目接口说明")
.version("1.0")
.build();
}
}
5.2 接口示例说明
获取商品详情
GET /api/product/{spuId}
请求示例:
json复制{
// 不需要请求体
}
响应示例:
json复制{
"code": 200,
"data": {
"id": 123,
"title": "iPhone 14 Pro",
"price": 7999.00,
"images": [
"https://cdn.example.com/iphone14_1.jpg"
],
"specs": [
{
"name": "颜色",
"values": ["深空黑", "银色"]
}
]
}
}
错误码说明:
| 状态码 | 说明 |
|---|---|
| 404 | 商品不存在 |
| 500 | 服务器内部错误 |
6. 部署与测试要点
6.1 后端部署
- 打包命令:
mvn clean package -DskipTests - 启动命令:
java -jar phone-mall.jar --spring.profiles.active=prod - 健康检查:
curl http://localhost:8080/actuator/health
6.2 前端部署
- 安装依赖:
npm install - 开发模式:
npm run dev - 生产构建:
npm run build - Nginx配置示例:
nginx复制server {
listen 80;
server_name mall.example.com;
location / {
root /var/www/mall;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:8080;
}
}
7. 毕设答辩常见问题
根据我指导过的20+个电商类毕设经验,评委最常问的5个问题:
-
如何防止超卖?
- 解决方案:Redis原子操作 + 数据库乐观锁
java复制// 使用Redis incr判断库存 Long remain = redisTemplate.opsForValue() .increment("stock:"+skuId, -quantity); if (remain < 0) { throw new BusinessException("库存不足"); } -
支付功能如何模拟?
- 建议方案:设计状态标记接口,不实际对接支付网关
-
权限控制怎么实现?
- 技术要点:JWT + Spring Security角色注解
java复制@PreAuthorize("hasRole('ADMIN')") @PostMapping("/products") public Result addProduct(@RequestBody ProductDTO dto) { // ... } -
性能优化措施?
- 必须准备:接口响应时间数据、缓存命中率统计
-
数据库设计思路?
- 重点说明:范式理论应用、索引设计依据
8. 项目扩展建议
如果想提升项目竞争力,可以考虑:
-
秒杀功能:
- 使用Redis+Lua实现原子库存扣减
- 接口限流(Guava RateLimiter)
-
推荐系统:
- 基于用户行为的协同过滤(简单版)
sql复制-- 获取相似用户喜欢的商品 SELECT item_id FROM user_behavior WHERE user_id IN ( SELECT similar_user FROM user_similarity WHERE user_id=123 ORDER BY score DESC LIMIT 5 ) -
数据大屏:
- ECharts展示销售数据
- WebSocket实时更新
我在实际开发中发现,很多同学在文件上传功能上容易踩坑。建议使用阿里云OSS等云存储服务,比本地存储更可靠:
java复制// OSS上传示例
public String uploadToOss(MultipartFile file) {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey);
try {
String fileName = "images/" + UUID.randomUUID() + ".jpg";
ossClient.putObject(bucketName, fileName, file.getInputStream());
return "https://" + bucketName + "." + endpoint + "/" + fileName;
} finally {
ossClient.shutdown();
}
}