WebService入门

来源:互联网 发布:淘宝打单插件 编辑:程序博客网 时间:2024/06/06 00:34

转载:http://blog.csdn.net/opopopwqwqwq/article/details/51758862

Webservice:跨语言跨平台的远程调用技术

WebService定义: 顾名思义就是基于Web的服务。它使用Web(HTTP)方式,接收和响应外部系统的某种请求。从而实现远程调用。

 

Webservice理解:我们可以调用互联网上查询天气信息Web服务,然后将它嵌入到我们的程序(C/S或B/S程序)当中来,当用户从我们的网点看到天气信息时,他会认为我们为他提供了很多的信息服务,但其实我们什么也没有做,只是简单了调用了一下服务器上的一段代码而已。WebSerice可以将你的服务(一段代码)发布到互联网上让别人去调用,也可以调用别人机器上发布的WebService,就像使用自己的代码一样.。

 

 

1     远程调用的案例(模拟远程调用天气预报服务)

便民查询网站的分析

 

天气信息必须通过远程调用的方式获得。

 

远程调用的方法

1.1.1       Socket实现远程调用

 

1.1.1.1    实现步骤:

服务端:

第一步:创建一个Java工程

第二步:使用ServerSocket创建一个服务。需要指定服务的端口号。

第三步:调用accept()方法等待客户端建立连接。

第四步:建立连接后使用输入流读取客户端发送的城市名称

第五步:查询天气信息。模拟。

第六步:使用输出流返回天气信息。

第七步:关闭输入输出流。服务端不关闭连接,等待客户端关闭。

 

客户端

第一步:创建一个java工程

第二步:使用Socket类和服务端建立连接。需要指定ip和端口。

第三步:使用输出流发送城市名称

第四步:使用输入流读取服务端返回的结果

第五步:打印结果。

 

1.1.1.2    代码实现

开发环境:要求jdk1.7以上

开发工具:eclipse indigo

 

服务端

[java] view plain copy
  1. public class WeatherServer {  
  2.   
  3.     public static void main(String[] args) {  
  4.           
  5.         try {  
  6.             // 创建一个Socket服务  
  7.             // 参数:服务的端口号,建议大一些0-1024是系统留用端口  
  8.             ServerSocket serverSocket = new ServerSocket(12345);  
  9.             System.out.println("服务端已启动。。。。。");  
  10.             while(true) {  
  11.                 // 等待客户端建立连接  
  12.                 // 阻塞的方法,建立连接后向下执行  
  13.                 final Socket socket = serverSocket.accept();  
  14.                 Runnable runnable = new Runnable() {  
  15.                       
  16.                     @Override  
  17.                     public void run() {  
  18.                         DataInputStream inputStream = null;  
  19.                         DataOutputStream outputStream = null;  
  20.                         try {  
  21.                         // 使用输入流读取客户端发送的数据  
  22.                         inputStream = new DataInputStream(socket.getInputStream());  
  23.                         String cityName = inputStream.readUTF();  
  24.                         System.out.println("接收到客户端发送的数据:" + cityName);  
  25.                         // 根据城市查询天气  
  26.                         System.out.println("查询天气。。。。");  
  27.                         Thread.sleep(1000);  
  28.                         String resultString = "阴天转雷阵雨";  
  29.                         outputStream = new DataOutputStream(socket.getOutputStream());  
  30.                         // 返回查询结果  
  31.                         System.out.println("返回查询结果:" + resultString);  
  32.                         outputStream.writeUTF(resultString);  
  33.                         } catch (Exception e) {  
  34.                             // TODO: handle exception  
  35.                         }finally {  
  36.                             // 关闭流  
  37.                             try {  
  38.                                 inputStream.close();  
  39.                                 outputStream.close();  
  40.                             } catch (IOException e) {  
  41.                                 // TODO Auto-generated catch block  
  42.                                 e.printStackTrace();  
  43.                             }  
  44.                         }  
  45.                           
  46.                     }  
  47.                 };  
  48.                 //启动线程  
  49.                 new Thread(runnable).start();  
  50.             }  
  51.         } catch (Exception e) {  
  52.             // TODO: handle exception  
  53.         }   
  54.   
  55.     }  
  56. }  


 

