【每特教育】基于SpringCloud构建微服务电商项目 – 带源码课件

77 阅读5分钟

基于SpringCloud构建微服务电商平台实战指南

一、项目架构设计

1. 微服务拆分方案

电商平台通常按照业务功能划分为以下核心服务:

├── 用户服务(user-service)          # 用户注册/登录/权限管理
├── 商品服务(product-service)       # 商品管理/类目管理
├── 订单服务(order-service)         # 订单创建/状态流转
├── 支付服务(payment-service)       # 支付渠道对接
├── 库存服务(inventory-service)     # 库存管理
├── 搜索服务(search-service)        # 商品搜索
├── 推荐服务(recommend-service)     # 个性化推荐
└── 网关服务(gateway)               # 统一API入口

2. 技术栈选型

spring-cloud: 2022.0.4
spring-cloud-alibaba: 2022.0.0.0
spring-boot: 3.1.0
java: 17
nacos: 2.2.3        # 服务注册与配置中心
sentinel: 1.8.6     # 流量控制与熔断降级
seata: 1.7.1        # 分布式事务
redis: 7.0          # 缓存与分布式锁
rabbitmq: 3.11      # 异步消息处理
elasticsearch: 8.7  # 商品搜索

二、核心服务实现

1. 商品服务实现

// 商品领域模型
@Entity
@Table(name = "product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private String name;
    
    @Column(nullable = false)
    private BigDecimal price;
    
    @Column(name = "category_id")
    private Long categoryId;
    
    @Column(columnDefinition = "TEXT")
    private String description;
    
    @Column(name = "stock_count")
    private Integer stockCount;
    
    // Getters & Setters...
}

// 商品服务接口
@RestController
@RequestMapping("/products")
@RequiredArgsConstructor
public class ProductController {
    private final ProductService productService;
    
    @GetMapping("/{id}")
    public Result<Product> getProduct(@PathVariable Long id) {
        return Result.success(productService.getById(id));
    }
    
    @PostMapping
    public Result<Long> createProduct(@Valid @RequestBody ProductCreateDTO dto) {
        return Result.success(productService.createProduct(dto));
    }
    
    @GetMapping("/search")
    public Result<PageResult<Product>> searchProducts(
            @RequestParam String keyword,
            @RequestParam(defaultValue = "0") Integer page,
            @RequestParam(defaultValue = "10") Integer size) {
        return Result.success(productService.search(keyword, page, size));
    }
}

2. 订单服务分布式事务

// 订单创建服务(使用Seata)
@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
    private final OrderMapper orderMapper;
    private final InventoryClient inventoryClient;
    private final ProductClient productClient;
    
    @GlobalTransactional // 开启全局事务
    @Override
    public Long createOrder(OrderCreateDTO dto) {
        // 1. 验证商品信息
        Product product = productClient.getProduct(dto.getProductId());
        if (product == null) {
            throw new BusinessException("商品不存在");
        }
        
        // 2. 扣减库存
        inventoryClient.deductStock(dto.getProductId(), dto.getQuantity());
        
        // 3. 创建订单
        Order order = new Order();
        order.setUserId(dto.getUserId());
        order.setProductId(dto.getProductId());
        order.setQuantity(dto.getQuantity());
        order.setTotalAmount(product.getPrice().multiply(
            BigDecimal.valueOf(dto.getQuantity())));
        order.setStatus(OrderStatus.CREATED);
        orderMapper.insert(order);
        
        // 4. 发送订单创建事件
        sendOrderCreatedEvent(order);
        
        return order.getId();
    }
    
    private void sendOrderCreatedEvent(Order order) {
        // 消息队列实现...
    }
}

三、服务通信设计

1. OpenFeign声明式调用

// 库存服务Feign客户端
@FeignClient(name = "inventory-service", path = "/inventories")
public interface InventoryClient {
    @PostMapping("/deduct")
    Result<Void> deductStock(
        @RequestParam Long productId, 
        @RequestParam Integer quantity);
    
