抢先一步
VMware 提供培训和认证,助您快速提升。
了解更多这是 Spring Cloud Stream 2.0.0.RELEASE 发布准备工作中的一系列预发布博客中的第一篇。
Spring Cloud Stream 2.0 包含对基于通道的绑定器的内容类型协商的全面改进,以解决性能、灵活性和最重要的是一致性问题。以下博客探讨了已完成的一些关键点、期望的内容以及它可能如何帮助您。
数据转换是任何消息驱动微服务架构的核心功能之一。在 Spring Cloud Stream 中,此类数据表示为 Spring 的Message
。
在消息流(一个流)的各个点,可能需要将消息转换为所需的形状/大小,然后再到达其目标。这是由于两个原因造成的
1. 将传入消息的内容从线格式转换为与应用程序提供的处理程序签名匹配。2. 将传出消息的内容转换为下一个处理程序的签名(如果存在某些内部流)或转换回线格式。
线格式通常为byte[]
,并由绑定器实现控制。
在 Spring Cloud Stream 消息中,转换是通过org.springframework.messaging.converter.MessageConverter
抽象来完成的。
以下步骤序列显示了典型消息流以及Message
经历的转换,使用 Spring Cloud Stream 的Processor
契约进行了描述,基本上涵盖了入站和出站内容转换背后的需求。
1. 从绑定器接收线格式的 Spring Message
2. 确保在 Spring Message
中设置了输入contentType
标头 3. 将 Spring Message
从线格式转换为应用程序提供的MessageHandler
的签名 4. 调用应用程序提供的MessageHandler
5. 将MessageHandler
的返回值转换回 Spring Message
6. 确保在 Spring Message
中设置了输出contentType
标头 7. 将 Spring Message
转换回到线格式 8. 将线格式的 Spring Message
发送回绑定器
虽然以上内容提供了典型消息流中主要状态变化的完整摘要,但细节总是很重要的,因此让我们更仔细地查看每个步骤。
Processor.INPUT'
)。contentType
标头时才向传入消息注入contentType
标头。这是为了确保,如果需要,下游消息转换可以考虑contentType
(稍后将详细介绍)。注入的contentType
来自为每个目标绑定设置的内容类型,其中application/json
为默认内容类型。例如,'spring.cloud.stream.bindings.myInput.content-type=text/plain' 将目标绑定'myInput'(传入)的内容类型设置为'text/plain'。这意味着除非消息已包含'contentType'标头,否则每个传入消息都会注入'contentType=text/plain'标头。换句话说,标头提供的contentType
优先于每个绑定设置的标头。3. 现在,借助HandlerMethodArgumentResolvers
和预配置或用户提供的MessageConverters
,传入消息将转换为应用程序提供的MessageHandler
的签名(例如,public Text process(Foo foo){..}
)。此类处理程序方法通常使用@StreamListener
、@ServiceActivator
、@Transformer
等其中一个进行注释。这就是一些转换器可能需要contentType
的地方,并且步骤 2 中的操作保证此类消息始终可以通过其contentType
标头获得它。当然,如果此类方法将Message
作为其输入参数,则不会执行转换。4. 处理程序方法被调用,并且成功后,将从处理程序方法的返回值开始创建传出消息的过程(假设非空处理程序方法)。5. 处理程序方法返回的值将转换回 Spring Message
,当且仅当返回值本身不是Message
时。这意味着将使用处理程序的返回值作为有效负载创建一个新的 Spring Message
。传入消息的标头将复制到新的传出消息中,同时剥离'SpringIntegrationProperties.messageHandlerNotPropagatedHeaders'标识的任何标头。默认情况下,只有一个标头设置在那里 - contentType
。这意味着新的传出消息是在没有设置contentType
标头的情况下创建的。这是为了确保contentType
可以随着应用程序级数据转换而发展。注意:仅当处理程序方法返回非 Message 时才会剥离contentType
。消息将发送到绑定器的输出通道。6. 与绑定器的输入通道类似,绑定器的输出通道(例如,Processor.OUTPUT
)也预先配置了通道拦截器。在这里,我们可选地将contentType
标头注入传出消息中,以准备将传出消息的内容转换回线格式。让我们看看仅有的两种可能的情况:a. 传出 Message 设置了contentType
标头。由于标头设置的contentType
优先于任何其他contentType
,因此不会执行任何contentType
注入,并且标头设置的contentType
的值将在转换回线格式期间使用。b. 传出 Message 未设置contentType
标头。绑定contentType
(默认或提供)将作为标头注入传出消息中,并在转换回线格式期间使用。7. 使用可用的MessageConverters
之一将消息转换为线格式。8. 转换后的消息将发送回绑定器,同时保留注入的或现有的contentType
标头。换句话说,传出消息将始终具有contentType
标头。
以上内容涵盖了开箱即用的默认行为。但这可能还不够,所以我们能否以及如何自定义?。2.0 中进行的内容类型协商改进的目标不仅是为了回答此类问题,而且是为了确保答案的一致性 - 入站和出站通道拦截器用于转换为/从线格式的'MessageConverters'与'HandlerMethodArgumentResolvers'用于转换为/从强类型转换的'MessageConverters'相同。
要添加自定义MessageConverter,只需创建org.springframework.messaging.converter.MessageConverter
的实现,并将其配置为@Bean
,并将该 bean 注释为@StreamMessageConverter
,它将作为现有MessageConverters堆栈中的第一个转换器添加,基本上优先于现有的MessageConverters。
希望到目前为止,任何和所有内容类型转换都是由MessageConverters
完成的这一点已经相当清楚了。虽然MessageConverters
的实现有所不同,但大多数都利用contentType
标头以及目标类型(targetClass
),这使它们能够执行类型内转换以及到/从线格式的转换。目前有一组预配置的MessageConverters
来支持大多数用例,因此对于大多数典型数据类型(即 json、文本等),最终用户实际上无需执行任何操作。但是,了解现在的工作原理与如何自定义之间的区别仍然很有价值 - 自定义现有和/或引入新的MessageConverter
实现。
我们目前正在更新文档,其中将包含更多关于此主题以及许多其他与 2.0 版本相关工作的详细信息和示例。这些预发布博文的目的是提高认知度,促进“试用”并征求反馈。综上所述,Spring Cloud Stream 2.0.0.RC1 已发布,您可以点击此处获取。
我们鼓励您使用以下方式提供反馈:
祝您使用愉快!