客户端

[java] view plain copy
  1. public class WeatherClient {  
  2.   
  3.     public static void main(String[] args) throws Exception {  
  4.         while (true) {  
  5.             // 创建一个socket连接  
  6.             Socket socket = new Socket("127.0.0.1"12345);  
  7.             // 使用输出流发送城市名称  
  8.             DataOutputStream outputStream = new DataOutputStream(  
  9.                     socket.getOutputStream());  
  10.             // 发送城市名称  
  11.             outputStream.writeUTF("北京");  
  12.             // 接收返回的结果  
  13.             DataInputStream inputStream = new DataInputStream(  
  14.                     socket.getInputStream());  
  15.             String resultString = inputStream.readUTF();  
  16.             System.out.println("天气信息:" + resultString);  
  17.             // 关闭流  
  18.             inputStream.close();  
  19.             outputStream.close();  
  20.         }  
  21.     }  
  22.   
  23. }  

Socket要求服务端有持续服务能力,而且要实现多线程。编码比较麻烦。

 

1.1.2       Webservice实现远程调用

1.1.2.1    实现步骤

服务端

1.    编写SEI(ServiceEndpoint Interface),SEI在WSDL中称为portType,在java中称为接口。

2.    编写sei实现类,需要实现SEI接口,而且还要求在实现类上添加一个@Webservice注解。

3.    发布服务。使用Endpoint的静态方法publish。

 

1.1.2.2    代码实现

Sei

[java] view plain copy
  1. public interface WeatherInterface {  
  2.   
  3.     String queryWeather(String cityName);  
  4. }  


SEI实现类

 

[java] view plain copy
  1. @WebService  
  2. //加上此注解传输时使用soap1.2版本的协议  
  3. @BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)  
  4. public class WeatherInterfaceImpl implements WeatherInterface {  
  5.   
  6.     @Override  
  7.     public String queryWeather(String cityName) {  
  8.         System.out.println("接收到客户端发送的城市名称:" + cityName);  
  9.         //查询天气信息  
  10.         String result = "雷阵雨";  
  11.         //返回查询结果  
  12.         return result;  
  13.     }  
  14. }  

 

发布服务

[java] view plain copy
  1. public class WeatherServer {  
  2.   
  3.     public static void main(String[] args) {  
  4.         //发布服务  
  5.         //第一个参数:服务发布的地址,就是一个url  
  6.         //第二个参数:SEI实现类对象  
  7.         Endpoint.publish("http://127.0.0.1:12345/weather"new WeatherInterfaceImpl());  
  8.     }  
  9. }  


 

1.1.2.3    服务启动成功的判断

访问服务发布地址+?wsdl查看服务的wsdl。如果wsdl中有porttype就说明服务发布成功。

 

1.1.2.4    Wsimport生成客户端调用代码

Wsimport路径就在jdk的bin目录下。

使用方法

wsimport是jdk自带的webservice客户端工具,可以根据wsdl文档生成客户端调用代码(java代码).当然,无论服务器端的WebService是用什么语言写的,都可以生成调用webservice的客户端代码,服务端通过客户端代码调用webservice。

wsimport.exe位于JAVA_HOME\bin目录下.

常用参数为:

-d<目录>  - 将生成.class文件。默认参数。

-s<目录> - 将生成.java文件。

-p<生成的新包名> -将生成的类,放于指定的包下。如果不指定此参数包名就是wsdl命名空间的倒序

(wsdlurl)- http://server:port/service?wsdl,必须的参数。

示例:

C:/>wsimport –s . http://127.0.0.1:1234/weather?wsdl

注意:-s不能分开,-s后面有个小点

 

1.1.2.5    客户端创建

1.1.2.5.1 实现步骤

利用生成的代码创建客户端。

第一步:创建一个服务视图对象。

第二步:从服务视图获得porttype(SEI)对象。

第三步:调用服务端方法

第四步:打印结果

 

1.1.2.5.2 代码实现