    @PostMapping("/increase")
    Result<Void> increaseStock(
        @RequestParam Long productId, 
        @RequestParam Integer quantity);
}

// 自定义Feign配置
@Configuration
public class FeignConfig {
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
    
    @Bean
    public Retryer feignRetryer() {
        return new Retryer.Default(100, 1000, 3);
    }
}

2. 消息队列异步处理

// 订单支付成功消息处理
@Component
@RequiredArgsConstructor
@RabbitListener(queues = "order.payment.success.queue")
public class OrderPaymentSuccessListener {
    private final OrderService orderService;
    private final InventoryService inventoryService;
    
    @RabbitHandler
    public void handlePaymentSuccess(PaymentSuccessMessage message) {
        // 1. 更新订单状态
        orderService.updateStatus(message.getOrderId(), OrderStatus.PAID);
        
        // 2. 扣减真实库存(预扣库存已在创建订单时完成)
        inventoryService.confirmDeduction(message.getOrderId());
        
        // 3. 发送订单支付成功通知
        sendPaymentSuccessNotification(message);
    }
}

四、关键业务逻辑实现

1. 购物车实现方案

// Redis购物车服务
@Service
@RequiredArgsConstructor
public class CartServiceImpl implements CartService {
    private final RedisTemplate<String, Object> redisTemplate;
    private final ProductClient productClient;
    
    private String getCartKey(Long userId) {
        return "cart:" + userId;
    }
    
    @Override
    public void addItem(Long userId, CartItemDTO item) {
        // 验证商品信息
        Product product = productClient.getProduct(item.getProductId());
        if (product == null) {
            throw new BusinessException("商品不存在");
        }
        
        // 存储购物车项
        redisTemplate.opsForHash().put(
            getCartKey(userId),
            item.getProductId().toString(),
            item
        );
    }
    
    @Override
    public List<CartItemDTO> getCart(Long userId) {
        List<Object> items = redisTemplate.opsForHash().values(getCartKey(userId));
        return items.stream()
            .map(item -> (CartItemDTO) item)
            .collect(Collectors.toList());
    }
}

2. 分布式锁实现秒杀

// 秒杀服务实现
@Service
@RequiredArgsConstructor
public class SeckillServiceImpl implements SeckillService {
    private final RedissonClient redissonClient;
    private final ProductService productService;
    private final OrderService orderService;
    
    @Override
    public SeckillResult seckill(Long userId, Long seckillId) {
        // 获取分布式锁
        RLock lock = redissonClient.getLock("seckill:lock:" + seckillId);
        
        try {
            // 尝试加锁,最多等待100ms,锁有效期10s
            if (lock.tryLock(100, 10000, TimeUnit.MILLISECONDS)) {
                // 1. 检查库存
                Product product = productService.getSeckillProduct(seckillId);
                if (product.getStock() <= 0) {
                    return SeckillResult.soldOut();
                }
                
                // 2. 检查是否已购买
                if (orderService.hasPurchased(userId, seckillId)) {
                    return SeckillResult.repeatPurchase();
                }
                
                // 3. 创建秒杀订单
                Long orderId = orderService.createSeckillOrder(userId, seckillId);
                return SeckillResult.success(orderId);
            }
            return SeckillResult.retryLater();
        } finally {
            lock.unlock();
        }
    }
}

五、平台安全设计

1. JWT认证实现

// JWT工具类
@Component
public class JwtTokenProvider {
    @Value("${jwt.secret}")
    private String secret;
    
    @Value("${jwt.expiration}")
    private long expiration;
    
    public String generateToken(UserDetails userDetails) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + expiration);
        
        return Jwts.builder()
            .setSubject(userDetails.getUsername())
            .setIssuedAt(now)
            .setExpiration(expiryDate)
            .signWith(SignatureAlgorithm.HS512, secret)
            .compact();
    }
    
    public String getUsernameFromToken(String token) {
        return Jwts.parser()
            .setSigningKey(secret)
            .parseClaimsJws(token)
            .getBody()
            .getSubject();
    }
    
    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
            return true;
        } catch (Exception ex) {
            return false;
        }
    }
}

