其实看到这个功能的时候,我的疑问还是很大的。众所周知,如果想跨语言,WebService绝对会纳入你的考虑。既然这个东西都能够跨语言了,那么还需要通过ESB么?
个人的理解,如果只是单独调一下WebService,然后就没有后文了,那么确实没有什么必要,但如果是调WebService之前、之后还有别的操作,而这些操作是和其它系统的交互,那么此时ESB就能够发挥出较大的作用了。因为ESB有可编排的这个优点,所以实现起来是很容易的。
上面说的这些优点,以后有空再慢慢说,现在还是先入题,看下ESB是怎样调用WebService的吧。
在JBossesb中,它封装了一个叫SOAPClient的类,这个类的调用是通过在jboss-esb.xml中配置调用的。
直接上代码:
<action name="soapui-client-action"
class="org.jboss.soa.esb.actions.soap.SOAPClient">
<property name="wsdl" value="这里是WSDL的URL" />
<!--property name="wsdlTransform" value="如果是本地的xml,那么用这个属性" / -->
<property name="responseAsOgnlMap" value="true" /><!--如果有返回值,且以Map的方式返回,就这样配置-->
<property name="SOAPAction" value="sayHello"/><!--别说你不知道这个是干嘛的啊-->
</action>
在代码中,我的注释很详细了,但这个Action只是用来调用方法的,那么参数和返回值应该怎样设置及获取呢?
先说设置参数:
对WebService有过研究的都知道,一个方法,转成WSDL后,方法名是一个element,如果有返回值,那么还会多一个"方法名+Response"的element,对于每个方法的详细说明,会在以name为相应方法名的complexType进行说明,参数会按顺序在sequence中进行说明,如果说的很抽象,那么看下面代码。
<xs:element name="sayHello" type="tns:sayHello"/>
<xs:element name="sayHelloResponse" type="tns:sayHelloResponse"/>
<xs:complexType name="sayHello">
<xs:sequence>
<xs:element minOccurs="0" name="toWhom" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="sayHelloResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
好了,知道了这些,那么就来看一下怎样进行参数传递吧。
在传递到调用WebService这个Action之前,配置一个Action,这个Action的主要内容如下:
public Message process(Message message) throws Exception
{
//将消息内容取出
String msgBody = (String) message.getBody().get();
//设置参数
HashMap requestMap = new HashMap();
//sayHello为方法名,toWhom是参数
requestMap.put("sayHello.toWhom", msgBody);
message.getBody().add(requestMap);
return message;
}
可以看到其独特的设置参数的方式,那么执行完调用WebService后,返回值又会是什么样的呢?其实通过方法调用的设置参数方式,或许你已经想到了。就是在执行WebService后,再配置一个Action,从这个Action中取得消息体,然后将其转为Map,用"方法名Response.return"这个key从Map取得值即可。光说抽象,上代码:
public Message process(Message message) throws Exception
{
Map responseMsg = (Map) message.getBody().get(Body.DEFAULT_LOCATION);
System.out.println("Response Map is: " + responseMsg);
return message;
}
最后,再看一下这个responseMsg是什么:
一直在说调用WebService之前之后配置Action,下面再看一下Service的Action排布吧:
<action name="设置参数"
class="设置参数的类">
</action>
<action name="soapui-client-action"
class="org.jboss.soa.esb.actions.soap.SOAPClient">
<property name="wsdl" value="这里是WSDL的URL" />
<!--property name="wsdlTransform" value="如果是本地的xml,那么用这个属性" / -->
<property name="responseAsOgnlMap" value="true" /><!--如果有返回值,且以Map的方式返回,就这样配置-->
<property name="SOAPAction" value="sayHello"/><!--别说你不知道这个是干嘛的啊-->
</action>
<action name="处理结果"
class="处理结果的类">
</action>
<action name="其它处理" class="其它处理类"/>
文中的代码都是我把可以运行的代码进行简化后贴上来的,不知道大家是否喜欢这样的代码风格。这个代码的原码在JBossESB中就有,是webservice_consumer1这个实例。
最后,再总结一下ESB调用WebService这个举动。
如果你的ESB服务只是调用一个WebService,然后就没有了其它的动作,也不会再有,那么我感觉真的没有必要来多此一举,但是如果你考虑今后的服务可扩展,那么就用上,因为它扩展起来只需要你写一个类,然后配置进去就OK。这点对于只增加,不修改,真的是完美支持。