[java] view plain copy
  1. public class WeatherClient {  
  2.   
  3.     public static void main(String[] args) {  
  4.           
  5.         //创建服务视图  
  6.         WeatherInterfaceImplService service = new WeatherInterfaceImplService();  
  7.         //获得porttype对象  
  8.         WeatherInterfaceImpl portType = service.getWeatherInterfaceImplPort();  
  9.         //调用服务端方法  
  10.         String result = portType.queryWeather("北京");  
  11.         System.out.println(result);  
  12.           
  13.     }  
  14. }  


 

1.1.3       Webservice和socket技术对比

Socket是所有通信的基础也是语言个无关平台无关。

Socket使用的是tcp协议,传输效率高。适合传递大数据高并发场景,高并发的情况需要实现多线程并且使用到线程池,编码复杂。Sockt的高并发框架mina。

Socket只是流的传输,传输的格式需要程序员自己定义。

Webservice使用的是soap协议,soap协议基于http协议的应用层协议,本质就是http+xml。Soap协议是w3c标准,传输效率低。使用传输数据不是太大的场合,也是支持高并发的,受限于web容器。支持soap协议和wsdl两者都是国际通用标准,不需要自定义数据格式,只需要面向对象开发。

 

2     什么是webservice

Webservice 即web服务,它是一种跨编程语言和跨操作系统平台的远程调用技术即跨平台远程调用技术。

JAVA 中共有三种WebService 规范,分别是JAX-WS(JAX-RPC)JAXM&SAAJJAX-RS

Webservice的三种规范


2.1.1       JAX-WS

JAX-WS  的全称为 Java API for XML-BasedWebservices ,早期的基于SOAP 的JAVA 的Web 服务规范JAX-RPC(java API For XML-Remote ProcedureCall)目前已经被JAX-WS 规范取代。从java5开始支持JAX-WS2.0版本,Jdk1.6.0_13以后的版本支持2.1版本,jdk1.7支持2.2版本。

    采用标准SOAP(SimpleObject Access Protocol)  协议传输,soap属于w3c标准。Soap协议是基于http的应用层协议,soap协议传输是xml数据。

    采用wsdl作为描述语言即webservice使用说明书,wsdl属w3c标准。

    xml是webservice的跨平台的基础,XML主要的优点在于它既与平台无关,又与厂商无关。

    XSD,W3C为webservice制定了一套传输数据类型,使用xml进行描述,即XSD(XML Schema Datatypes),任何编程语言写的webservice接口在发送数据时都要转换成webservice标准的XSD发送。


2.1.2       JAXM&SAAJ

JAXM(JAVA API For XML Message)主要定义了包含了发送和接收消息所需的API,SAAJ(SOAP With Attachment API For Java,JSR 67)是与JAXM 搭配使用的API,为构建SOAP 包和解析SOAP 包提供了重要的支持,支持附件传输等,JAXM&SAAJ 与JAX-WS 都是基于SOAP 的Web 服务,相比之下JAXM&SAAJ 暴漏了SOAP更多的底层细节,编码比较麻烦,而JAX-WS 更加抽象,隐藏了更多的细节,更加面向对象,实现起来你基本上不需要关心SOAP 的任何细节

 

2.1.3       JAX-RS

JAX-RS是JAVA 针对REST(Representation StateTransfer)风格制定的一套Web 服务规范,由于推出的较晚,该规范(JSR 311,目前JAX-RS 的版本为1.0)并未随JDK1.6 一起发行。

支持JAX-RS服务规范的框架有:

    CXF——XFire和Celtix的合并(一个由IONA赞助的开源ESB,最初寄存在ObjectWeb上)。

    Jersey——Sun公司的JAX-RS参考实现。

    RESTEasy——JBoss的JAX-RS项目。

    Restlet——也许是最早的REST框架了,它JAX-RS之前就有了。

 

注:REST 是一种软件架构模式,只是一种风格,rest服务采用HTTP 做传输协议

 

Webservice三要素


2.1.4       soap

SOAP即简单对象访问协议(Simple Object Access Protocal) 是一种简单的基于 XML 的协议,它使应用程序通过 HTTP 来交换信息,简单理解为soap=http+xml。

Soap协议版本主要使用soap1.1、soap1.2

 

2.1.5       wsdl

WSDL 是基于 XML 的用于描述Web Service及其函数、参数和返回值。通俗理解Wsdl是webservice的使用说明书。

 

