掌握基础增删改查(CRUD)只是 Java 开发的起点,要真正吃透这门技术栈,必须深入业务场景,通过实际项目来磨练架构思维。本文将围绕“电商”与“支付”这两个强关联的核心系统,从技术选型、架构设计到核心代码实现,带你一步步完成从初级开发向架构设计的进阶。 一、 项目背景与技术选型 在实际企业开发中,电商系统与支付系统通常既是协同工作的,又是物理隔离的。电商系统负责商品展示、订单生成;支付系统负责资金流水、渠道对接。 核心技术栈:
后端框架:Spring Boot 3.x + Spring MVC 数据访问:MyBatis-Plus + Druid 连接池 数据库:MySQL 8.0 (主从架构模拟) 缓存中间件:Redis (分布式缓存、分布式锁) 消息队列:RabbitMQ (异步解耦、流量削峰) 服务治理:Nacos (注册中心、配置中心) RPC 调用:OpenFeign
二、 电商订单系统:构建高并发交易基石 电商系统的核心在于处理高并发下的订单一致性。这里我们通过“Redis 预扣库存 + MQ 异步下单”的模式来提升吞吐量。
- 数据库设计
sql
复制
sql 体验AI代码助手 代码解读复制代码-- 商品表
CREATE TABLE
product(idbigint NOT NULL AUTO_INCREMENT,namevarchar(100) NOT NULL COMMENT '商品名称',stockint NOT NULL DEFAULT '0' COMMENT '库存',pricedecimal(10,2) NOT NULL COMMENT '单价', PRIMARY KEY (id) );
-- 订单表
CREATE TABLE order_info (
id bigint NOT NULL AUTO_INCREMENT,
order_no varchar(64) NOT NULL COMMENT '订单号',
product_id bigint NOT NULL COMMENT '商品ID',
user_id bigint NOT NULL COMMENT '用户ID',
amount decimal(10,2) NOT NULL COMMENT '订单金额',
status tinyint NOT NULL DEFAULT '0' COMMENT '状态:0-待支付,1-已支付',
create_time datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_order_no (order_no)
);
Redis 预扣库存逻辑(Lua 脚本保证原子性) 为了防止超卖,不能直接查库扣减,必须利用 Redis 的单线程特性。 java 复制 vbnet 体验AI代码助手 代码解读复制代码@Service @RequiredArgsConstructor public class StockService {
private final RedisTemplate<String, Object> redisTemplate;
// Lua 脚本:检查库存并扣减 private static final String STOCK_LUA_SCRIPT =
"if tonumber(redis.call('get', KEYS[1])) >= tonumber(ARGV[1]) then " + " return redis.call('decrby', KEYS[1], ARGV[1]); " + "else " + " return -1; " + "end";public boolean deductStock(Long productId, Integer quantity) {
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(STOCK_LUA_SCRIPT, Long.class); String key = "product:stock:" + productId; Long result = redisTemplate.execute(redisScript, Collections.singletonList(key), quantity); return result != null && result >= 0;} }
下单与消息发送 库存扣减成功后,发送消息到 MQ,由消费者异步落库。 java 复制 kotlin 体验AI代码助手 代码解读复制代码@Service @RequiredArgsConstructor public class OrderService {
private final RabbitTemplate rabbitTemplate;
@Transactional(rollbackFor = Exception.class) public String createOrder(Long productId, Integer quantity, Long userId) {
// 1. 生成订单号 String orderNo = UUID.randomUUID().toString().replace("-", ""); // 2. 封装消息对象 OrderDTO orderDTO = OrderDTO.builder() .orderNo(orderNo) .productId(productId) .userId(userId) .quantity(quantity) .build(); // 3. 发送消息到订单交换机 rabbitTemplate.convertAndSend("order.exchange", "order.routing.key", orderDTO); return orderNo;} }
java 复制 less 体验AI代码助手 代码解读复制代码@Component @RabbitListener(queues = "order.queue") @RequiredArgsConstructor public class OrderConsumer {
private final OrderMapper orderMapper;
private final ProductMapper productMapper;
@RabbitHandler
public void handleOrder(OrderDTO orderDTO) {
try {
// 幂等性校验:检查订单是否已存在
OrderInfo existingOrder = orderMapper.selectByOrderNo(orderDTO.getOrderNo());
if (existingOrder != null) {
return; // 避免重复消费
}
// 查询商品价格(实际场景会走缓存)
Product product = productMapper.selectById(orderDTO.getProductId());
// 构建订单实体
OrderInfo order = OrderInfo.builder()
.orderNo(orderDTO.getOrderNo())
.productId(orderDTO.getProductId())
.userId(orderDTO.getUserId())
.amount(product.getPrice().multiply(new BigDecimal(orderDTO.getQuantity())))
.status(0) // 待支付
.build();
orderMapper.insert(order);
// TODO: 可以在这里触发“支付超时自动取消”的延时消息
} catch (Exception e) {
// 实际场景需要记录死信队列或人工介入
throw new RuntimeException("订单入库失败");
}
}}
三、 支付系统:核心架构设计 支付系统要求极高的稳定性与数据一致性。我们采用“策略模式”对接不同支付渠道(支付宝、微信),并使用“状态机”管理支付状态。
支付核心接口设计 java 复制 typescript 体验AI代码助手 代码解读复制代码// 支付渠道策略接口 public interface PaymentStrategy {
/**
统一下单接口
/ PaymentResult unifiedOrder(PaymentRequest request);
/**
支付回调处理
/ Boolean handleCallback(Map<String, String> params); }
// 支付宝实现 @Component("aliPayStrategy") public class AliPayStrategy implements PaymentStrategy {
@Override
public PaymentResult unifiedOrder(PaymentRequest request) {
// 模拟调用支付宝 SDK
System.out.println("调用支付宝 API,订单号:" + request.getOrderNo());
return PaymentResult.builder()
.payUrl("https://openapi.alipay.com/..." + request.getOrderNo())
.build();
}
@Override
public Boolean handleCallback(Map<String, String> params) {
// 1. 验签(必须)
// 2. 校验金额与订单号
// 3. 执行业务逻辑
return true;
}}
支付上下文与工厂模式 根据前端传来的渠道类型,动态选择具体的支付实现。 java 复制 typescript 体验AI代码助手 代码解读复制代码@Service @RequiredArgsConstructor public class PaymentContext {
private final Map<String, PaymentStrategy> strategyMap;
/**
- 发起支付
- /
public PaymentResult executePayment(PaymentRequest request) {
PaymentStrategy strategy = strategyMap.get(request.getChannel() + "PayStrategy");
if (strategy == null) {
} return strategy.unifiedOrder(request); } }throw new IllegalArgumentException("不支持的支付渠道");
支付回调与分布式事务处理 这是最关键的一步。支付系统收到成功回调后,需要更新自身状态,并通知电商系统更新订单状态。这里使用 Seata 或简单的消息队列实现最终一致性。 java 复制 less 体验AI代码助手 代码解读复制代码@RestController @RequestMapping("/api/payment") @RequiredArgsConstructor public class PaymentCallbackController {
private final PaymentService paymentService; private final OrderFeignClient orderFeignClient; // 调用电商系统接口
@PostMapping("/callback/ali") public String aliCallback(@RequestBody Map<String, String> params) {
// 1. 校验签名与金额 if (!paymentService.verifyAliPay(params)) { return "fail"; } String tradeNo = params.get("out_trade_no"); // 商户订单号 // 2. 更新支付流水状态(加分布式锁防止并发回调) PaymentRecord record = paymentService.updatePaymentStatus(tradeNo, "SUCCESS"); if (record != null && "SUCCESS".equals(record.getStatus())) { // 3. 通知电商系统:支付成功 // 为了保证高可用,通常这里结合本地消息表做重试 try { orderFeignClient.updateOrderStatus(record.getOrderNo(), 1); } catch (Exception e) { // 记录日志,通过补偿任务重试 log.error("通知电商系统失败", e); } } return "success";} }
四、 架构设计要点总结 在从单体应用向微服务演进的过程中,这两个系统的实战经验至关重要:
高并发处理:电商侧通过 Redis 预扣库存 + MQ 异步解耦,将流量冲击挡在数据库之外。 分布式事务:支付与订单属于两个不同的数据库,不能使用本地事务。实战中推荐使用 MQ 最终一致性方案(如本例),或者在强一致性要求场景下使用 Seata AT 模式。 系统解耦:支付系统不应强依赖于电商系统。回调通知失败时,支付系统应有重试机制;电商系统也应提供主动查询支付状态的接口。 策略模式:支付渠道多变,策略模式能有效隔离代码,新增渠道只需新增实现类,符合开闭原则。
通过以上实战代码,你可以看到 Java 技术栈在处理复杂业务逻辑时的强大能力。真正的架构师不仅仅是会写代码,更是在业务与技术之间寻找最平衡的解决方案。
https://infogram.com/9862pdf-1h1749wqm57vq2z https://infogram.com/9862pdf-1hnp27eqy81zy4g https://infogram.com/9862pdf-1h9j6q75k18e54g https://infogram.com/9862pdf-1hnp27eqy81ln4g https://infogram.com/9862pdf-1h1749wqm58wq2z https://infogram.com/9862pdf-1h7v4pd08zkjj4k https://infogram.com/9862pdf-1hmr6g8jzq9mz2n https://infogram.com/9862pdf-1h9j6q75k1w954g https://infogram.com/9862pdf-1hnq41opzv1dk23 https://infogram.com/9862pdf-1hxj48mqek8kq2v
