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