2.1.6       UDDI

UDDI 是一种目录服务,通过它,企业可注册并搜索 Web services。企业将自己提供的Web Service注册在UDDI,也可以使用别的企业在UDDI注册的web service服务,从而达到资源共享。

UDDI旨在将全球的webservcie资源进行共享,促进全球经济合作。

但是使用webservice并不是必须使用UDDI,因为用户通过WSDL知道了web service的地址,可以直接通过WSDL调用webservice。

 

Webservice的应用场景

1.    企业中异构系统集成

在做企业整体信息化时,企业中一般都或多或少的存在一些既存系统,这些各种各样的系统不可能全部推翻,重新规划和开发,因为很多供应商在某一领域也做的很专业,博众家之长并进行集成应该是一个比较现实和可取的做法。各个系统之间通过WebService进行集成,不仅缩短了开发周期,降低了风险,还减少了代码复杂度,并能够增强应用程序的可维护性,因为webservice支持跨平台且遵循标准协议(soap)。

 

 

2.    软件扩展重用

将一个软件的功能以webservice方式暴露出来,达到软件重用。例如上边分析的天气预报,将天气查询功能以webservice接口方式暴露出来非常容易集成在其它系统中;再比如一个第三方物流系统将快递查询、快递登记暴露出来,从而集成在电子商务系统中。

 

3.    手机App服务端接口

现在几乎100%的手机App都需要联网和服务端有数据交互的行为。此时需要服务端开发服务接口也就是,Webservice接口。一般来说可以可使用rest风格的Webservice发布服务,手机App和服务之间传递xml或者json数据。

 

3     WSDL

Webservice的使用说明书。描述了webservice的服务地址以及webservice服务接口、参数、返回值。

 

 

Wsdl的阅读方法:从下往上读。

1、先找Service节点:每个wsdl中有且只有一个service节点,叫做服务视图节点。相当于插座的面板。Service节点中有port节点服务端端口。

2、根据port节点的binding属性找binding节点。根据binding节点的type属性找portType节点。

3、portType节点就是我们定义的SEI服务的接口类型。Prottype中的operation 节点就是方法名称。

4、operation 节点的input就是参数的定义,output就是返回值的定义。

5、Input有个属性叫做message,message属性对应message节点。其中有一个element,对应element节点。

6、Element节点定义中xsd中。定义了数据的类型。参数和返回值都在其中定义。


 wsdl图示



 schema



查询公网天气


3.1.1       实现步骤

第一步:生成客户端调用代码

第二步:创建服务视图

第三步:从服务视图获得portType对象

第四步:调用服务端方法。

 

3.1.2       代码实现

[java] view plain copy
  1. public class WeatherClient2 {  
  2.   
  3.     public static void main(String[] args) {  
  4.         //创建服务视图  
  5.         WeatherWebService service = new WeatherWebService();  
  6.         //从服务视图获得portType对象  
  7.         WeatherWebServiceSoap portType = service.getWeatherWebServiceSoap();  
  8.         //调用服务端方法查询天气  
  9.         ArrayOfString arrayOfString = portType.getWeatherbyCityName("三亚");  
  10.         //打印天气信息  
  11.         for (String string : arrayOfString.getString()) {  
  12.             System.out.println(string);  
  13.         }  
  14.     }  
  15. }  


3.1.3       第二种调用webservice的方法

第一种方法的缺点是,如果服务器的ip或者域名发生改变后需要重新生成客户端调用代码。需要把ip或者的域名配置到配置文件中,至少是可修改的。

 

使用Service类创建服务视图

