SpringCloud 机械学
为了更好地理解内容类型协商的机制和必要性,我们以下面的消息处理程序为例,看一个非常简单的用例:
@StreamListener(Processor.INPUT) @SendTo(Processor.OUTPUT) public String handle(Person person) {..}
为简单起见,我们假设这是应用程序中唯一的处理程序(我们假设没有内部管道)。
前面示例中所示的处理程序期望将Person
对象作为参数,并产生String
类型作为输出。为了使框架成功将传入的Message
作为参数传递给此处理程序,它必须以某种方式将Message
类型的有效负载从有线格式转换为Person
类型。换句话说,框架必须找到并应用适当的MessageConverter
。为此,该框架需要用户提供一些指导。处理程序方法本身的签名(Person
类型)已经提供了这些指令之一。因此,从理论上讲,这应该是(并且在某些情况下是足够的)。但是,对于大多数用例而言,为了选择适当的MessageConverter
,框架需要额外的信息。缺少的部分是contentType
。
Spring Cloud Stream提供了三种机制来定义contentType
(按优先顺序):
1.标题:contentType
可以通过消息本身进行通信。通过提供contentType
标头,您可以声明用于查找和应用适当的MessageConverter
的内容类型。
2.绑定:可以通过设置spring.cloud.stream.bindings.input.content-type
属性为每个目标绑定设置contentType
。
属性名称中的
input
段与目的地的实际名称相对应(在本例中为“输入”)。通过这种方法,您可以在每个绑定的基础上声明用于查找和应用适当的MessageConverter
的内容类型。
3.默认值:如果Message
标头或绑定中不存在contentType
,则使用默认的application/json
内容类型来查找和应用适当的MessageConverter
。
如前所述,前面的列表还演示了平局时的优先顺序。例如,标头提供的内容类型优先于任何其他内容类型。对于按绑定设置的内容类型也是如此,这实际上使您可以覆盖默认内容类型。但是,它也提供了明智的默认值(由社区反馈确定)。
将application/json
设置为默认值的另一个原因是由分布式微服务体系结构驱动的互操作性要求,在该体系结构中,生产者和使用者不仅可以在不同的JVM中运行,而且还可以在不同的非JVM平台上运行。
当非无效处理程序方法返回时,如果返回值已经是Message
,则该Message
成为有效负载。但是,当返回值不是Message
时,将使用返回值作为有效负载构造新的Message
,同时从输入Message
继承标头减去由SpringIntegrationProperties.messageHandlerNotPropagatedHeaders
定义或过滤的标头。默认情况下,仅设置一个标头:contentType
。这意味着新的Message
没有设置contentType
头,从而确保contentType
可以演进。您始终可以选择不从处理程序方法返回Message
的位置,在该方法中可以注入所需的任何标头。
如果存在内部管道,则通过相同的转换过程将Message
发送到下一个处理程序。但是,如果没有内部管道或您已经到达内部管道的末尾,则Message
将发送回输出目的地。
更多建议: