Spring Cloud Stream-编程模型

声明和绑定频道

触发绑定@EnableBinding

@Input和@Output 

访问绑定通道

生产和消费消息

聚合 


本文介绍Spring Cloud Stream的编程模型。Spring Cloud Stream提供了许多预定义的注释,用于声明绑定的输入和输出通道以及如何收听频道。

声明和绑定频道

触发绑定@EnableBinding

您可以将Spring应用程序转换为Spring Cloud Stream应用程序,将@EnableBinding注释应用于应用程序的配置类之一。@EnableBinding注释本身使用@Configuration进行元注释,并触发Spring Cloud Stream基础架构的配置:

...
@Import(...)
@Configuration
@EnableIntegration
public @interface EnableBinding {
    ...
    Class<?>[] value() default {};
}

@EnableBinding注释可以作为参数的一个或多个接口类,其中包含表示可绑定组件(通常是消息通道)的方法。

在Spring Cloud Stream 1.0中,唯一支持的可绑定组件是Spring消息传递MessageChannel及其扩展名SubscribableChannelPollableChannel。未来版本应该使用相同的机制将此支持扩展到其他类型的组件。在本文档中,我们将继续参考渠道。

@Input@Output 

Spring Cloud Stream应用程序可以在接口中定义任意数量的输入和输出通道为@Input@Output方法:

public interface Barista {

    @Input
    SubscribableChannel orders();

    @Output
    MessageChannel hotDrinks();

    @Output
    MessageChannel coldDrinks();
}

使用此接口作为@EnableBinding的参数将分别触发三个绑定通道,分别命名为ordershotDrinkscoldDrinks

@EnableBinding(Barista.class)
public class CafeConfiguration {

   ...
}

自定义频道名称

您可以使用@Input@Output注释指定频道的自定义频道名称,如以下示例所示:

public interface Barista {
    ...
    @Input("inboundOrders")
    SubscribableChannel orders();
}

在这个例子中,创建的绑定通道将被命名为inboundOrders

SourceSinkProcessor

为了方便寻址最常见的用例,涉及输入通道,输出通道或两者,Spring Cloud Stream提供了三个预定义的开箱即用的接口。

Source可用于具有单个出站通道的应用程序。

public interface Source {

  String OUTPUT = "output";

  @Output(Source.OUTPUT)
  MessageChannel output();

}

Sink可用于具有单个入站通道的应用程序。

public interface Sink {

  String INPUT = "input";

  @Input(Sink.INPUT)
  SubscribableChannel input();

}

Processor可用于具有入站通道和出站通道的应用程序。

public interface Processor extends Source, Sink {
}

对于任何这些接口,Spring Cloud Stream不提供特殊处理; 它们只是开箱即用。

访问绑定通道

注入绑定界面

对于每个绑定接口,Spring Cloud Stream将生成一个实现该接口的bean。调用其中一个bean的@Input注释或@Output注释方法将返回相关的绑定通道。

以下示例中的bean在调用其hello方法时在输出通道上发送消息。它在注入的Source bean上调用output()来检索目标通道。

@Component
public class SendingBean {

    private Source source;

    @Autowired
    public SendingBean(Source source) {
        this.source = source;
    }

    public void sayHello(String name) {
         source.output().send(MessageBuilder.withPayload(body).build());
    }
}

直接注入渠道

绑定通道也可以直接注入:

@Component
public class SendingBean {

    private MessageChannel output;

    @Autowired
    public SendingBean(MessageChannel output) {
        this.output = output;
    }

    public void sayHello(String name) {
         output.send(MessageBuilder.withPayload(body).build());
    }
}

如果在声明注释上定制了通道的名称,则应使用该名称而不是方法名称。给出以下声明:

public interface CustomSource {
    ...
    @Output("customOutput")
    MessageChannel output();
}

通道将被注入,如下例所示:

@Component
public class SendingBean {

    @Autowired
    private MessageChannel output;

    @Autowired @Qualifier("customOutput")
    public SendingBean(MessageChannel output) {
        this.output = output;
    }

    public void sayHello(String name) {
         customOutput.send(MessageBuilder.withPayload(body).build());
    }
}

生产和消费消息

您可以使用Spring Integration注释或Spring Cloud Stream的@StreamListener注释编写Spring Cloud Stream应用程序。@StreamListener注释在其他Spring消息传递注释(例如@MessageMapping@JmsListener@RabbitListener等)之后建模,但添加了内容类型管理和类型强制功能。

本地Spring Integration支持

因为Spring Cloud Stream基于Spring Integration,Stream完全继承了Integration的基础和基础设施以及组件本身。例如,您可以将Source的输出通道附加到MessageSource

@EnableBinding(Source.class)
public class TimerSource {

  @Value("${format}")
  private String format;

  @Bean
  @InboundChannelAdapter(value = Source.OUTPUT, poller = @Poller(fixedDelay = "${fixedDelay}", maxMessagesPerPoll = "1"))
  public MessageSource<String> timerMessageSource() {
    return () -> new GenericMessage<>(new SimpleDateFormat(format).format(new Date()));
  }
}