[cpp] view plain copy
  1. public class WeatherClient {  
  2.   
  3.     public static void main(String[] args) {  
  4.         //创建服务视图  
  5.         //指定服务的url,可以是wsdl的地址也可以是服务的地址  
  6.         URL url = null;  
  7.         try {  
  8.             url = new URL("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL");  
  9.         } catch (MalformedURLException e) {  
  10.             // TODO Auto-generated catch block  
  11.             e.printStackTrace();  
  12.         }  
  13.         //第一个参数是wsdl的命名空间  
  14.         //第二个参数是service节点的name属性  
  15.         QName qName = new QName("http://WebXml.com.cn/""WeatherWebService");  
  16.         Service service = Service.create(url, qName);  
  17.         //从服务视图获得portType对象  
  18.         //WeatherWebServiceSoap portType = service.getWeatherWebServiceSoap();  
  19.         WeatherWebServiceSoap portType = service.getPort(WeatherWebServiceSoap.class);  
  20.         //调用服务端方法查询天气  
  21.         ArrayOfString arrayOfString = portType.getWeatherbyCityName("三亚");  
  22.         //打印天气信息  
  23.         for (String string : arrayOfString.getString()) {  
  24.             System.out.println(string);  
  25.         }  
  26.     }  
  27. }  


 

4     Soap

soap是什么

SOAP 是一种网络通信协议

SOAP即Simple Object Access Protocol简易对象访问协议

SOAP 用于跨平台应用程序之间的通信

SOAP 被设计用来通过因特网(http)进行通信

SOAP = HTTP+XML,其实就是通过HTTP发xml数据

SOAP 很简单并可扩展支持面向对象

SOAP 允许您跨越防火墙

SOAP 将被作为 W3C 标准来发展

 

使用TCP/IP Monitor监视Soap协议


TCP/IPMonitor是eclipse自带的工具。

是一个代理方式的查看协议体内容的工具。

 

 

 

Soap1.1

Webservice默认使用的是1.1版本的soap协议。

 

4.1.1       请求的协议体

头信息

[plain] view plain copy
  1. POST /weather HTTP/1.1  
  2. Accept: text/xml, multipart/related  
  3. Content-Type: text/xml; charset=utf-8  
  4. SOAPAction: "http://jaxws.itheima.com/WeatherInterfaceImpl/queryWeatherRequest"  
  5. User-Agent: JAX-WS RI 2.2.4-b01  
  6. Host: 127.0.0.1:54321  
  7. Connection: keep-alive  
  8. Content-Length: 210  
  9.   
  10. <?xml version="1.0" ?>  
  11. <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">  
  12.     <S:Body>  
  13.         <ns2:queryWeather xmlns:ns2="http://jaxws.itheima.com/">  
  14.             <arg0>北京</arg0>  
  15.         </ns2:queryWeather>  
  16.     </S:Body>  
  17. </S:Envelope>  




4.1.2       响应的协议体

[plain] view plain copy
  1. HTTP/1.1 200 OK  
  2. Transfer-encoding: chunked  
  3. Content-type: text/xml; charset=utf-8  
  4. Date: Wed, 24 Jun 2015 07:21:20 GMT  
  5.   
  6. <?xml version="1.0" ?>  
  7. <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">  
  8.     <S:Body>  
  9.         <ns2:queryWeatherResponse xmlns:ns2="http://jaxws.itheima.com/">  
  10.             <return>雷阵雨</return>  
  11.         </ns2:queryWeatherResponse>  
  12.     </S:Body>  
  13. </S:Envelope>  


结论就是:soap=http+xml

 

Soap1.2协议

如果使用soap1.2协议的话只需要在SEI实现类上添加一个注解即可。

@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)

Jdk自带的jax-ws API(JAX-WS RI 2.2.4-b01)不支持soap1.2版本的协议需要使用高版本的api。

需要使用到2.2.8版本的jax-ws的api。


使用soap1.2后wsdl的变化:

soap变成soap12 


Soap协议协议改变后,不需要重新生成客户端调用代码。

 

4.1.3       请求的协议体

[sql] view plain copy
  1. POST /weather HTTP/1.1  
  2. Accept: application/soap+xml, multipart/related  
  3. Content-Type: application/soap+xml; charset=utf-8;  
  4. action="http://jaxws.itheima.com/WeatherInterfaceImpl/queryWeatherRequest"  
  5. User-Agent: JAX-WS RI 2.2.4-b01  
  6. Host: 127.0.0.1:54321  
  7. Connection: keep-alive  
  8. Content-Length: 208  
  9.   
  10. <?xml version="1.0" ?>  
  11. <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">  
  12.     <S:Body>  
  13.         <ns2:queryWeather xmlns:ns2="http://jaxws.itheima.com/">  
  14.             <arg0>北京</arg0>  
  15.         </ns2:queryWeather>  
  16.     </S:Body>  
  17. </S:Envelope>  


 