// 认证过滤器
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private final JwtTokenProvider tokenProvider;
    private final UserDetailsService userDetailsService;
    
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                  HttpServletResponse response,
                                  FilterChain filterChain) throws ServletException, IOException {
        String token = getJwtFromRequest(request);
        
        if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
            String username = tokenProvider.getUsernameFromToken(token);
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            UsernamePasswordAuthenticationToken authentication = 
                new UsernamePasswordAuthenticationToken(
                    userDetails, null, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        
        filterChain.doFilter(request, response);
    }
    
    private String getJwtFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

六、性能优化实践

1. 多级缓存设计

// 商品详情缓存服务
@Service
@RequiredArgsConstructor
public class ProductCacheServiceImpl implements ProductCacheService {
    private final ProductMapper productMapper;
    private final RedisTemplate<String, Object> redisTemplate;
    private final CaffeineCache localCache;
    
    private static final String REDIS_KEY_PREFIX = "product:";
    
    @Cacheable(value = "products", key = "#id") // 本地缓存
    @Override
    public Product getProductById(Long id) {
        // 1. 查Redis
        String redisKey = REDIS_KEY_PREFIX + id;
        Product product = (Product) redisTemplate.opsForValue().get(redisKey);
        
        if (product == null) {
            // 2. 查数据库
            product = productMapper.selectById(id);
            if (product != null) {
                // 3. 写Redis
                redisTemplate.opsForValue().set(
                    redisKey, 
                    product, 
                    30, TimeUnit.MINUTES);
            }
        }
        
        return product;
    }
}

2. 接口限流配置

// Sentinel限流配置
@Configuration
public class SentinelConfig {
    @PostConstruct
    public void init() {
        // 商品查询接口限流
        FlowRule rule1 = new FlowRule();
        rule1.setResource("GET:/api/products/{id}");
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setCount(100); // 每秒100次
        
        // 订单创建接口限流
        FlowRule rule2 = new FlowRule();
        rule2.setResource("POST:/api/orders");
        rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule2.setCount(50); // 每秒50次
        
        FlowRuleManager.loadRules(Arrays.asList(rule1, rule2));
    }
}

// 网关层限流
@Configuration
public class GatewayConfig {
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
}

七、项目部署方案

1. Docker Compose部署

version: '3.8'

services:
  nacos:
    image: nacos/nacos-server:2.2.3
    ports:
      - "8848:8848"
    environment:
      - MODE=standalone
      
  redis:
    image: redis:7.0
    ports:
      - "6379:6379"
    
  rabbitmq:
    image: rabbitmq:3.11-management
    ports:
      - "5672:5672"
      - "15672:15672"
    
  user-service:
    build: ./user-service
    ports:
      - "8081:8080"
    depends_on:
      - nacos
      - redis
  
  product-service:
    build: ./product-service
    ports:
      - "8082:8080"
    depends_on:
      - nacos
      - redis
      - rabbitmq

2. Kubernetes部署文件

# product-service部署示例
apiVersion: apps/v1
kind: Deployment
metadata:
  name: product-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: product-service
  template:
    metadata:
      labels:
        app: product-service
    spec:
      containers:
      - name: product
        image: registry.example.com/ecommerce/product-service:1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: prod
        resources:
          limits:
            cpu: "2"
            memory: 2Gi
---
apiVersion: v1
kind: Service
metadata:
  name: product-service
spec:
  selector:
    app: product-service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

通过本项目的实践,开发者可以全面掌握基于SpringCloud的微服务架构设计与实现,构建高可用、高性能的电商平台。课程强调生产级代码规范与最佳实践,帮助学员从零开始搭建完整的分布式系统,为应对复杂业务场景打下坚实基础。