|
该版本仍在开发中,尚未被视为稳定。对于最新的稳定版本,请使用 Spring Integration 7.0.0! |
消息映射规则与约定
Spring Integration 实现了一种灵活的功能,可以将消息映射到方法及其参数,无需额外配置,依赖一些默认规则并定义某些约定。 以下章节的例子阐述了规则。
示例场景
以下示例展示了一个未注释的参数(对象或原语),它不是地图或者性能具有非空返回类型的对象:
public String doSomething(Object o);
输入参数是一个消息有效载荷。 如果参数类型与消息有效载荷不兼容,则尝试使用Spring 3.0提供的转换服务进行转换。 返回值被纳入返回消息的有效载荷。
以下示例展示了一个未注释的参数(对象或原元),它不是地图或者性能其中消息返回类型:
public Message doSomething(Object o);
输入参数是一个消息有效载荷。 如果参数类型与消息有效载荷不兼容,则尝试使用Spring 3.0提供的转换服务进行转换。 返回值是新构建的消息,发送到下一个目的地。
以下示例展示了一个参数,该参数是一个消息(或其子类之一),具有任意对象或原始返回类型:
public int doSomething(Message msg);
输入参数本身是消息.
返回值成为消息该数据被送往下一个目的地。
以下示例展示了一个单一参数,该参数为消息(或其子类之一)具有消息(或其子类之一)作为返回类型:
public Message doSomething(Message msg);
输入参数本身是消息.
返回值是新构建的消息该数据被送往下一个目的地。
下例展示了一个类型的参数地图或性能其中消息作为返回类型:
public Message doSomething(Map m);
这个有点有趣。
虽然一开始看似简单地直接映射到消息头,但通常优先考虑消息有效载荷。
这意味着如果消息有效载荷类型为地图,这个输入参数表示一个消息有效载荷。
然而,如果消息有效载荷不是类型地图转换服务不尝试转换有效载荷,输入参数映射到消息头部。
以下示例展示了两个参数,其中一个是任意类型(对象或原元),但不是地图或者性能对象,另一个类型为地图或性能类型(无论报税结果如何):
public Message doSomething(Map h, <T> t);
该组合包含两个输入参数,其中一个类型为地图.
那个非——地图参数(无论顺序如何)都映射到消息有效载荷和地图或性能(无论顺序如何)都映射到消息头部,提供了一种很好的POJO交互方式消息结构。
以下示例显示无参数(无论返回如何):
public String doSomething();
该消息处理方法的调用基于发送到该处理程序所连接的输入信道的消息。
然而,没有消息数据被映射,因此消息作为事件或触发器来调用处理者。
输出按照前面描述的规则进行映射。
以下示例显示无参数且返回为空值:
public void soSomething();
这个例子和前面的例子一样,但它不产生输出。
基于注释的映射
基于注释的映射是最安全且最不歧义的将消息映射到方法的方法。 以下示例展示了如何显式地将方法映射到报头:
public String doSomething(@Payload String s, @Header("someheader") String b)
如你后面所见,如果没有注释,这个签名会导致歧义条件。
然而,通过显式地将第一个参数映射到消息有效载荷,以及对某标题消息头部,我们避免了任何歧义。
以下示例与前例几乎相同:
public String doSomething(@Payload String s, @RequestParam("something") String b)
@RequestMapping或者任何其他非 Spring Integration 映射注释都无关紧要,因此忽略,第二个参数未映射。
虽然第二个参数可以轻松映射到有效载荷,但实际上只能有一个有效载荷。
因此,注释避免了这种方法的歧义。
以下示例展示了另一种类似方法,如果没有注释来澄清意图,这种方法会显得模糊:
public String foo(String s, @Header("foo") String b)
唯一的区别是第一个参数隐式映射到消息有效载荷。
以下示例展示了另一个签名,如果没有注释,肯定会被视为歧义,因为它有超过两个参数:
public String soSomething(@Headers Map m, @Header("something") Map f, @Header("someotherthing") String bar)
这个例子尤其有问题,因为其中两个论证是地图实例。
然而,基于注释的映射可以轻松避免歧义。
在这个例子中,第一个参数映射到所有消息头,而第二和第三个参数映射到名为“something”和“someotherthing”的消息头的值。
有效载荷没有映射到任何参数。
复杂情景
以下示例使用多个参数:
多个参数会在确定合适的映射时造成很大模糊性。
一般建议是用@Payload,@Header和@Headers.
本节示例显示了导致例外情况的模糊条件。
public String doSomething(String s, int i)
这两个参数的重量相等。 因此,无法确定哪个是有效载荷。
下一个例子展示了类似的问题,但有三个参数:
public String foo(String s, Map m, String b)
虽然Map可以轻松映射到消息头部,但无法确定这两个字符串参数的处理方式。
以下示例展示了另一种歧义方法:
public String foo(Map m, Map f)
虽然有人可能会争论这一点地图可以映射到消息有效载荷,另一个映射到消息头部,我们不能依赖顺序。
任何具有多个方法参数且不是的方法签名(地图,<了>)且参数未标注,会导致歧义并触发异常。 |
接下来的一组示例展示了多种导致歧义的方法。
拥有多方法的消息处理程序基于之前(示例中)描述的相同规则进行映射。 不过,有些场景看起来仍然可能让人困惑。
以下示例展示了具有合法(可映射且无歧义)签名的多种方法:
public class Something {
public String doSomething(String str, Map m);
public String doSomething(Map m);
}
(无论这些方法名称相同或不同,都无关紧要。)
这消息可以映射到任一方法。
当消息有效载荷可以映射到 时,会调用第一种方法力量消息头可以映射到m.
第二种方法也可以作为候选方法,仅将消息头映射到m.
更糟糕的是,这两种方法的名字相同。
起初,这看起来可能有些模糊,因为以下配置:
<int:service-activator input-channel="input" output-channel="output" method="doSomething">
<bean class="org.things.Something"/>
</int:service-activator>
之所以有效,是因为映射首先基于有效载荷,其次才考虑其他一切。 换句话说,第一个参数可以映射到有效载荷的方法优先于所有其他方法。
现在考虑一个另一个例子,它产生了一个真正模糊的条件:
public class Something {
public String doSomething(String str, Map m);
public String doSomething(String str);
}
这两种方法都有可以映射到消息有效载荷的签名。
它们的名字也相同。
此类处理方法会触发异常。
然而,如果方法名称不同,你可以用方法属性(见下一个示例)。
以下示例展示了同一示例,但使用了两种不同的方法名称:
public class Something {
public String doSomething(String str, Map m);
public String doSomethingElse(String str);
}
以下示例展示了如何使用方法属性来决定映射:
<int:service-activator input-channel="input" output-channel="output" method="doSomethingElse">
<bean class="org.bar.Foo"/>
</int:service-activator>
因为该配置显式地映射了做点别的事方法,我们消除了歧义。