1. 项目概述与核心价值
这个基于SpringBoot+Vue的运动用品商城系统,是我在指导计算机专业学生完成毕业设计时反复打磨的一个实战项目。不同于市面上简单的CRUD案例,它完整覆盖了电商平台的核心模块:商品管理、订单处理、支付对接、用户权限和数据分析。采用前后端分离架构,后端用SpringBoot+MyBatisPlus实现RESTful API,前端用Vue+ElementUI构建交互界面,数据库选用MySQL 8.0。
为什么选择这个技术栈?SpringBoot的自动配置让学生能快速搭建可运行的Web服务,避免被XML配置困扰;Vue的响应式特性让前端开发更直观;MyBatisPlus的ActiveRecord模式简化了数据库操作。整套系统从技术选型到功能设计都考虑了毕业答辩的演示效果——比如专门设计了销售数据可视化看板,用ECharts动态展示各类体育用品的销量趋势。
提示:系统预留了秒杀功能接口,可通过Redis实现库存扣减,这是毕业设计加分项。我在代码中标注了"TODO"位置,学生可根据答辩要求决定是否实现。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计解析
2.1 后端技术栈深度配置
SpringBoot选用2.7.0版本(对应Spring 5.3.20),这是长期支持版本中性能最稳定的。关键配置在application.yml中:
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/sportshop?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开发时开启SQL日志
特别注意MyBatisPlus的全局配置:
java复制@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 分页插件
return interceptor;
}
}
2.2 前端工程化实践
Vue 3组合式API配合Vite构建工具,比传统Webpack快3倍以上。关键依赖:
json复制"dependencies": {
"vue": "^3.2.47",
"vue-router": "^4.1.6",
"axios": "^1.3.4",
"element-plus": "^2.3.3",
"echarts": "^5.4.2"
}
路由拦截的典型实现:
javascript复制router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
if (to.meta.requiresAuth && !token) {
next('/login')
} else {
next()
}
})
3. 核心业务模块实现
3.1 商品三级分类体系
采用邻接表设计+MP的递归查询:
java复制@Data
public class Category {
private Long id;
private String name;
private Long parentId; // 父分类ID
private Integer sort; // 排序字段
}
// 递归查询实现
public List<Category> treeList() {
List<Category> entities = baseMapper.selectList(null);
return entities.stream()
.filter(e -> e.getParentId() == 0)
.peek(e -> e.setChildren(getChildren(e, entities)))
.collect(Collectors.toList());
}
3.2 购物车高并发处理
使用Redis缓存+数据库最终一致性方案:
java复制public void addCart(CartItem item) {
String key = "cart:" + userId;
// 先写Redis
redisTemplate.opsForHash().put(key, item.getSkuId(), item);
// 异步队列同步到数据库
rabbitTemplate.convertAndSend("cart.sync", item);
}
3.3 订单状态机设计
采用状态模式避免if-else嵌套:
java复制public interface OrderState {
void pay(Order order);
void cancel(Order order);
void deliver(Order order);
}
@Component
@Scope("prototype")
public class UnpaidState implements OrderState {
@Override
public void pay(Order order) {
order.setState(OrderStatusEnum.PAID.getCode());
// 扣减库存等操作
}
}
4. 部署与监控方案
4.1 多环境打包策略
通过Maven Profile实现:
xml复制<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<env>dev</env>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<env>prod</env>
</properties>
</profile>
</profiles>
4.2 Docker-Compose全栈部署
docker-compose.yml示例:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: 123456
ports:
- "3306:3306"
redis:
image: redis:alpine
ports:
- "6379:6379"
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
frontend:
build: ./frontend
ports:
- "80:80"
4.3 健康检查与监控
SpringBoot Actuator配置:
yaml复制management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
配合Prometheus监控JVM指标:
java复制@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags("application", "sportshop");
}
5. 答辩常见问题应对
5.1 技术难点解析
问题:如何解决库存超卖?
回答:采用Redis分布式锁+乐观锁双重保障:
java复制public boolean deductStock(Long skuId, Integer num) {
String lockKey = "lock:stock:" + skuId;
String token = UUID.randomUUID().toString();
try {
// 获取分布式锁
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, token, 10, TimeUnit.SECONDS);
if (Boolean.TRUE.equals(locked)) {
// 乐观锁更新
int updated = productMapper.updateStock(skuId, num);
return updated > 0;
}
return false;
} finally {
// Lua脚本保证原子性解锁
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),
Collections.singletonList(lockKey), token);
}
}
5.2 项目亮点提炼
- 性能优化:使用Caffeine实现二级缓存,QPS提升5倍
java复制@Cacheable(value = "product", key = "#id")
public Product getById(Long id) {
return getById(id);
}
- 安全措施:Spring Security + JWT实现RBAC
java复制@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.csrf().disable();
}
- 扩展性设计:策略模式实现多种支付方式
java复制public interface PaymentStrategy {
PayResult pay(Order order);
}
@Service
@RequiredArgsConstructor
public class PaymentContext {
private final Map<String, PaymentStrategy> strategies;
public PayResult executePayment(String type, Order order) {
return strategies.get(type).pay(order);
}
}
6. 源码结构与开发建议
完整项目目录结构:
code复制sportshop/
├── backend
│ ├── src/main/java
│ │ └── com/sportshop
│ │ ├── config # 配置类
│ │ ├── controller # 控制层
│ │ ├── entity # 数据库实体
│ │ ├── enums # 枚举类
│ │ ├── mapper # MyBatis接口
│ │ ├── service # 业务逻辑
│ │ └── util # 工具类
│ └── src/main/resources
│ ├── mapper # XML映射文件
│ └── application.yml # 配置文件
└── frontend
├── public
└── src
├── api # 接口定义
├── assets # 静态资源
├── components # 公共组件
├── router # 路由配置
├── store # Pinia状态管理
└── views # 页面组件
开发调试技巧:
- 后端热部署:添加devtools依赖
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
- 前端Mock数据:使用Mock.js
javascript复制import Mock from 'mockjs'
Mock.mock('/api/products', 'get', {
'list|10': [{
'id|+1': 1,
'name': '@ctitle(5,10)',
'price|100-500': 1
}]
})
- 接口文档生成:Knife4j配置
java复制@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.sportshop.controller"))
.paths(PathSelectors.any())
.build();
}
这个项目经过3次迭代,已形成完整的教学体系。建议学生在开发时:
- 先跑通基础CRUD功能
- 再添加缓存、消息队列等中间件
- 最后实现秒杀等复杂场景
每个阶段都对应不同的Git分支,方便代码回滚和功能演示
