SlimMessageBus FluentValidation 插件实战:消息生产端与消费端双向校验

📅 2026/8/25 8:42:46
SlimMessageBus FluentValidation 插件实战:消息生产端与消费端双向校验
SlimMessageBus FluentValidation 插件实战消息生产端与消费端双向校验【免费下载链接】SlimMessageBusLightweight message bus interface for .NET (pub/sub and request-response) with transport plugins for popular message brokers.项目地址: https://gitcode.com/gh_mirrors/sl/SlimMessageBusSlimMessageBus 是一款轻量级的 .NET 消息总线框架而 SlimMessageBus.Host.FluentValidation 插件为它带来了强大的消息校验能力。借助这个插件你可以在消息生产端Publish/Send 发出前和消费端投递给消费者/处理器前对消息做双向校验让非法消息在进入系统之前就原路返回避免脏数据污染下游业务。本文带你快速上手这套消息校验机制。 插件解决什么问题在真实的消息系统中你会遇到两类风险生产端风险调用方发出了一个字段缺失、格式错误的消息白白占用传输通道Kafka、RabbitMQ、内存总线等的带宽消费端风险外部系统往消息通道投递了不可信的消息消费者如果不加甄别直接处理就可能抛出难以排查的运行时错误。SlimMessageBus 的 FluentValidation 插件正是为此而生它基于 SlimMessageBus.Host.Interceptor 的拦截器核心接口实现因此可以与任意传输层搭配使用包括 Kafka、Azure Service Bus、Redis乃至进程内的内存总线。 工作原理一套校验两个拦截点插件的核心是一个抽象校验拦截器它会汇总所有IValidatorT校验器的结果一旦发现有错误就抛出异常拦截后续的发送或消费流程。核心逻辑见 AbstractValidationInterceptor.cs// 所有校验器并行执行只要有任何一个失败项就抛异常 var results await Task.WhenAll(validationTasks); var failures results.SelectMany(x x.Errors); if (failures.Any()) { var ex _errorsHandler ! null ? _errorsHandler.OnValidationErrors(failures) : new ValidationException(failures); throw ex; }插件通过两个拦截器把这段逻辑挂到消息总线的两个关键节点上拦截器挂载时机作用ProducerValidationInterceptorT消息执行.Publish()/.Send()时消息尚未发出就完成校验失败则直接抛异常消息根本不会进入传输层ConsumerValidationInterceptorT消息即将投递给IConsumerT或IRequestHandlerT, R前拦截不可信的外部消息防止其进入消费者业务逻辑 快速上手三步启用消息校验以项目自带的 Sample.ValidatingWebApi 为例一个用 CQRS 内存总线的 ASP.NET 应用只需要三步。第 1 步编写 FluentValidation 校验器给消息类型命令/查询写一个IValidatorT实现例如 CreateCustomerCommandValidator.cspublic class CreateCustomerCommandValidator : AbstractValidatorCreateCustomerCommand { public CreateCustomerCommandValidator() { RuleFor(x x.FirstName).NotEmpty(); RuleFor(x x.LastName).NotEmpty(); RuleFor(x x.Email).NotEmpty(); RuleFor(x x.Phone).NotEmpty().Length(6).When(x x.Phone ! null); } }第 2 步在消息总线构建器中启用插件AddFluentValidation扩展方法定义在 MessageBusBuilderExtensions.cs。在 Program.cs 中可以看到完整的配置方式builder.Services.AddSlimMessageBus(mbb mbb .WithProviderMemory() .AutoDeclareFrom(Assembly.GetExecutingAssembly()) .AddAspNet() .AddFluentValidation(cfg { // 生产端校验扫描程序集中的 IValidatorT注册生产拦截器 cfg.AddProducerValidatorsFromAssemblyContainingCreateCustomerCommandValidator(); // 消费端校验注册消费拦截器 //cfg.AddConsumerValidatorsFromAssemblyContainingCreateCustomerCommandValidator(); // 可自定义校验失败时抛出的异常 //cfg.AddValidationErrorsHandler(errors new ApplicationException(Custom exception)); })); // 别忘了把 FluentValidation 的校验器注册进依赖注入容器 builder.Services.AddValidatorsFromAssemblyContainingCreateCustomerCommandValidator();两个AddXxxValidatorsFromAssemblyContaining方法会自动扫描指定程序集中所有IValidatorT实现并针对消息类型 T 批量注册对应拦截器详见 FluentValidationMessageBusBuilder.cs。第 3 步把 HTTP 请求交给消息总线app.MapPost(/customer, (CreateCustomerCommand command, IMessageBus bus) bus.Send(command));就这么简单——当客户端发来一条Email为空的请求时生产端拦截器会在消息进入传输层之前就抛出ValidationException。⚙️ 自定义异常让校验失败说人话默认情况下生产端和消费端校验失败都会抛出FluentValidation.ValidationException。你可以通过AddValidationErrorsHandler把它映射成业务自定义异常甚至返回null来吞掉校验错误mbb.AddFluentValidation(opts { opts.AddValidationErrorsHandler(errors new ApplicationException(消息格式非法)); });在示例项目中Program.cs 还演示了一个实用技巧用异常处理中间件把ValidationException翻译成 HTTP400 Bad Request并把具体错误字段序列化返回给前端而不是让用户看到 500 错误。️ 消费端校验失败后会怎样当消费端校验失败时插件会抛出ValidationException随后进入标准的消费者错误处理流程——取决于底层传输消息可能会被重试多次最终进入死信队列DLQ。这正是拦截不可信外部消息比如 Kafka 里被其他系统写坏的数据的期望行为生产端拦截 → 消息从未发出零传输成本消费端拦截 → 坏消息进不了业务逻辑交给重试/DLQ 机制兜底。 延伸阅读插件官方文档docs/plugin_fluent_validation.md含非 Microsoft DI 容器的手动注册方式完整示例项目Sample.ValidatingWebApi包含命令Commands与查询Queries两套 CQRS 消息的校验演示拦截器机制SlimMessageBus.Host.Interceptor 提供IProducerInterceptorT、IConsumerInterceptorT、IRequestHandlerInterceptorT, R三类拦截接口是插件体系的基石可用插件总览docs/NuGet.md一句话总结给消息总线装上 FluentValidation 插件相当于在门口和工位各设了一道安检——生产端校验守住出口消费端校验守住入口非法消息再也进不了你的业务系统。【免费下载链接】SlimMessageBusLightweight message bus interface for .NET (pub/sub and request-response) with transport plugins for popular message brokers.项目地址: https://gitcode.com/gh_mirrors/sl/SlimMessageBus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考