解决workshop开发的服务器端与axis开发的客户端之间的交互通信问题
解决workshop开发的服务器端与axis开发的客户端之间的交互通信问题
解决workshop开发的服务器端与axis开发的客户端之间的交互通信问题
1。用workshop开发web services的方法就是简单的jws的开发形式,相对比较简单。可以立即部署到相关的服务器之上。
其jws文件如下:
ublic class Test implements com.bea.jws.WebService
{
static final long serialVersionUID = 1L;
/**
* @common:operation
*/
public String convert(String name)
{
return 'hello'+','+name;
}
}
现在看一下其正确的请求soap消息:
<SOAP-ENV:Envelope xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<SOAP-ENV:Body>
<convert xmlns='http://www.openuri.org/'>
<name>string</name>
</convert>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
2。一般编写的axis客户端访问程序如下:
mport javax.xml.rpc.ParameterMode;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
public class ServiceClient{
public static void main(String[] args) throws Exception{
String endpoint='http://localhost:7001/axis/services/Version';
String name='gaolong1';
Service service=new Service();
Call call=(Call) service.createCall();
call.setUsername('gaolong1');
call.setPassword('19831001');
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.setOperationName('convert ');
call.addParameter('name',XMLType.XSD_STRING,ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);//XMLType.XSD_STRING);
String ret=(String)call.invoke(new Object[] {});
System.out.println(ret);
}
}
它产生的soap消息是:
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<soapenv:Body>
<convert soapenv:encodingStyle='http://schemas.xmlsoap.org /soap/encoding/'>
<name xsi:type='xsd:string'>gaolong1</name>
</convert>
</soapenv:Body></soapenv:Envelope>
3。运行服务器和客户端之后,会发现soap错误-xml解析错误。这说明了原因在于这两个soap消息不兼容。 问题在于不支持soapenv:encodingStyle='“,而支持xmlns='http://www.openuri.org/'以及 xmlType类型。通过编程的办法使之得到与之间容的soap消息。
产生的 原因在生成的wsdl文档中:
<types>
- <s:schema xmlns:s='http://www.w3.org/2001/XMLSchema' elementFormDefault='qualified' targetNamespace='http://www.openuri.org/'>//已经指定名称空间,该名称空间,是workshop开发jws默认给的描述部署的命名空间,要求对应的soap请求消息引用该名称空间
- <s:element name='convert'>
- <s:complexType>
- <s:sequence>
<s:element name='name' type='s:string' minOccurs='0' />
</s:sequence>
</s:complexType>
</s:element>
- <s:element name='convertResponse'>
+ <s:complexType>
- <s:sequence>
<s:element name='convertResult' type='s:string' minOccurs='0' />
</s:sequence>
</s:complexType>
</s:element>
<s:element name='string' nillable='true' type='s:string' />
</s:schema>
</types>
4。解决方法:重新编写axis客户端使之产生合理的soap消息。使之生成与workshop对应的jws文件及部署成的web services相兼容的soap消息。
其代码如下:
import javax.xml.rpc.ParameterMode;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import javax.xml.namespace.QName;
import org.apache.axis.soap.SOAP11Constants;
import java.*;
//import javax.xml.soap.*;
//import org.apache.axis.message.SOAPHeaderElement;
public class ServiceClient{
public static void main(String[] args) throws Exception{
String endpoint='http://localhost:7001/Test/Test.jws';
String name='gaolong1';
Service service=new Service();
Call call=(Call) service.createCall();
// call.setUsername('gaolong1');
// call.setPassword('831001');
/* SOAPHeaderElement se=new SOAPHeaderElement(new QName(''));
se.setEncodingStyle('http://schemas.xmlsoap.org/soap/encoding/');
call.addHeader(se);*///添加命名到soapheader中
/*SOAP11Constants sx=new SOAP11Constants();
call.setSOAPVersion(sx);选择soap的版本*/
call.setTargetEndpointAddress(new java.net.URL(endpoint));
// call.setEncodingStyle(null);//消息编码,如果有这条语句的话,就会出现按下面的语句生成各自的xmlns,而且没有编码描述。否则的话根据开发时设定的命名空间namespace灵活生成soap
// call.setOperationName('convert');
// call.setEncodingStyle('http://schemas.xmlsoap.org/soap/encoding/');
call.setOperationName(new QName('http://www.openuri.org/', 'convert'));//指定方法的命名空间
call.addParameter(new QName('http://www.openuri.org/', 'name'),XMLType.XSD_STRING,Class.forName('java.lang.String'),ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);//XMLType.XSD_STRING);//用Class.forName('java.lang.String')来获取java类型
String ret=(String)call.invoke(new Object[] {name});
System.out.println(ret);
}
}
5。产生的soap消息:
(1)。使用了 call.setEncodingStyle(null)。
请求的soap消息:
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsd='http://www.w3.org/001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<soapenv:Body>
<convert xmlns='http://www.openuri.org/'>
<name xsi:type='xsd:string'>gaolong1</name>
</convert>
</soapenv:Body></soapenv:Envelope>
回应的soap消息:
<?xml version='1.0' encoding='utf-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<SOAP-ENV:Body>
<ns:convertResponse xmlns:ns='http://www.openuri.org/'>
<ns:convertResult>hello,gaolong1</ns:convertResult></ns:convertResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
(2)。没有使用call.setEncodingStyle(null)。
请求的soap消息:
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<soapenv:Body>
<ns1:convert soapenv:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:ns1='http://www.openuri.org/'>
<ns1:name xsi:type='xsd:string'>gaolong1</ns1:name></ns1:convert>
</soapenv:Body>
</soapenv:Envelope>
6。总结:虽然有时使用axix编写的客户端程序不一定都需要给每个方法规定相应的命名空间(可查看wsdl),但是产生可行的soap消息,建议规定方法的命名空间,以避免不必要的错误。