我们通过wsld来生成java代码,都会把参数和返回值包装成一个类。
在返回的参数类中,我们加上一个成员变量address,address为Address类的一个实例。我们看看wsld文件中wsdl:type标签中的表述。
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://test.chm.com/" elementFormDefault="unqualified" targetNamespace="http://test.chm.com/" version="1.0">
<xs:element name="parameterName" type="tns:paramType"/>
<xs:element name="resultName" type="tns:resultType"/>
<xs:complexType name="paramType">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string"/>
<xsd:element name="address" type="tns:address"></xsd:element><!-- 关键点-->
</xs:sequence>
</xs:complexType>
<xs:complexType name="resultType">
<xs:sequence>
<xs:element minOccurs="0" name="helloResult" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xsd:complexType name="address">
<xsd:sequence>
<xsd:element name="shoolAddress" type="xsd:string"></xsd:element>
<xsd:element name="homeAddress" type="xsd:string"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xs:schema>
</wsdl:types>
再看看参数类
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "paramType", propOrder = {
"name",
"address"
})
public class ParamType {
protected String name;
@XmlElement(required = true)
protected Address address;
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
public Address getAddress() {
return address;
}
public void setAddress(Address value) {
this.address = value;
}
}
我们看一下wsld中关键部分
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://test.chm.com/" elementFormDefault="unqualified" targetNamespace="http://test.chm.com/" version="1.0">
<xs:element name="parameterName" type="tns:paramType"/>
<xs:element name="resultName" type="tns:resultType"/>
<xs:complexType name="paramType">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="resultType">
<xs:sequence>
<xs:element minOccurs="0" name="helloResult" type="xs:string"/>
<xsd:element name="addrList" type="tns:addr" minOccurs="0" maxOccurs="unbounded"></xsd:element>
</xs:sequence> <!-- 关键点 -->
</xs:complexType>
<xsd:complexType name="addr">
<xsd:sequence>
<xsd:element name="shoolAddress" type="xsd:string"></xsd:element>
<xsd:element name="homeAddress" type="xsd:string"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xs:schema>
</wsdl:types>
对应生成的返回类
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "resultType", propOrder = {
"helloResult",
"addrList"
})
public class ResultType {
protected String helloResult;
protected List<Addr> addrList;
public String getHelloResult() {
return helloResult;
}
public void setHelloResult(String value) {
this.helloResult = value;
}
public List<Addr> getAddrList() {
if (addrList == null) {
addrList = new ArrayList<Addr>();
}
return this.addrList;
}
}
我们看一下wsld中关键代码部分
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://test.chm.com/" elementFormDefault="unqualified" targetNamespace="http://test.chm.com/" version="1.0">
<xs:element name="parameterName" type="tns:paramType"/>
<xs:element name="resultName" type="tns:resultType"/>
<xs:complexType name="paramType">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string"/>
<xsd:element name="grade" type="tns:grade"></xsd:element> <!-- 一个枚举类型的成员变量 -->
</xs:sequence>
</xs:complexType>
<xs:complexType name="resultType">
<xs:sequence>
<xs:element minOccurs="0" name="helloResult" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xsd:simpleType name="grade"> <!-- 声明枚举类型 -->
<xsd:restriction base="xsd:string">
<xsd:enumeration value="excellent"></xsd:enumeration>
<xsd:enumeration value="medium"></xsd:enumeration>
<xsd:enumeration value="pass"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xs:schema>
</wsdl:types>
wsld中空类型的表示
<xsd:complexType>
<xsd:sequence/>
</xsd:complexType>
在wsld中如何表示一个文件的上传?用字节数组,然后就是IO的操作了
<xs:complexType name="paramType">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string"/>
<xsd:element name="file" type="xsd:base64Binary"></xsd:element> <!-- 关键点 -->
</xs:sequence>
</xs:complexType>
对应生成的java代码
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "paramType", propOrder = {
"name",
"file"
})
public class ParamType {
protected String name;
@XmlElement(required = true)
protected byte[] file;
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
public byte[] getFile() {
return file;
}
public void setFile(byte[] value) {
this.file = value;
}
}
对于小文件这样传输是没问题,但是对于大的文件(几兆以上吧)就可能报内存溢出的错误了,那么我们需要使用另一种方法,Using MTOM(SOAP Message Transmission Optimization Mechanism ),可到连接这个地址查看
<xs:complexType name="paramType">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string"/>
<xsd:element name="file" type="xsd:base64Binary" xmime:expectedContentTypes="application/octet-stream"/> <!-- -->
</xs:sequence>
</xs:complexType>
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "paramType", propOrder = {
"name",
"file"
})
public class ParamType {
protected String name;
@XmlElement(required = true)
@XmlMimeType("application/octet-stream")
protected DataHandler file;
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
public DataHandler getFile() {
return file;
}
public void setFile(DataHandler value) {
this.file = value;
}
}
cxf默认情况下没有开启对MTOM的支持,我们需要同时在客户端和服务端开启对MTOM的支持。
客户端
StudentService ss = new StudentService(wsdlURL, SERVICE_NAME);
People port = ss.getStudentPort();
SOAPBinding binding = (SOAPBinding) ((BindingProvider)port).getBinding();
binding.setMTOMEnabled(true);
System.out.println("Invoking sayGood...");
com.chm.test.ParamType parameters = new ParamType();
DataSource dataSource = new FileDataSource(new File("D:/test.xls"));
parameters.setFile(new DataHandler(dataSource));
parameters.setName("aa");
port.sayGood(parameters);
服务端
Object implementor = new StudentPortImpl();
String address = "http://localhost:8080/myservice3";
Endpoint ep = Endpoint.publish(address, implementor);
SOAPBinding binding = (SOAPBinding)ep.getBinding();
binding.setMTOMEnabled(true);
web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:jaxws="http://cxf.apache.org/jaxws" <!-- 增加命名空间 --> xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml"/> <!--<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>--> <!--<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>--> <jaxws:endpoint id="myservice" implementor="com.chm.test.MyServiceImpl" address="/myserver"></jaxws:endpoint> </beans>
客户端
<jaxws:client id="service" address="http://localhost:8080/myserver" serviceClass="com.chm.test.MyService"></jaxws:client>