4.1.4       响应的协议体

[plain] view plain copy
  1. HTTP/1.1 200 OK  
  2. Transfer-encoding: chunked  
  3. Content-type: application/soap+xml; charset=utf-8  
  4. Date: Wed, 24 Jun 2015 07:59:16 GMT  
  5.   
  6. <?xml version='1.0' encoding='UTF-8'?>  
  7. <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">  
  8.     <S:Body>  
  9.         <ns2:queryWeatherResponse xmlns:ns2="http://jaxws.itheima.com/">  
  10.             <return>雷阵雨</return>  
  11.         </ns2:queryWeatherResponse>  
  12.     </S:Body>  
  13. </S:Envelope>  


Soap1.1和soap1.2的区别

Content-type:

Soap1.1:Content-type: text/xml; charset=utf-8

Soap1.2:Content-type: application/soap+xml; charset=utf-8

Envelope标签的命名空间:

Soap1.1:<S:Envelopexmlns:S="http://schemas.xmlsoap.org/soap/envelope/">

Soap1.2:<S:Envelopexmlns:S="http://www.w3.org/2003/05/soap-envelope">

 

模拟httpclient调用webservice


4.1.5       实现步骤

第一步:创建一java工程

第二步:创建一个HttpURLConnection对象。可以使用URL对象的openConnection方法获得。

第三步:设置content-type,根据服务端使用的版本,设置不同的content-type。

第四步:编辑一个请求的xml格式的协议体发送给服务端。

第五步:接收服务端响应的内容。打印出来

 

4.1.6       代码的实现

使用http的方式调用服务端方法

[java] view plain copy
  1. public class SoapHttpClient {  
  2.   
  3.     public static void main(String[] args) throws Exception {  
  4.         URL url = new URL("http://127.0.0.1:54321/weather");  
  5.         //创建一个HttpURLConnection对象  
  6.         HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
  7.         //设置content-type  
  8.         //服务端是soap1.2的协议  
  9.         connection.setRequestProperty("Content-Type"" application/soap+xml; charset=utf-8;");  
  10.         //设置使用connection对象进行输入输出  
  11.         connection.setDoInput(true);  
  12.         connection.setDoOutput(true);  
  13.         //使用输出流向服务端发送xml数据  
  14.         connection.getOutputStream().write(getRequestBody("北京").getBytes());  
  15.         //接收服务端响应的内容  
  16.         InputStream inputStream = connection.getInputStream();  
  17.         byte[] b = new byte[1024];  
  18.         int len = 0;  
  19.         ByteArrayOutputStream data = new ByteArrayOutputStream();  
  20.         while((len = inputStream.read(b, 01024)) != -1) {  
  21.             data.write(b, 0, len);  
  22.         }  
  23.           
  24.         System.out.println(data);  
  25.           
  26.     }  
  27.     //拼装请求协议体  
  28.     private static String getRequestBody(String cityName) {  
  29.         String body = "<?xml version=\"1.0\" ?>\n" +  
  30.                 "<S:Envelope xmlns:S=\"http://www.w3.org/2003/05/soap-envelope\">\n" +  
  31.                 "   <S:Body>\n" +  
  32.                 "       <ns2:queryWeather xmlns:ns2=\"http://jaxws.itheima.com/\">\n" +  
  33.                 "           <arg0>"+cityName+"</arg0>\n" +  
  34.                 "       </ns2:queryWeather>\n" +  
  35.                 "   </S:Body>\n" +  
  36.                 "</S:Envelope>";  
  37.         return body;  
  38.     }  
  39.       
  40. }  

拼装xml字符串小技巧


 

5     案例:区域查询系统

5.1区域查询系统的结构

 

6.2需求

创建区域查询服务系统,对外发布WebService服务,供客户端调用,根据parentid查询区域信息。客户端向服务端传递xml格式数据,服务端向客户端响应xml格式数据。

 

6.3分析

基于soap协议的webservice就可以传递对象。

5.1.1       传递xml数据的原因:

1、跨语言时可能会花很长时间来调试,如果直接传递xml省去的调试的时间。参数和返回值都是字符串类型,非常简单。