或者您可以在变压器中使用处理器的通道:

@EnableBinding(Processor.class)
public class TransformProcessor {
  @Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
  public Object transform(String message) {
    return message.toUpper();
  }
}

使用@StreamListener进行自动内容类型处理

在Spring Integration支持之外,Spring Cloud Stream提供自己的@StreamListener注释,在其他Spring消息传递注释(例如@MessageMapping@JmsListener@RabbitListener等)之后建模。 )。@StreamListener注释提供了一种更简单的处理入站邮件的模型,特别是在处理涉及内容类型管理和类型强制的用例时。

Spring Cloud Stream提供了一种可扩展的MessageConverter机制,用于通过绑定的通道处理数据转换,在这种情况下,将派生到使用@StreamListener注释的方法。以下是处理外部Vote事件的应用程序的示例:

@EnableBinding(Sink.class)
public class VoteHandler {

  @Autowired
  VotingService votingService;

  @StreamListener(Sink.INPUT)
  public void handle(Vote vote) {
    votingService.record(vote);
  }
}

当考虑具有String有效载荷和contentType标题application/json的入站Message时,可以看出@StreamListener和Spring Integration @ServiceActivator之间的区别。在@StreamListener的情况下,MessageConverter机制将使用contentType标头将String有效载荷解析为Vote对象。

与其他Spring消息传递方法一样,方法参数可以用@Payload@Headers@Header注释。

对于返回数据的方法,必须使用@SendTo注释来指定方法返回的数据的输出绑定目的地:

@EnableBinding(Processor.class)
public class TransformProcessor {

  @Autowired
  VotingService votingService;

  @StreamListener(Processor.INPUT)
  @SendTo(Processor.OUTPUT)
  public VoteResult handle(Vote vote) {
    return votingService.record(vote);
  }
}
 

聚合 

Spring Cloud Stream支持将多个应用程序聚合在一起,直接连接其输入和输出通道,并避免通过代理交换消息的额外成本。从版本1.0的Spring Cloud Stream开始,仅对以下类型的应用程序支持聚合:

  • 来源 - 具有名为output的单个输出通道的应用程序,通常具有类型为org.springframework.cloud.stream.messaging.Source的单个绑定

  • 接收器 - 具有名为input的单个输入通道的应用程序,通常具有类型为org.springframework.cloud.stream.messaging.Sink的单个绑定

  • 处理器 - 具有名为input的单个输入通道和名为output的单个输出通道的应用程序,通常具有类型为org.springframework.cloud.stream.messaging.Processor的单个绑定。

它们可以通过创建一系列互连的应用程序来聚合在一起,其中序列中的元素的输出通道连接到下一个元素的输入通道(如果存在)。序列可以从处理器开始,它可以包含任意数量的处理器,并且必须以处理器接收器结束。

根据起始和结束元素的性质,序列可以具有一个或多个可绑定的信道,如下所示:

  • 如果序列从源头开始并以sink结束,则应用程序之间的所有通信都是直接的,并且不会绑定任何通道

  • 如果序列以处理器开始,则其输入通道将成为聚合的input通道,并将相应地进行绑定

  • 如果序列以处理器结束,则其输出通道将成为聚合的output通道,并将相应地进行绑定

使用AggregateApplicationBuilder实用程序类执行聚合,如以下示例所示。我们考虑一个项目,我们有源,处理器和汇点,可以在项目中定义,或者可以包含在项目的依赖之一中。

 

@SpringBootApplication
@EnableBinding(Sink.class)
public class SinkApplication {

	private static Logger logger = LoggerFactory.getLogger(SinkModuleDefinition.class);

	@ServiceActivator(inputChannel=Sink.INPUT)
	public void loggerSink(Object payload) {
		logger.info("Received: " + payload);
	}
}
@SpringBootApplication
@EnableBinding(Processor.class)
public class ProcessorApplication {

	@Transformer
	public String loggerSink(String payload) {
		return payload.toUpperCase();
	}
}
@SpringBootApplication
@EnableBinding(Source.class)
public class SourceApplication {

	@Bean
	@InboundChannelAdapter(value = Source.OUTPUT)
	public String timerMessageSource() {
		return new SimpleDateFormat().format(new Date());
	}
}

每个配置可以用于运行一个单独的组件,但在这种情况下,它们可以聚合在一起,如下所示:

@SpringBootApplication
public class SampleAggregateApplication {

	public static void main(String[] args) {
		new AggregateApplicationBuilder()
			.from(SourceApplication.class).args("--fixedDelay=5000")
			.via(ProcessorApplication.class)
			.to(SinkApplication.class).args("--debug=true").run(args);
	}
}

该序列的起始组件作为from()方法的参数提供。序列的结尾部分作为to()方法的参数提供。中间处理器作为via()方法的参数提供。同一类型的多个处理器可以一起链接(例如,用于具有不同配置的流水线转换)。对于每个组件,构建器可以为Spring Boot配置提供运行时参数。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值