实现一个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),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。