2、如果参数发生变化后,可以不用修改接口,不用重新生成客户端调用代码。

3、Xml格式的数据是跨语音跨平台的。

 

5.1.2       架构分析

 

 

  

5.1.3       实现步骤:

服务端:

第一步:创建一个java工程

第二步:导入jar包需要MySQL的数据库驱动,dom4j的jar包。

第三步:创建一个SEI。

第四步:创建SEI实现类。调用dao查询区域列表。

1、接收客户端发送的xml

2、需要解析xml数据转换成java对象

3、查询数据库得到区域列表,使用jdbc查询。

4、把区域列表转换成xml数据

5、返回xml数据

第五步:发布服务,使用Endpoint的publish方法发布服务。

 

客户端:

1、生成客户端调用代码

2、创建服务视图

3、从服务视图获得porttype

4、调用服务端方法。

 

5.1.4       接口描述:

 

客户端发送数据格式:

[plain] view plain copy
  1. <?xml version="1.1"  encoding="utf-8"?>  
  2. <queryarea>  
  3. <parentid> </parentid>//父级区域id  
  4. <start></start>//起始记录,从1开始  
  5. <end></end>//结束记录  
  6. </queryarea>  


服务端响应数据格式:

[plain] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <areas>  
  3. <area>  
  4. <areaid> </areaid>//区域id  
  5. <areaname></areaname>//区域名称  
  6. <arealevel></arealevel>//区域等级  
  7. <parentid></parentid>//父级区域id  
  8. </area>  
  9. //…..  
  10. </areas>  


 

5.1.5       代码实现

5.1.5.1    Dao

[java] view plain copy
  1. public class AreaDao {  
  2.   
  3.     public List<AreaModel> queryArea(String parentid, int start, int end) {  
  4.         Connection connection = null;  
  5.         PreparedStatement preparedStatement = null;  
  6.         ResultSet resultSet = null;  
  7.         List<AreaModel> areaList = new ArrayList<>();  
  8.         try {  
  9.             //加载数据库驱动  
  10.             Class.forName("com.mysql.jdbc.Driver");  
  11.             //获得connection  
  12.             connection = DriverManager.getConnection("jdbc:mysql:///webservice""root""root");  
  13.             //获得preparedStatement  
  14.             String sql = "select * from area where parentid = ? limit ?,?";  
  15.             preparedStatement = connection.prepareStatement(sql);  
  16.             //设置参数  
  17.             preparedStatement.setString(1, parentid);  
  18.             preparedStatement.setInt(2, start - 1);  
  19.             preparedStatement.setInt(3, end - start + 1);  
  20.             //执行查询  
  21.             resultSet = preparedStatement.executeQuery();  
  22.               
  23.             //取区域列表  
  24.             while(resultSet.next()) {  
  25.                 AreaModel model = new AreaModel();  
  26.                 model.setAreaid(resultSet.getString("areaid"));  
  27.                 model.setAreaname(resultSet.getString("areaname"));  
  28.                 model.setArealevel(resultSet.getString("arealevel"));  
  29.                 model.setParentid(resultSet.getString("parentid"));  
  30.                 //添加到区域列表  
  31.                 areaList.add(model);  
  32.             }  
  33.         } catch (Exception e) {  
  34.             e.printStackTrace();  
  35.         } finally {  
  36.             try {  
  37.                 resultSet.close();  
  38.             } catch (SQLException e) {  
  39.                 // TODO Auto-generated catch block  
  40.                 e.printStackTrace();  
  41.             }  
  42.             try {  
  43.                 preparedStatement.close();  
  44.             } catch (SQLException e) {  
  45.                 // TODO Auto-generated catch block  
  46.                 e.printStackTrace();  
  47.             }  
  48.             try {  
  49.                 connection.close();  
  50.             } catch (SQLException e) {  
  51.                 // TODO Auto-generated catch block  
  52.                 e.printStackTrace();  
  53.             }  
  54.         }  
  55.         return areaList;  
  56.     }  
  57. }  


 

5.1.5.2    Service

