本文目录导读:

我将为您创建一个基于COLA(Clean Object-oriented and Layered Architecture)架构的电商订单系统完整案例。
项目结构
cola-order-system
├── pom.xml
├── start
│ └── src/main/java/com/example/start
│ └── Application.java
├── adapter
│ ├── web
│ │ └── src/main/java/com/example/adapter/web
│ │ ├── controller/OrderController.java
│ │ └── common/Response.java
│ └── repository
│ └── src/main/java/com/example/adapter/repository
│ ├── OrderRepositoryImpl.java
│ └── assembler/OrderAssembler.java
├── app
│ └── src/main/java/com/example/app
│ ├── executor/OrderCreateCmdExe.java
│ ├── executor/OrderQueryExe.java
│ ├── service/OrderService.java
│ └── assembler/OrderDTOAssembler.java
├── domain
│ └── src/main/java/com/example/domain
│ ├── order/Order.java
│ ├── order/OrderItem.java
│ ├── order/OrderStatus.java
│ ├── order/OrderFactory.java
│ ├── gateway/OrderGateway.java
│ └── service/OrderDomainService.java
├── infrastructure
│ └── src/main/java/com/example/infrastructure
│ ├── config/MybatisConfig.java
│ ├── convertor/OrderConvertor.java
│ ├── mapper/OrderMapper.java
│ └── dataobject/OrderDO.java
└── client
└── src/main/java/com/example/client
├── dto/OrderDTO.java
├── dto/OrderItemDTO.java
├── dto/command/OrderCreateCommand.java
├── dto/query/OrderQuery.java
└── api/OrderServiceI.java
核心代码实现
1 Client模块 (API层)
// OrderServiceI.java
package com.example.client.api;
import com.example.client.dto.OrderDTO;
import com.example.client.dto.command.OrderCreateCommand;
import com.example.client.dto.query.OrderQuery;
public interface OrderServiceI {
String createOrder(OrderCreateCommand command);
OrderDTO getOrder(OrderQuery query);
}
// OrderCreateCommand.java
package com.example.client.dto.command;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class OrderCreateCommand {
@NotNull(message = "用户ID不能为空")
private Long userId;
@NotNull(message = "订单项不能为空")
private List<OrderItemCommand> orderItems;
private String couponCode;
private String address;
@Data
public static class OrderItemCommand {
@NotNull(message = "商品ID不能为空")
private Long productId;
@NotNull(message = "商品数量不能为空")
private Integer quantity;
private BigDecimal price;
}
}
// OrderDTO.java
package com.example.client.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Data
public class OrderDTO {
private String orderId;
private Long userId;
private BigDecimal totalAmount;
private BigDecimal discountAmount;
private BigDecimal payAmount;
private String status;
private Date createTime;
private List<OrderItemDTO> orderItems;
}
2 Domain模块 (领域层)
// Order.java
package com.example.domain.order;
import lombok.Getter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@Getter
public class Order {
private String orderId;
private Long userId;
private BigDecimal totalAmount;
private BigDecimal discountAmount;
private BigDecimal payAmount;
private OrderStatus status;
private List<OrderItem> orderItems;
public Order() {
this.orderId = UUID.randomUUID().toString().replace("-", "");
this.status = OrderStatus.CREATED;
this.orderItems = new ArrayList<>();
this.totalAmount = BigDecimal.ZERO;
this.discountAmount = BigDecimal.ZERO;
}
public void addItem(Long productId, Integer quantity, BigDecimal price) {
OrderItem item = new OrderItem(productId, quantity, price);
this.orderItems.add(item);
this.totalAmount = this.totalAmount.add(item.getTotalPrice());
}
public void applyDiscount(BigDecimal discount) {
if (discount.compareTo(this.totalAmount) > 0) {
throw new IllegalArgumentException("折扣金额不能超过订单总额");
}
this.discountAmount = discount;
this.payAmount = this.totalAmount.subtract(discount);
}
public void confirm() {
if (this.status != OrderStatus.CREATED) {
throw new IllegalStateException("订单状态不允许确认");
}
this.status = OrderStatus.CONFIRMED;
}
public void cancel() {
if (this.status == OrderStatus.COMPLETED) {
throw new IllegalStateException("已完成订单不能取消");
}
this.status = OrderStatus.CANCELLED;
}
public void complete() {
if (this.status != OrderStatus.CONFIRMED) {
throw new IllegalStateException("订单未确认不能完成");
}
this.status = OrderStatus.COMPLETED;
}
}
// OrderFactory.java
package com.example.domain.order;
import com.example.domain.gateway.OrderGateway;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class OrderFactory {
@Autowired
private OrderGateway orderGateway;
public Order createOrder(Long userId) {
Order order = new Order();
order.initUser(userId);
return order;
}
public Order getOrder(String orderId) {
return orderGateway.findByOrderId(orderId);
}
}
// OrderDomainService.java
package com.example.domain.service;
import com.example.domain.order.Order;
import com.example.domain.gateway.OrderGateway;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
@Service
public class OrderDomainService {
@Autowired
private OrderGateway orderGateway;
public void createOrder(Order order) {
orderGateway.save(order);
}
public void cancelOrder(String orderId, String operator) {
Order order = orderGateway.findByOrderId(orderId);
if (order == null) {
throw new IllegalArgumentException("订单不存在");
}
order.cancel();
orderGateway.save(order);
}
public BigDecimal calculateDiscount(Order order, String couponCode) {
// 简单折扣逻辑:优惠码折扣10%
if ("SAVE10".equals(couponCode)) {
return order.getTotalAmount().multiply(new BigDecimal("0.1"));
}
return BigDecimal.ZERO;
}
}
3 App模块 (应用层)
// OrderService.java
package com.example.app.service;
import com.example.client.api.OrderServiceI;
import com.example.client.dto.OrderDTO;
import com.example.client.dto.command.OrderCreateCommand;
import com.example.client.dto.query.OrderQuery;
import com.example.app.executor.OrderCreateCmdExe;
import com.example.app.executor.OrderQueryExe;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderService implements OrderServiceI {
@Autowired
private OrderCreateCmdExe orderCreateCmdExe;
@Autowired
private OrderQueryExe orderQueryExe;
@Override
public String createOrder(OrderCreateCommand command) {
return orderCreateCmdExe.execute(command);
}
@Override
public OrderDTO getOrder(OrderQuery query) {
return orderQueryExe.execute(query);
}
}
// OrderCreateCmdExe.java
package com.example.app.executor;
import com.example.client.dto.command.OrderCreateCommand;
import com.example.domain.order.Order;
import com.example.domain.order.OrderFactory;
import com.example.domain.service.OrderDomainService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
public class OrderCreateCmdExe {
@Autowired
private OrderFactory orderFactory;
@Autowired
private OrderDomainService orderDomainService;
@Transactional
public String execute(OrderCreateCommand command) {
// 1. 创建订单实体
Order order = orderFactory.createOrder(command.getUserId());
// 2. 添加订单项
command.getOrderItems().forEach(item ->
order.addItem(item.getProductId(), item.getQuantity(), item.getPrice())
);
// 3. 计算折扣
if (command.getCouponCode() != null) {
BigDecimal discount = orderDomainService.calculateDiscount(order, command.getCouponCode());
order.applyDiscount(discount);
}
// 4. 保存订单
orderDomainService.createOrder(order);
return order.getOrderId();
}
}
4 Adapter模块 (适配层)
// OrderController.java
package com.example.adapter.web.controller;
import com.example.client.api.OrderServiceI;
import com.example.client.dto.OrderDTO;
import com.example.client.dto.command.OrderCreateCommand;
import com.example.client.dto.query.OrderQuery;
import com.example.adapter.web.common.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private OrderServiceI orderService;
@PostMapping
public Response<String> createOrder(@RequestBody OrderCreateCommand command) {
String orderId = orderService.createOrder(command);
return Response.success(orderId);
}
@GetMapping("/{orderId}")
public Response<OrderDTO> getOrder(@PathVariable String orderId) {
OrderQuery query = new OrderQuery();
query.setOrderId(orderId);
OrderDTO order = orderService.getOrder(query);
return Response.success(order);
}
}
// OrderRepositoryImpl.java
package com.example.adapter.repository;
import com.example.domain.gateway.OrderGateway;
import com.example.domain.order.Order;
import com.example.adapter.repository.assembler.OrderAssembler;
import com.example.infrastructure.convertor.OrderConvertor;
import com.example.infrastructure.mapper.OrderMapper;
import com.example.infrastructure.dataobject.OrderDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class OrderRepositoryImpl implements OrderGateway {
@Autowired
private OrderMapper orderMapper;
@Override
public void save(Order order) {
OrderDO orderDO = OrderConvertor.toDataObject(order);
orderMapper.insert(orderDO);
}
@Override
public Order findByOrderId(String orderId) {
OrderDO orderDO = orderMapper.findByOrderId(orderId);
return OrderAssembler.toEntity(orderDO);
}
@Override
public void update(Order order) {
OrderDO orderDO = OrderConvertor.toDataObject(order);
orderMapper.update(orderDO);
}
}
5 Infrastructure模块 (基础设施层)
// OrderMapper.java
package com.example.infrastructure.mapper;
import com.example.infrastructure.dataobject.OrderDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface OrderMapper {
int insert(OrderDO orderDO);
OrderDO findByOrderId(@Param("orderId") String orderId);
int update(OrderDO orderDO);
}
// OrderConvertor.java
package com.example.infrastructure.convertor;
import com.example.domain.order.Order;
import com.example.domain.order.OrderItem;
import com.example.infrastructure.dataobject.OrderDO;
public class OrderConvertor {
public static OrderDO toDataObject(Order order) {
if (order == null) {
return null;
}
OrderDO orderDO = new OrderDO();
orderDO.setOrderId(order.getOrderId());
orderDO.setUserId(order.getUserId());
orderDO.setTotalAmount(order.getTotalAmount());
orderDO.setDiscountAmount(order.getDiscountAmount());
orderDO.setPayAmount(order.getPayAmount());
orderDO.setStatus(order.getStatus().getCode());
return orderDO;
}
}
配置文件
<!-- pom.xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>cola-order-system</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>start</module>
<module>adapter</module>
<module>app</module>
<module>domain</module>
<module>infrastructure</module>
<module>client</module>
</modules>
</project>
# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/order_db
username: root
password: root
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.infrastructure.dataobject
server:
port: 8080
核心特性说明
1 依赖方向
- 外层依赖内层,内层不依赖外层
- 领域层完全不依赖任何框架
- 通过接口(Interface)实现依赖倒置
2 模块职责
- Client层:定义API接口和DTO
- App层:用例编排、事务管理、日志
- Domain层:核心业务逻辑、领域模型
- Infrastructure层:技术实现细节
- Adapter层:接口适配、数据转换
3 关键设计原则
// 1. 依赖倒置
public interface OrderGateway {
void save(Order order);
Order findByOrderId(String orderId);
}
// 2. 聚合根设计
@Getter
public class Order {
private String orderId;
private List<OrderItem> items;
public void addItem(OrderItem item) {
// 业务规则校验
this.items.add(item);
this.totalAmount = calculateTotalAmount();
}
}
// 3. 领域服务
@Service
public class OrderDomainService {
// 跨聚合的业务逻辑
}
这个案例展示了COLA架构的核心思想和实践方式,通过分层架构实现了业务与技术细节的解耦,使得系统更加清晰、可维护和可扩展。