工作需要想要实现一个动态调用Web Service的客户端,希望不同的Web Service只需要提供出WSDL URI和需要的输入参数值,就可以方便的得到Web Service的输出结果。于是一直盘旋于AXIS和CXF的代码中,源码看了一大堆,办法想尽,实现无数,效果却不尽理想。
忽然想到,Web Service底层就是SOAP的XML格式的Request与Response,如果我组装好Request的XML,然后直接用SOAP 进行Connect和call,拿到Response后进行拆包岂不就可以实现动态的client端?CXF和AXIS/2说到底就是把XML的组装的分拆进行了封装,而恰好是这些封装,导致了很多时候出现Web Service通用性问题。
调出JDK API,直接查找javax.xml.soap包,寥寥几行代码解决了让我头疼一个月的问题:
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import javax.xml.messaging.URLEndpoint;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import org.apache.log4j.Logger;
/**
* SOAP底层方式实现与Web Service通讯。
*
* @author Alex Woo
*
*/
public class DynamicSoapCall {
private static final Logger log = Logger.getLogger(DynamicSoapCall.class);
private String wsdlURI = null;
public DynamicSoapCall(String wsdlURI) throws Exception {
log.info("Reading WSDL document from '" + wsdlURI + "'");
this.wsdlURI = wsdlURI;
}
public SOAPMessage soapCall(String xmlString, String charsetName, String soapVersion) throws Exception {
if(null == xmlString) xmlString = "";
byte[] bytes = null;
if(null == charsetName || charsetName.trim().equals("")) {
bytes = xmlString.getBytes();
} else {
try {
bytes = xmlString.getBytes(charsetName);
} catch(UnsupportedEncodingException e) {
log.warn("不支持指定的字符集,将按照操作系统默认字符集转换。可能会导致发送数据(特别是中文字符等数据)乱码。");
bytes = xmlString.getBytes();
}
}
InputStream is = new ByteArrayInputStream(bytes);
return soapCall(is, soapVersion);
}
public SOAPMessage soapCall(InputStream is, String soapVersion) throws Exception {
MessageFactory mf = null;
if(null != soapVersion && soapVersion.trim().equals("1.2")) {
mf = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
} else {//SOAP 1.1 is default.
mf = MessageFactory.newInstance();
}
SOAPMessage message = null;
try {
message = mf.createMessage(null, is);
} catch(SOAPException e) {
throw new Exception("根据Request XML数据创建的SOAP Message消息无效。错误原因:" + e.getCause());
}
SOAPConnectionFactory soapFactory = SOAPConnectionFactory.newInstance();
SOAPConnection con = soapFactory.createConnection();
URLEndpoint endpoint=new URLEndpoint(wsdlURI);
SOAPMessage response=con.call(message, endpoint);
return response;
}
}
?
于是,我需要面对的就只剩下XML的生成与解析了。
有的时候,抛开现成的框架,问题处理起来反而简单啊!
?
1 楼
brooklyng60
2012-04-26
能详细点吗,这种方式就是想达到的,不用写客户端,cxf,axis无非就是自己封装了一下,怎么调用啊
比如说现在有一个
getMessage方法,接收3个参数,返回1个参数,怎么做啊
比如说现在有一个
getMessage方法,接收3个参数,返回1个参数,怎么做啊