实现一个Web服务的过程,大概有3个基本的过程:
- Web服务提供者设计并开发Web服务
- Web服务提供者发布Web服务
- Web服务请求者调用Web服务
下面,我通过一个例子,来实现上述过程:
假设一个Web服务提供者提供一个对域名进行探测解析的服务,给定一个域名,可以给出改域名解析后对应的IP地址列表。Web服务提供者设计并开发这个Web服务,然后将服务发布出去,并可以让Web服务请求者进行调用。
开发Web服务
服务接口文件DetectionService.java代码如下所示:
package org.shirdrn.server.webservices.jaxws;
public interface DetectService {
DetectedResult detect(String domain);
}
对应的实现类DomainDetectionService.java,如下所示:
package org.shirdrn.server.webservices.jaxws;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import org.xbill.DNS.Address;
@WebService(serviceName = "DomainDetector",portName = "DomainDetectorPort",
targetNamespace = "http://ws.shirdrn.org/jaxws/WSDomainDetector")
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,use=SOAPBinding.Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
public class DomainDetectService implements DetectService {
@WebMethod
public DetectedResult detect(String domain) {
DetectedResult result = new DetectedResult();
result.setStartTime(new Date());
try {
InetAddress[] addresses = Address.getAllByName(domain);
for(InetAddress addr : addresses) {
result.getIpAddresses().add(addr.getHostAddress());
}
} catch (UnknownHostException e) {
e.printStackTrace();
} finally {
result.setFinishTime(new Date());
result.setTimeTaken(result.getFinishTime().getTime() - result.getStartTime().getTime());
}
return result;
}
}
上面用到一个DtectedResult类,如下所示:
package org.shirdrn.server.webservices.jaxws;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class DetectedResult {
private Date startTime;
private Date finishTime;
private long timeTaken;
private List<String> ipAddresses = new ArrayList<String>();
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getFinishTime() {
return finishTime;
}
public void setFinishTime(Date finishTime) {
this.finishTime = finishTime;
}
public long getTimeTaken() {
return timeTaken;
}
public void setTimeTaken(long timeTaken) {
this.timeTaken = timeTaken;
}
public List<String> getIpAddresses() {
return ipAddresses;
}
public void setIpAddresses(List<String> ipAddresses) {
this.ipAddresses = ipAddresses;
}
}
生成Web Service描述文件(WSDL),如下所示:
shirdrn@SYJ:~$ cd ~/programs/eclipse-java-juno/workspace/self_practice/bin shirdrn@SYJ:~/programs/eclipse-java-juno/workspace/self_practice/bin$ wsgen -cp . org.shirdrn.server.webservices.jaxws.DomainDetectService -wsdl shirdrn@SYJ:~/programs/eclipse-java-juno/workspace/self_practice/bin$ ls com DomainDetector_schema1.xsd DomainDetector.wsdl log4j.properties main org server.xml test shirdrn@SYJ:~/programs/eclipse-java-juno/workspace/self_practice/bin$ cp DomainDetect* /home/shirdrn/programs/eclipse-java-juno/workspace/self_practice/src/org/shirdrn/server/webservices/jaxws/wsdl
经过上面步骤,生成了两个文件:DomainDetect_schema1.xsd和DomainDetect.wsdl,内容分别如下所示:
- DomainDetector_schema1.xsd内容
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" targetNamespace="http://ws.shirdrn.org/jaxws/WSDomainDetector"
xmlns:tns="http://ws.shirdrn.org/jaxws/WSDomainDetector" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="detect" type="tns:detect" />
<xs:element name="detectResponse" type="tns:detectResponse" />
<xs:complexType name="detect">
<xs:sequence>
<xs:element name="arg0" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="detectResponse">
<xs:sequence>
<xs:element name="return" type="tns:detectedResult" minOccurs="0" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="detectedResult">
<xs:sequence>
<xs:element name="finishTime" type="xs:dateTime" minOccurs="0" />
<xs:element name="ipAddresses" type="xs:string" nillable="true"
minOccurs="0" maxOccurs="unbounded" />
<xs:element name="startTime" type="xs:dateTime" minOccurs="0" />
<xs:element name="timeTaken" type="xs:long" />
</xs:sequence>
</xs:complexType>
</xs:schema>
- DomainDetector.wsdl内容
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS
RI 2.1.6 in JDK 6. -->
<definitions targetNamespace="http://ws.shirdrn.org/jaxws/WSDomainDetector"
name="DomainDetector" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws.shirdrn.org/jaxws/WSDomainDetector"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<types>
<xsd:schema>
<xsd:import namespace="http://ws.shirdrn.org/jaxws/WSDomainDetector"
schemaLocation="DomainDetector_schema1.xsd" />
</xsd:schema>
</types>
<message name="detect">
<part name="parameters" element="tns:detect" />
</message>
<message name="detectResponse">
<part name="parameters" element="tns:detectResponse" />
</message>
<portType name="DomainDetectService">
<operation name="detect">
<input message="tns:detect" />
<output message="tns:detectResponse" />
</operation>
</portType>
<binding name="DomainDetectorPortBinding" type="tns:DomainDetectService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<operation name="detect">
<soap:operation soapAction="" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<service name="DomainDetector">
<port name="DomainDetectorPort" binding="tns:DomainDetectorPortBinding">
<soap:address location="REPLACE_WITH_ACTUAL_URL" />
</port>
</service>
</definitions>
可以看到,在wsdl文件中通过import引用了前面的schema文件,这个schema文件用于定义类型。
发布Web服务
我们可以发布我们上面开发的Web服务,代码如下所示:
package org.shirdrn.server.webservices.jaxws;
import javax.xml.ws.Endpoint;
public class PublishingServer {
public static void main(String[] args) {
String address = "http://172.0.8.212:9033/ws/services/DomainDetectService";
DetectService domainDetectService = new DomainDetectService();
Endpoint.publish(address, domainDetectService);
}
}
可以查看本地运行的Web服务进程:
shirdrn@SYJ:~/programs/eclipse-java-juno/workspace/self_practice/src/org/shirdrn/server/webservices/jaxws$ sudo netstat -nap | grep 9033 tcp6 0 0 172.0.8.212:9033 :::* LISTEN 8302/java shirdrn@SYJ:~/programs/eclipse-java-juno/workspace/self_practice/src/org/shirdrn/server/webservices/jaxws$ jps 8302 PublishingServer 8358 Jps
可见,服务发布成功。
也可以在浏览器中打开链接:http://172.0.8.212:9033/ws/services/DomainDetectService?wsdl,就能看到发布的WSDL,内容如下所示:
<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. --> <!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. --> <definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ws.shirdrn.org/jaxws/WSDomainDetector" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.shirdrn.org/jaxws/WSDomainDetector" name="DomainDetector"> <types> <xsd:schema> <xsd:import namespace="http://ws.shirdrn.org/jaxws/WSDomainDetector" schemaLocation="http://172.0.8.212:9033/ws/services/DomainDetectService?xsd=1" /> </xsd:schema> </types> <message name="detect"> <part name="parameters" element="tns:detect" /> </message> <message name="detectResponse"> <part name="parameters" element="tns:detectResponse" /> </message> <portType name="DomainDetectService"> <operation name="detect"> <input message="tns:detect" /> <output message="tns:detectResponse" /> </operation> </portType> <binding name="DomainDetectorPortBinding" type="tns:DomainDetectService"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> <operation name="detect"> <soap:operation soapAction="" /> <input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding> <service name="DomainDetector"> <port name="DomainDetectorPort" binding="tns:DomainDetectorPortBinding"> <soap:address location="http://172.0.8.212:9033/ws/services/DomainDetectService" /> </port> </service> </definitions>
调用Web服务
首先要根据服务提供者发布的Web服务,生成服务请求者客户端代码,如下所示:
shirdrn@SYJ:~/programs/eclipse-java-juno/workspace/self_practice/bin$ wsimport -keep -p org.shirdrn.client.webservices.jaxws http://172.0.8.212:9033/ws/services/DomainDetectService?wsdl parsing WSDL... generating code... compiling code... shirdrn@SYJ:~/programs/eclipse-java-juno/workspace/self_practice/bin$ cd org/shirdrn/client/webservices/jaxws/ shirdrn@SYJ:~/programs/eclipse-java-juno/workspace/self_practice/bin/org/shirdrn/client/webservices/jaxws$ cp *.java /home/shirdrn/programs/eclipse-java-juno/workspace/self_practice/src/org/shirdrn/client/webservices/jaxws shirdrn@SYJ:~/programs/eclipse-java-juno/workspace/self_practice/bin/org/shirdrn/client/webservices/jaxws$ cd ~/programs/eclipse-java-juno/workspace/self_practice/src/org/shirdrn/client/webservices/jaxws/ shirdrn@SYJ:~/programs/eclipse-java-juno/workspace/self_practice/src/org/shirdrn/client/webservices/jaxws$ ls DetectedResult.java DetectResponse.java DomainDetector.java ObjectFactory.java Detect.java DomainDetectService.java package-info.java
上面自动生成了客户端代码的骨架,如下几个文件:
- DetectedResult.java
- DetectResponse.java
- DomainDetector.java
- ObjectFactory.java
- Detect.java
- DomainDetectService.java
- package-info.java
基于这些代码,就可以实现服务请求者对服务提供者发布服务的调用。我们实现了一个简单的调用,代码如下所示:
package org.shirdrn.client.webservices.jaxws;
public class DomainDetectClient {
public static void main(String[] args) {
DomainDetector detector = new DomainDetector();
String domain = "baidu.com";
DetectedResult result = detector.getDomainDetectorPort().detect(domain);
System.out.println(result.getIpAddresses());
}
}
调用后可以返回对域名进行解析后得到的IP地址列表,结果如下所示:
[220.181.111.86, 123.125.114.144, 220.181.111.85]
到此为止,我们完成了一个简单的Web Service的开发、发布、调用的过程。
参考链接
- http://www.ibm.com/developerworks/cn/education/webservices/ws-jax/section4.html
- http://mxdxm.iteye.com/blog/728539

本文基于署名-非商业性使用-相同方式共享 4.0许可协议发布,欢迎转载、使用、重新发布,但务必保留文章署名时延军(包含链接:http://shiyanjun.cn),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。