You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Clean Architecture与Mediator模式的Mass Transit逻辑位置咨询

业务逻辑该放在Consumers还是Application层Handlers?

核心原则要先明确:Clean Architecture的核心是依赖倒置,核心业务逻辑必须放在内层(Application/Domain),而Consumers属于消息适配层,只做消息的接收与转发,不承载核心业务逻辑。

下面结合你的项目结构给出具体建议:

1. 优先将业务逻辑放在Application层的Handlers里

Application层本身就是处理业务用例的核心层,不管触发逻辑的是WebApi的请求,还是消息队列的事件,核心业务逻辑都应该复用同一份实现。这样做的好处:

  • 避免重复代码:比如创建订单的逻辑,不管是用户通过API提交,还是系统通过消息触发,都调用同一个Handler,不用写两遍业务逻辑。
  • 便于测试:测试业务逻辑时不需要依赖消息队列,直接调用Handler即可,降低测试复杂度。
  • 符合分层原则:Application层不依赖任何外部基础设施(包括消息队列),保持业务逻辑的纯净性和可移植性。

2. Consumers仅做适配性工作

Consumers里只放和消息消费强相关的适配逻辑,比如:

  • 消息参数的格式转换(把消息DTO转换成Application层的Command/Query)
  • 消息消费的基础校验(比如必填字段是否存在,格式是否合法,而非业务规则校验)
  • 消息重试、死信的基础处理(比如记录消费日志)

3. 结合你的项目结构的具体实现示例

SharedContracts项目

存放公共的消息契约(如CreateOrderMessage),保证WebApi、Messaging等项目引用的消息格式一致。

Messaging项目

定义Mass Transit的Consumer,作为薄适配层:

public class CreateOrderConsumer : IConsumer<CreateOrderMessage>
{
    private readonly IMediator _mediator;

    public CreateOrderConsumer(IMediator mediator)
    {
        _mediator = mediator;
    }

    public async Task Consume(ConsumeContext<CreateOrderMessage> context)
    {
        // 仅做参数转换,不处理业务
        var command = new CreateOrderCommand(
            context.Message.OrderId,
            context.Message.CustomerId,
            context.Message.Items);

        // 转发到Application层处理核心逻辑
        await _mediator.Send(command);
    }
}

Application层

实现核心业务逻辑的Handler:

public class CreateOrderHandler : IRequestHandler<CreateOrderCommand, Result>
{
    private readonly IOrderRepository _orderRepository;
    private readonly ICustomerRepository _customerRepository;

    public CreateOrderHandler(IOrderRepository orderRepository, ICustomerRepository customerRepository)
    {
        _orderRepository = orderRepository;
        _customerRepository = customerRepository;
    }

    public async Task<Result> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
    {
        // 核心业务逻辑:校验客户合法性、创建订单实体、持久化等
        var customer = await _customerRepository.GetByIdAsync(request.CustomerId);
        if (customer == null)
            return Result.Failure("客户不存在");

        var order = Order.Create(request.OrderId, customer.Id, request.Items);
        await _orderRepository.AddAsync(order);

        return Result.Success();
    }
}

总结

核心业务逻辑必须放在Application层的Handlers里,Consumers只负责把消息转换为Application层能处理的命令/查询,这样既符合Clean Architecture的分层规范,又能保证业务逻辑的复用性、可测试性和可维护性。

内容的提问来源于stack exchange,提问作者pietro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 13:17:13