动态绑定这种绑定方式只有orchestration发送端口有,orchestration接收端口不具有这种绑定方式。(注意:sql adapter不支持动态绑定)
所谓动态,就是跟orchestration发送端口绑定的物理发送端口是动态发送端口(物理发送端口有静态发送端口和动态发送端口),这种动态发送端口只有管道的设置,没有端口使用的适配器和URI的设置,运行时根据消息中上下文属性来决定使用的适配器类型和URI的相关属性。这样一个发送端口可以动态的路由消息到不同的适配器的不同的地址。
设想这种需求,在一个文件夹中有个消息,类似这样:
<ns0:Person xmlns:ns0="http://BindingDynamic.InputSch">
<Method>mail</Method>
<id>id_0</id>
<name>name_0</name>
</Body>
</ns0:Person>
读取此消息,并需要根据Method元素指定的方式把此消息发送到不同的地方,Method有三种可能:
file – 把消息用file适配器发送到指定文件夹
mail – 把消息用smtp适配器发送到指定的邮箱
ftp – 把消息用ftp适配器发送到指定的ftp服务器
设计一个跟消息相匹配的消息架构,并把架构中Method元素设为可分辨字段,因为需要在orchestration中使用这个字段作为分支判断条件。
设计流程如下:
输入消息通过Port_Person_In端口绑定单向接收端口从指定的文件夹中读取。
通过Decide形状根据Method元素的三种可能的值分别处理file、mail和ftp时的情况。
在orchestration中分别建立三个跟入站消息同类型的消息分别对应三种情况需要构造的消息。
OutFileMsg消息对应要输出到文件夹的消息。
OutMailMsg消息对应要发送到email的消息。
OutFtpMsg消息对应要上传到ftp服务器的消息。
Port_Person_Out端口配置为动态发送端口,orchestrastion的动态端口在部署后会自动在biztalk控制台生成相应的物理动态发送端口并绑定。物理动态发送端口根据orchestration的动态端口发出消息的上下文属性BTS.OutboundTransportType(决定使用何种适配器)和BTS.OutboundTransportLocation(决定消息发送到的URI)把消息发送到不同的适配器。流程根据输入的消息构造不同的消息(这里是消息类型一样,上下文属性不同),都是通过orchestrastion的动态端口发送出去。
ConstructMsg_File构造要输出到文件夹的OutFileMsg消息:
OutFileMsg = InPersonMsg; //将入站消息赋给OutFileMsg
Port_Person_Out(Microsoft.XLANGs.BaseTypes.Address) = @"file://C:\Samples\BindingDynamic\Out\File_%MessageID%.xml";
ConstructMsg_Mail构造要输出到文件夹的OutMailMsg消息:
OutMailMsg = InPersonMsg;
Port_Person_Out(Microsoft.XLANGs.BaseTypes.Address) = "mailto:[email protected]"; //目的地email地址
OutMailMsg(SMTP.EmailBodyTextCharset)="UTF-8"; //正文编码
OutMailMsg(SMTP.Subject) = "test"; //邮件主题
OutMailMsg(SMTP.MessagePartsAttachments) = 2; //表示消息的所有部分都作为附件发送
OutMailMsg(SMTP.SMTPAuthenticate) = 1; //基本验证,使用明码发送用户名和密码
OutMailMsg(SMTP.From) = "[email protected]"; //from的email地址
OutMailMsg(SMTP.SMTPHost) = "smtp.yeah.net"; //smtp服务器
OutMailMsg(SMTP.Username) = "username"; //smtp验证用户名
OutMailMsg(SMTP.Password) = "password"; //密码
ConstructMsg_Ftp构造要输出到文件夹的OutFtplMsg消息:
OutFtpMsg = InPersonMsg;
Port_Person_Out(Microsoft.XLANGs.BaseTypes.Address) = "ftp://ftpserver.com";
OutFtpMsg(FTP.UserName) = " username ";
OutFtpMsg(FTP.Password) = " password ";
发往动态端口的消息依靠消息上下文属性BTS.OutboundTransportLocation决定端口最终使用哪种适配器和发往的地址。消息在发送Messagebox路由到动态发送端口前必须把这个属性升级到消息上下文。
可以在设计消息schema时将消息中的某个字段promote到TS.OutboundTransportLocation属性,然后在pipeline中使用xml拆装管道组件升级BTS.OutboundTransportLocation属性。
也可以在orchestration的表达式中给orchestration动态绑定端口的Microsoft.XLANGs.BaseTypes.Address赋值来给消息的BTS.OutboundTransportLocation属性升级。
赋值形式是这样:
DynamicPortName(Microsoft.XLANGs.BaseTypes.Address) = "前缀别名+URI";
比如,发送到smtp适配器,email地址为[email protected],赋值语句是这样:
Port_Person_Out(Microsoft.XLANGs.BaseTypes.Address) = "mailto:[email protected]";
下表是biztalk中所有可用于动态发送端口的适配器、前缀别名和适配器名:
适配器
|
前缀别名
|
适配器名
|
HTTP adapter
|
HTTP://
|
HTTP 或 SOAP
|
FILE adapter
|
FILE://
|
FILE
|
Windows SharePoint Services adapter
|
WSS://
|
Windows SharePoint Services
|
SMTP adapter
|
MAILTO:
|
SMTP
|
SQL adapter
|
SQL://
|
SQL
|
FTP adapter
|
FTP://
|
FTP
|
MSMQ adapter
|
MSMQ://
|
MSMQ
|
MQSeries adapter
|
MQS://
|
MQSeries
|
EDI adapter
|
EDI://
|
EDI
|
当消息到了orchestration的动态绑定发送端口后, orchestration将端口的Microsoft.XLANGs.BaseTypes.Address属性的值,赋给消息的BTS.OutboundTransportLocation属性。
带有BTS.OutboundTransportLocation属性的消息到达动态发送端口后,消息引擎根据BTS.OutboundTransportLocation属性值的前缀判断需要使用何种适配器,从上表中可以看出,一般从地址的的前缀就能判断出相应的适配器,但是HTTP://前缀会对应到两种适配器:HTTP 或 SOAP,消息引擎如何判断应该使用哪种适配器呢?
这里需要引入另外一个属性:BTS.OutboundTransportType,当从地址的前缀上判断适配器有歧义时,使用这个属性指定使用哪个适配器。当需要使用SOAP适配器时,给消息的BTS.OutboundTransportType属性赋值“SOAP”即可;如果需要使用HTTP适配器时,给消息的BTS.OutboundTransportType属性赋值“HTTP”即可。当消息BTS.OutboundTransportLocation属性指的前缀为HTTP://,同时没有给消息的BTS.OutboundTransportType属性赋值的情况下,消息引擎默认使用SOAP适配器。
编译项目,部署。
配置项目,接收端口是specify later绑定类型端口,配置中使用file适配器指向指定的文件夹。
物理动态发送端口在部署好后已经自动建立并跟orchestration的动态绑定端口绑定。
启动部署好的应用程序,看产生的订阅:
第一个订阅是orchestration接收端口跟file适配器接收端口的specify later绑定产生的订阅,接收来自文件的消息,这种订阅前面已经讨论过。
后面后十个订阅,形式看上去类似,先来看第一个订阅的详情,“General”标签:
Figure 14. Dynamic动态发送端口订阅
Service class是订阅消息的服务类型,这里是Messaging类型,就是只一般的端口类型服务。
Service name是订阅消息的具体服务,这里是BindingDynamic_
“Expression”标签:
Figure 14. Dynamic动态发送端口订阅条件
订阅条件是:
Subscription:
{
ORGroup0
{
BTS.OutboundTransportType == FILE
And
BTS.SPID == {BA5CD1EE-19D8-4904
And
BTS.OutboundTransportLocation Exists
}
}
这个订阅表示接收BTS.OutboundTransportType属性类型指定file适配器的,并且消息中BTS.OutboundTransportLocation属性存在的,消息中BTS.SPID属性指向这个动态物理发送端口。消息的BTS.SPID属性在orchestration端口跟动态物理发送端口绑定后,在消息到了orchestration端口后在端口中把BTS.SPID属性升级到消息上下文的。
类似订阅一共有十个,分别订阅所有十个可用于动态发送端口的适配器,每个订阅对应一种适配器,适应消息中可能出现的各种适配器名。订阅的服务都是这个物理动态发送端口。
这十个订阅的订阅主体都是这个物理动态发送端口,只是订阅的条件有些不同,根据订阅的原理,应该可以把这十个订阅合并为一个订阅,把订阅条件用或组合并在一起就行了,类似这样:
Subscription:
{
ORGroup0
{
BTS.OutboundTransportType == FILE
And
BTS.SPID == {BA5CD1EE-19D8-4904
And
BTS.OutboundTransportLocation Exists
}
OR
ORGroup1
{
BTS.OutboundTransportType == SOAP
And
BTS.SPID == {BA5CD1EE-19D8-4904
And
BTS.OutboundTransportLocation Exists
}
OR
ORGroup2
{
BTS.OutboundTransportType == SMTP
And
BTS.SPID == {BA5CD1EE-19D8-4904
And
BTS.OutboundTransportLocation Exists
}
……
}
项目的测试代码下载:BindingDynamic.rar