Axon 通过BeanValidationInterceptor实现数据结构校验

Axon数据校验

场景:

因为command的发送方和接收方是不同的服务,所以就考虑对command数据结构做数据校验。联想到Controller层使用Hibernate Validator基于注解的方式进行数据校验,就想Axon是不是也有同样的实现。

官方文档说明

翻阅官网可以看的如下内容:

Structural validation
There is no point in processing a query if it does not contain all required information in the correct format. In fact, a query that lacks information should be blocked as early as possible. Therefore, an interceptor should check all incoming queries for the availability of such information. This is called structural validation.
Axon Framework has support for JSR 303 Bean Validation based validation. This allows you to annotate the fields on queries with annotations like @NotEmpty and @Pattern. You need to include a JSR 303 implementation (such as Hibernate-Validator) on your classpath. Then, configure a BeanValidationInterceptor on your query bus, and it will automatically find and configure your validator implementation. While it uses sensible defaults, you can fine-tune it to your specific needs.
Interceptor Ordering Tip
You want to spend as few resources on an invalid queries as possible. Therefore, this interceptor is generally placed at the very front of the interceptor chain. In some cases, a logging or auditing interceptor might need to be placed first, with the validating interceptor immediately following it.
The BeanValidationInterceptor also implements MessageHandlerInterceptor, allowing you to configure it as a handler interceptor as well.

可以看的加粗的地方,Axon支持JSR 303,只需要引入JSR303的实现(例如Hibernate-Validator),并将BeanValidationInterceptor 注册到命令总线里,他会自动找到对应JSR303的实现并在CommandMessage执行对应MessageHandler之前进行拦截做校验。

实现

理论依据存在,下面就是看如何实现了
首先找到了commandBus 注入spring容器的代码,查找路径如下:
在这里插入图片描述
根据springboot自动注入的机制找到AxonAutoConfiguration,然后可以找到如下的代码

 @ConditionalOnMissingBean(
        ignoredType = {"org.axonframework.commandhandling.distributed.DistributedCommandBus", "org.axonframework.axonserver.connector.command.AxonServerCommandBus"},
        value = {CommandBus.class}
    )
    @Qualifier("localSegment")
    @Bean
    public SimpleCommandBus commandBus(TransactionManager txManager, AxonConfiguration axonConfiguration, DuplicateCommandHandlerResolver duplicateCommandHandlerResolver) {
        SimpleCommandBus commandBus = SimpleCommandBus.builder().transactionManager(txManager).duplicateCommandHandlerResolver(duplicateCommandHandlerResolver).messageMonitor(axonConfiguration.messageMonitor(CommandBus.class, "commandBus")).build();
        commandBus.registerHandlerInterceptor(new CorrelationDataInterceptor(axonConfiguration.correlationDataProviders()));
        return commandBus;
    }

首先看看这个SimpleCommandBus内部有什么
在这里插入图片描述
看到这个handlerInterceptors, 是个List<MessageHandlerInterceptor<? super CommandMessage<?>>>,看之前官方文档可以知道
The BeanValidationInterceptor also implements MessageHandlerInterceptor, 那就是只要把BeanValidationInterceptor 加到这个list中就可以了。

那接着就是找SimpleCommandBus是不是有注册的方法,于是找到了下面的代码:

@Override
    public Registration registerHandlerInterceptor(
            MessageHandlerInterceptor<? super CommandMessage<?>> handlerInterceptor) {
        handlerInterceptors.add(handlerInterceptor);
        return () -> handlerInterceptors.remove(handlerInterceptor);
    }

由此就有了下面的配置:

  @ConditionalOnMissingBean(
            ignoredType = {"org.axonframework.commandhandling.distributed.DistributedCommandBus"
                    , "org.axonframework.axonserver.connector.command.AxonServerCommandBus"},
            value = {CommandBus.class}
    )
    @Qualifier("localSegment")
    @Bean
    public SimpleCommandBus commandBus(TransactionManager txManager, AxonConfiguration axonConfiguration,
                                       DuplicateCommandHandlerResolver duplicateCommandHandlerResolver) {
        SimpleCommandBus commandBus = SimpleCommandBus
                .builder()
                .transactionManager(txManager)
                .duplicateCommandHandlerResolver(duplicateCommandHandlerResolver)
                .messageMonitor(axonConfiguration.messageMonitor(CommandBus.class, "commandBus"))
                .build();
        commandBus.registerHandlerInterceptor(
                new CorrelationDataInterceptor(axonConfiguration.correlationDataProviders()));
        // 数据校验拦截器
        commandBus.registerHandlerInterceptor(new BeanValidationInterceptor<>());
        return commandBus;
    }

配置好拦截器后,就是给自己的command加注解了,具体支持那些注解,网上文档很多这里就不详细说明了,可以看下我配置的一个例子:


public class ChangeOrderCommand {

    @TargetAggregateIdentifier
    @NotBlank
    private String id;

    @NotBlank
    private String orderName;

    @NotNull
    private int number;

    public ChangeOrderCommand() {
    }

    public ChangeOrderCommand(String id, String orderName, int number) {
        this.id = id;
        this.orderName = orderName;
        this.number = number;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值