[java] view plain copy
  1. @WebService  
  2. public class AreaInterfaceImpl implements AreaInterface {  
  3.   
  4.     @Override  
  5.     public String queryArea(String area) {  
  6.         //解析xml查询条件  
  7.         AreaModel model = null;  
  8.         String result = null;  
  9.         try {  
  10.             model = parseXml(area);  
  11.             AreaDao dao = new AreaDao();  
  12.             List<AreaModel> list = dao.queryArea(model.getParentid(), model.getStart(), model.getEnd());  
  13.             result = list2xml(list);  
  14.         } catch (Exception e) {  
  15.             // TODO Auto-generated catch block  
  16.             e.printStackTrace();  
  17.         }  
  18.         return result;  
  19.     }  
  20.     /* 
  21.     <?xml version="1.1"  encoding="utf-8"?> 
  22.     <queryarea> 
  23.     <parentid> </parentid>//父级区域id 
  24.     <start></start>//起始记录,从1开始 
  25.     <end></end>//结束记录 
  26.     </queryarea> 
  27.      
  28.     */  
  29.     private AreaModel parseXml(String xml) throws Exception {  
  30.         Document document = DocumentHelper.parseText(xml);  
  31.         String parentid = document.selectSingleNode("/queryarea/parentid").getText();  
  32.         String start  = document.selectSingleNode("/queryarea/start").getText();  
  33.         String end  = document.selectSingleNode("/queryarea/end").getText();  
  34.           
  35.         AreaModel model = new AreaModel();  
  36.         model.setParentid(parentid);  
  37.         model.setStart(Integer.parseInt(start));  
  38.         model.setEnd(Integer.parseInt(end));  
  39.           
  40.         return model;  
  41.     }  
  42.     /** 
  43.       
  44.     <?xml version="1.0" encoding="UTF-8"?> 
  45.     <areas> 
  46.     <area> 
  47.     <areaid> </areaid>//区域id 
  48.     <areaname></areaname>//区域名称 
  49.     <arealevel></arealevel>//区域等级 
  50.     <parentid></parentid>//父级区域id 
  51.     </area> 
  52.     //….. 
  53.     </areas> 
  54.      */  
  55.     private String list2xml(List<AreaModel> list) throws Exception {  
  56.         Document document = DocumentHelper.createDocument();  
  57.         //添加以根节点  
  58.         Element root = document.addElement("areas");  
  59.           
  60.         for (AreaModel areaModel : list) {  
  61.             Element area = root.addElement("area");  
  62.             area.addElement("areaid").setText(areaModel.getAreaid());  
  63.             area.addElement("areaname").setText(areaModel.getAreaname());  
  64.             area.addElement("arealevel").setText(areaModel.getArealevel());  
  65.             area.addElement("parentid").setText(areaModel.getParentid());  
  66.         }  
  67.           
  68.         return document.asXML();  
  69.     }  
  70.   
  71. }  


 

5.1.5.3    发布服务

[java] view plain copy
  1. public class AreaServer {  
  2.   
  3.     public static void main(String[] args) {  
  4.         Endpoint.publish("http://127.0.0.1:12345/area"new AreaInterfaceImpl());  
  5.     }  
  6. }  


5.1.5.5    生成客户端调用代码

5.1.5.6    客户端

[java] view plain copy
  1. public class AreaClient {  
  2.   
  3.     public static void main(String[] args) {  
  4.         //创建服务视图  
  5.         AreaInterfaceImplService service = new AreaInterfaceImplService();  
  6.         //获得porttype  
  7.         AreaInterfaceImpl portType = service.getAreaInterfaceImplPort();  
  8.         //调用服务端方法  
  9.         String result = portType.queryArea(getQueryXml("1.2."110));  
  10.         System.out.println(result);  
  11.     }  
  12.       
  13.     private static String getQueryXml(String parentid, int start, int end) {  
  14.         String xml = "<?xml version=\"1.1\"  encoding=\"utf-8\"?>\n" +  
  15.                 "<queryarea>\n" +  
  16.                 "<parentid>"+parentid+"</parentid>\n" +  
  17.                 "<start>"+start+"</start>\n" +  
  18.                 "<end>"+end+"</end>\n" +  
  19.                 "</queryarea>";  
  20.         return xml;  
  21.     }  
  22. }  
原创粉丝点击