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消息,建议规定方法的命名空间,以避免不必要的错误。