WebService常见的远程调用协议与技术

1. 常见的远程调用协议与技术

IOS的七层模型:

第一层:应用层。定义了用于在网络中进行通信和传输数据的接口;

第二层:表示层。定义不同的系统中数据的传输格式,编码和解码规范等;

第三层:会话层。管理用户的会话,控制用户间逻辑连接的建立和中断;

第四层:传输层。管理着网络中的端到端的数据传输;

第五层:网络层。定义网络设备间如何传输数据;

第六层:链路层。将上面的网络层的数据包封装成数据帧,便于物理层传输;

第七层:物理层。这一层主要就是传输这些二进制数据。

Socket通信:Socket属于传输层,它是对TCP/IP协议的实现,包含TCP/UPD,它是所有通信协议的基础。

特点: 开启端口,该通信是长连接的通信 ,很容易被防火墙拦截,虽可以通过心跳机制来实现 ,但开发难度复杂;性能相对于其他的通信协议是最优的(客户端的大型网络游戏基本都是Socket通信);传输的数据一般是字符串 ,可读性不强。

Http协议:属于应用层的协议,对Socket进行了封装,HttpClient项目提供了通过java编程发送Http请求。

soap(http+xml):simple object access protocol(简单对象访问协议),xml是无关乎平台与语言的,使用http协议发送和接受xml数据来实现跨平台跨语言的远程调用。实现的技术是即将介绍的WebService。

RPC(Remote Procedure Call Protocol):使用C/S方式,采用http协议,发送请求到服务器,等待服务器返回结果。这个请求包括一个参数集和一个文本集,通常形成“classname.methodname”形式。优点是跨语言跨平台,C端、S端有更大的独立性,缺点是不支持对象,无法在编译器检查错误,只能在运行期检查。流行的RPC框架有gRPC、Thrift、Dubbo。

RMI:RMI是个典型的为java定制的远程通信协议,传输的标准格式是Java Object Stream;基于Java串行化机制将请求的Java Object信息转化为流,传输协议是Socket。缺点是只能基于Java语言。

JMS: JMS是Java的消息服务,JMS的客户端之间可以通过JMS服务进行异步的消息传输。JMS支持两种消息模型:Point-to-Point(P2P)和Publish/Subscribe(Pub/Sub),即点对点和发布订阅模型。 JMS规定的传输格式是Message,将参数信息放入Message中,传输协议不限。

2. WebService技术

WebService是一种跨编程语言和跨操作系统平台的远程调用技术,从表面上看,WebService就是一个应用程序向外界暴露出一个能通过Web进行调用的API,也就是说能用编程的方法通过Web来调用这个应用程序。我们把调用这个WebService的应用程序叫做客户端,而把提供这个WebService的应用程序叫做服务端。从深层次看,WebService是建立可互操作的分布式应用程序的新平台,是一个平台,是一套标准。它定义了应用程序如何在Web上实现互操作性。XML+XSD,SOAP和WSDL是构成WebService平台的三大技术;并且WebService服务提供商可以通过两种方式来暴露它的WSDL文件地址:

1.注册到UDDI服务器,以便被人查找;

2.直接告诉给客户端调用者。

XML+XSD:WebService采用HTTP协议作为传输协议,采用XMl格式封装数据,XML的优点在于它与平台和语言无关,XSD(XML Schema)来定义一套标准的数据类型,无论你使用什么语言的数据类型都会被转换为XSD类型。

SOAP(Simple Object Access Protocol):WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议。

WSDL:用于描述WebService及其函数、参数和返回值的XML。一些最新的开发工具既能根据你的Web service生成WSDL文档,又能导入WSDL文档,生成调用相应WebService的代理类代码。

UUDI:一种目录服务,企业可以使用它对Webservices进行注册和搜索。

2.1 使用WebService调用第三方接口

http://www.webxml.com.cn/zh_cn/index.aspx此网站提供了发布了的WebService服务。

WebService的调用有三种方式:

http#get

http#post

http#post+xml(soap)

package com.ws.client;

/**

* @desc 国内手机号码归属地查询WEB服务:http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx

* @author yutao

* @create 2018-06-26 9:33

*/

public class MobileCodeService {

    /**

    * Http GET请求

    * @param mobileCode

    * @param userID

    */

    public void get(String mobileCode,String userID){

        try {

            URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo?mobileCode="+mobileCode+"&userID="+userID);

            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

            httpURLConnection.setConnectTimeout(5000);  //设置连接超时

            httpURLConnection.setRequestMethod("GET");  //GET请求

            if (httpURLConnection.getResponseCode()==httpURLConnection.HTTP_OK) {  //请求返回码200

                InputStream inputStream = httpURLConnection.getInputStream();

                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  //内存流

                byte[] bytes = new byte[1024];

                int len = -1;

                while ((len=inputStream.read(bytes))!=-1) {

                    byteArrayOutputStream.write(bytes,0,len);

                }

                System.out.println(byteArrayOutputStream.toString());  //返回的是xml字符串

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    /**

    * Http POST请求

    * @param mobileCode

    * @param userID

    */

    public void post(String mobileCode,String userID) {

        /** org.apache.commons.httpclient.HttpClient访问网络的实现步骤:

        *  1. 准备一个请求客户端:浏览器

        *  2. 准备请求方式: GET 、POST

        *  3. 设置要传递的参数

        *  4.执行请求

        *  5. 获取结果

        */

        HttpClient httpClient = new HttpClient();

        PostMethod postMethod = new PostMethod("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo");

        postMethod.setParameter("mobileCode",mobileCode);

        postMethod.setParameter("userID",userID);

        try {

            int code = httpClient.executeMethod(postMethod);

            if (code == 200) {

                String result = postMethod.getResponseBodyAsString();

                System.out.println(result);

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    /**

    * soap 请求(HTTP#POST + xml)

    */

    public void soap() {

        HttpClient httpClient = new HttpClient();

        PostMethod postMethod = new PostMethod("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx");

        try {

            File file = new File("F:\\idea\\project\\webservice\\src\\main\\resources\\soap.xml");

            InputStreamRequestEntity inputStreamRequestEntity = new InputStreamRequestEntity(new FileInputStream(file),"text/xml; charset=utf-8");

            postMethod.setRequestEntity(inputStreamRequestEntity);  //设置POST请求请求体

            int code = httpClient.executeMethod(postMethod);

            if (code == HttpURLConnection.HTTP_OK) {

                System.out.println(postMethod.getResponseBodyAsString());

            }

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (HttpException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    public static void  main(String[] args) {

        MobileCodeService mobileCodeService = new MobileCodeService();

        mobileCodeService.get("13456789000","");

    }

}

2.1.1 使用WSDL

上述的三种调用方式返回的数据都是xml字符串

<?xml version="1.0" encoding="utf-8"?>

<string xmlns="http://WebXml.com.cn/">13456789000:浙江 杭州 浙江移动大众卡</string>

对于这样的数据我们每次取得岂不是都要编写xml解析,显然不是我们希望得到的。通过工具可以根据WebService的WSDL生成对应编程语言的代理类,原理如下图:

WSDL地址:http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL

使用JDK的wsimport指令生成代理类:

/**

* -d表示输出的.class文件位置,-s表示输出的.java文件位置,-p表示输出的包名

* wsimport无法生成SOAP12、GET、POST请求的代理类

*/

wsimport -d D:/ -s D:/src -p com.ws.proxy http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL

将生成的源码放入项目上述指定的包中或将生成的class文件打成jar包引入项目中,即可使用。

/**

* 返回的xml都会通过代理类处理成了String字符串或其他集合数据等

*/

public class MobileCodeWSTest {

    public static void main(String[] args) {

        //获取MobileCodeWS服务

        MobileCodeWS ws = new MobileCodeWS();

        //获取SOAP请求的服务

        MobileCodeWSSoap mobileCodeWSSoap = ws.getMobileCodeWSSoap();

        //调用该服务的getMobileCodeInfo方法

        String mobileCodeInfo = mobileCodeWSSoap.getMobileCodeInfo("18712343850", "");

        System.out.println(mobileCodeInfo);

        //调用该服务的getDatabaseInfo方法,ArrayOfString是生成的代理类,通过getString方法返回List集合

        ArrayOfString databaseInfo = mobileCodeWSSoap.getDatabaseInfo();

        List<String> list = databaseInfo.getString();

        for (String s : list) {

            System.out.println(s);

        }

    }

}

2.2 服务端WebService发布

2.2.1 WSDL

http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL解析如下:

<?xml version="1.0" encoding="utf-8"?>

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"

                  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"

                  xmlns:tns="http://WebXml.com.cn/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"

                  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"

                  targetNamespace="http://WebXml.com.cn/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">    <!--targetNamespace是命名空间,默认使用cn.com.WebXml作为生成代理类的包-->

    <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">  <!--文档-->

        &lt;a href="http://www.webxml.com.cn/" target="_blank"&gt;WebXml.com.cn&lt;/a&gt; &lt;strong&gt;国内手机号码归属地查询WEB服务&lt;/strong&gt;,提供最新的国内手机号码段归属地数据,每月更新。&lt;br /&gt;使用本站 WEB 服务请注明或链接本站:&lt;a href="http://www.webxml.com.cn/" target="_blank"&gt;http://www.webxml.com.cn/&lt;/a&gt; 感谢大家的支持!&lt;br /&gt;&amp;nbsp;

    </wsdl:documentation>

    <wsdl:types>

        <s:schema elementFormDefault="qualified" targetNamespace="http://WebXml.com.cn/">

            <s:element name="getMobileCodeInfo">    <!--输入参数信息,对外提供WebService的输入参数类-->

                <s:complexType>

                    <s:sequence>

                        <s:element minOccurs="0" maxOccurs="1" name="mobileCode" type="s:string" /> <!--输入参数名及参数类型-->

                        <s:element minOccurs="0" maxOccurs="1" name="userID" type="s:string" />

                    </s:sequence>

                </s:complexType>

            </s:element>

            <s:element name="getMobileCodeInfoResponse">

                <s:complexType>

                    <s:sequence>

                        <s:element minOccurs="0" maxOccurs="1" name="getMobileCodeInfoResult" type="s:string" />    <!--返回参数名及类型-->

                    </s:sequence>

                </s:complexType>

            </s:element>

            <s:element name="getDatabaseInfo">

                <s:complexType />

            </s:element>

            <s:element name="getDatabaseInfoResponse">

                <s:complexType>

                    <s:sequence>

                        <s:element minOccurs="0" maxOccurs="1" name="getDatabaseInfoResult" type="tns:ArrayOfString" />

                    </s:sequence>

                </s:complexType>

            </s:element>

            <s:complexType name="ArrayOfString">    <!-- 服务定义返回的类型,对外提供WebService的类型类 -->

                <s:sequence>

                    <s:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="s:string" />

                </s:sequence>

            </s:complexType>

            <s:element name="string" nillable="true" type="s:string" />

            <s:element name="ArrayOfString" nillable="true" type="tns:ArrayOfString" />

        </s:schema>

    </wsdl:types>

    <wsdl:message name="getMobileCodeInfoSoapIn">  <!--服务端口输入参数信息-->

        <wsdl:part name="parameters" element="tns:getMobileCodeInfo" />    <!--参数信息在上面<wsdl:types>中-->

    </wsdl:message>

    <wsdl:message name="getMobileCodeInfoSoapOut">  <!--服务端口返回参数信息-->

        <wsdl:part name="parameters" element="tns:getMobileCodeInfoResponse" />    <!--参数信息在上面<wsdl:types>中-->

    </wsdl:message>

    <wsdl:message name="getDatabaseInfoSoapIn">

        <wsdl:part name="parameters" element="tns:getDatabaseInfo" />

    </wsdl:message>

    <wsdl:message name="getDatabaseInfoSoapOut">

        <wsdl:part name="parameters" element="tns:getDatabaseInfoResponse" />

    </wsdl:message>

    <wsdl:message name="getMobileCodeInfoHttpGetIn">

        <wsdl:part name="mobileCode" type="s:string" />

        <wsdl:part name="userID" type="s:string" />

    </wsdl:message>

    <wsdl:message name="getMobileCodeInfoHttpGetOut">

        <wsdl:part name="Body" element="tns:string" />

    </wsdl:message>

    <wsdl:message name="getDatabaseInfoHttpGetIn" />

    <wsdl:message name="getDatabaseInfoHttpGetOut">

        <wsdl:part name="Body" element="tns:ArrayOfString" />

    </wsdl:message>

    <wsdl:message name="getMobileCodeInfoHttpPostIn">

        <wsdl:part name="mobileCode" type="s:string" />

        <wsdl:part name="userID" type="s:string" />

    </wsdl:message>

    <wsdl:message name="getMobileCodeInfoHttpPostOut">

        <wsdl:part name="Body" element="tns:string" />

    </wsdl:message>

    <wsdl:message name="getDatabaseInfoHttpPostIn" />

    <wsdl:message name="getDatabaseInfoHttpPostOut">

        <wsdl:part name="Body" element="tns:ArrayOfString" />

    </wsdl:message>

    <wsdl:portType name="MobileCodeWSSoap">    <!--服务端口类型,对外提供WebService业务类或接口-->

        <wsdl:operation name="getMobileCodeInfo">  <!-- 操作名 -->

            <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地省份、地区和手机卡类型信息&lt;/h3&gt;&lt;p&gt;输入参数:mobileCode = 字符串(手机号码,最少前7位数字),userID = 字符串(商业用户ID) 免费用户为空字符串;返回数据:字符串(手机号码:省份 城市 手机卡类型)。&lt;/p&gt;&lt;br /&gt;</wsdl:documentation>

            <wsdl:input message="tns:getMobileCodeInfoSoapIn" />    <!--输入参数,对应上面<wsdl:message>-->

            <wsdl:output message="tns:getMobileCodeInfoSoapOut" />  <!--返回参数,对应上面<wsdl:message>-->

        </wsdl:operation>

        <wsdl:operation name="getDatabaseInfo">

            <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地数据库信息&lt;/h3&gt;&lt;p&gt;输入参数:无;返回数据:一维字符串数组(省份 城市 记录数量)。&lt;/p&gt;&lt;br /&gt;</wsdl:documentation>

            <wsdl:input message="tns:getDatabaseInfoSoapIn" />

            <wsdl:output message="tns:getDatabaseInfoSoapOut" />

        </wsdl:operation>

    </wsdl:portType>

    <wsdl:portType name="MobileCodeWSHttpGet">

        <wsdl:operation name="getMobileCodeInfo">

            <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地省份、地区和手机卡类型信息&lt;/h3&gt;&lt;p&gt;输入参数:mobileCode = 字符串(手机号码,最少前7位数字),userID = 字符串(商业用户ID) 免费用户为空字符串;返回数据:字符串(手机号码:省份 城市 手机卡类型)。&lt;/p&gt;&lt;br /&gt;</wsdl:documentation>

            <wsdl:input message="tns:getMobileCodeInfoHttpGetIn" />

            <wsdl:output message="tns:getMobileCodeInfoHttpGetOut" />

        </wsdl:operation>

        <wsdl:operation name="getDatabaseInfo">

            <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地数据库信息&lt;/h3&gt;&lt;p&gt;输入参数:无;返回数据:一维字符串数组(省份 城市 记录数量)。&lt;/p&gt;&lt;br /&gt;</wsdl:documentation>

            <wsdl:input message="tns:getDatabaseInfoHttpGetIn" />

            <wsdl:output message="tns:getDatabaseInfoHttpGetOut" />

        </wsdl:operation>

    </wsdl:portType>

    <wsdl:portType name="MobileCodeWSHttpPost">

        <wsdl:operation name="getMobileCodeInfo">

            <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地省份、地区和手机卡类型信息&lt;/h3&gt;&lt;p&gt;输入参数:mobileCode = 字符串(手机号码,最少前7位数字),userID = 字符串(商业用户ID) 免费用户为空字符串;返回数据:字符串(手机号码:省份 城市 手机卡类型)。&lt;/p&gt;&lt;br /&gt;</wsdl:documentation>

            <wsdl:input message="tns:getMobileCodeInfoHttpPostIn" />

            <wsdl:output message="tns:getMobileCodeInfoHttpPostOut" />

        </wsdl:operation>

        <wsdl:operation name="getDatabaseInfo">

            <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地数据库信息&lt;/h3&gt;&lt;p&gt;输入参数:无;返回数据:一维字符串数组(省份 城市 记录数量)。&lt;/p&gt;&lt;br /&gt;</wsdl:documentation>

            <wsdl:input message="tns:getDatabaseInfoHttpPostIn" />

            <wsdl:output message="tns:getDatabaseInfoHttpPostOut" />

        </wsdl:operation>

    </wsdl:portType>

    <!-- 服务Soap访问方式 -->

    <wsdl:binding name="MobileCodeWSSoap" type="tns:MobileCodeWSSoap">  <!--服务端口类型,对应上面的</wsdl:portType>-->

        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />

        <!--该服务提供了以下二种操作-->

        <wsdl:operation name="getMobileCodeInfo">  <!--操作名称(对外暴露调用的方法名)-->

            <soap:operation soapAction="http://WebXml.com.cn/getMobileCodeInfo" style="document" />

            <wsdl:input>

                <soap:body use="literal" />

            </wsdl:input>

            <wsdl:output>

                <soap:body use="literal" />

            </wsdl:output>

        </wsdl:operation>

        <wsdl:operation name="getDatabaseInfo">

            <soap:operation soapAction="http://WebXml.com.cn/getDatabaseInfo" style="document" />

            <wsdl:input>

                <soap:body use="literal" />

            </wsdl:input>

            <wsdl:output>

                <soap:body use="literal" />

            </wsdl:output>

        </wsdl:operation>

    </wsdl:binding>

    <!-- 服务Soap12访问方式-->

    <wsdl:binding name="MobileCodeWSSoap12" type="tns:MobileCodeWSSoap">

        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />

        <wsdl:operation name="getMobileCodeInfo">

            <soap12:operation soapAction="http://WebXml.com.cn/getMobileCodeInfo" style="document" />

            <wsdl:input>

                <soap12:body use="literal" />

            </wsdl:input>

            <wsdl:output>

                <soap12:body use="literal" />

            </wsdl:output>

        </wsdl:operation>

        <wsdl:operation name="getDatabaseInfo">

            <soap12:operation soapAction="http://WebXml.com.cn/getDatabaseInfo" style="document" />

            <wsdl:input>

                <soap12:body use="literal" />

            </wsdl:input>

            <wsdl:output>

                <soap12:body use="literal" />

            </wsdl:output>

        </wsdl:operation>

    </wsdl:binding>

    <!--服务Get访问方式-->

    <wsdl:binding name="MobileCodeWSHttpGet" type="tns:MobileCodeWSHttpGet">

        <http:binding verb="GET" />

        <wsdl:operation name="getMobileCodeInfo">

            <http:operation location="/getMobileCodeInfo" />

            <wsdl:input>

                <http:urlEncoded />

            </wsdl:input>

            <wsdl:output>

                <mime:mimeXml part="Body" />

            </wsdl:output>

        </wsdl:operation>

        <wsdl:operation name="getDatabaseInfo">

            <http:operation location="/getDatabaseInfo" />

            <wsdl:input>

                <http:urlEncoded />

            </wsdl:input>

            <wsdl:output>

                <mime:mimeXml part="Body" />

            </wsdl:output>

        </wsdl:operation>

    </wsdl:binding>

    <!--服务Post访问方式-->

    <wsdl:binding name="MobileCodeWSHttpPost" type="tns:MobileCodeWSHttpPost">

        <http:binding verb="POST" />

        <wsdl:operation name="getMobileCodeInfo">

            <http:operation location="/getMobileCodeInfo" />

            <wsdl:input>

                <mime:content type="application/x-www-form-urlencoded" />

            </wsdl:input>

            <wsdl:output>

                <mime:mimeXml part="Body" />

            </wsdl:output>

        </wsdl:operation>

        <wsdl:operation name="getDatabaseInfo">

            <http:operation location="/getDatabaseInfo" />

            <wsdl:input>

                <mime:content type="application/x-www-form-urlencoded" />

            </wsdl:input>

            <wsdl:output>

                <mime:mimeXml part="Body" />

            </wsdl:output>

        </wsdl:operation>

    </wsdl:binding>

    <wsdl:service name="MobileCodeWS">  <!--服务名,对外提供WebService的服务类-->

        <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">&lt;a href="http://www.webxml.com.cn/" target="_blank"&gt;WebXml.com.cn&lt;/a&gt; &lt;strong&gt;国内手机号码归属地查询WEB服务&lt;/strong&gt;,提供最新的国内手机号码段归属地数据,每月更新。&lt;br /&gt;使用本站 WEB 服务请注明或链接本站:&lt;a href="http://www.webxml.com.cn/" target="_blank"&gt;http://www.webxml.com.cn/&lt;/a&gt; 感谢大家的支持!&lt;br /&gt;&amp;nbsp;</wsdl:documentation>

        <wsdl:port name="MobileCodeWSSoap" binding="tns:MobileCodeWSSoap">  <!--服务端口名及服务访问方式(Soap、Soap12、Get、Post,对应上面的<wsdl:binding>)-->

            <soap:address location="http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx" />  <!--服务访问地址-->

        </wsdl:port>

        <wsdl:port name="MobileCodeWSSoap12" binding="tns:MobileCodeWSSoap12">

            <soap12:address location="http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx" />

        </wsdl:port>

        <wsdl:port name="MobileCodeWSHttpGet" binding="tns:MobileCodeWSHttpGet">

            <http:address location="http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx" />

        </wsdl:port>

        <wsdl:port name="MobileCodeWSHttpPost" binding="tns:MobileCodeWSHttpPost">

            <http:address location="http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx" />

        </wsdl:port>

    </wsdl:service>

</wsdl:definitions>2.2.2 WebService注解

@WebService

/**

* 用于注解在需要作为WebService发布的类或接口上

*/

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.TYPE})

public @interface WebService {

    //服务端口类型名,修改<wsdl:portType>的name属性

    String name() default "";

    //命名空间,修改targetNamespaces属性

    String targetNamespace() default "";

    //服务名,修改<wsdl:service>的name属性

    String serviceName() default "";

    //端口服务名,修改<wsdl:service>下<wsdl:port>的name属性

    String portName() default "";

    //wsdl地址,修改wsdl:service>下<*:address>的location属性

    String wsdlLocation() default "";

    //服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口

    String endpointInterface() default "";

}


@WebMethod

/**

* 注释表示作为一项 WebService 操作的方法

*/

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

public @interface WebMethod {

    //操作名,修改<wsdl:operation>的name属性

    String operationName() default "";

    //义此操作的行为。对于 SOAP 绑定,此值将确定 SoapAction属性的信息。缺省值为 Java 方法的名称

    String action() default "";

    //如果为true,方法将不会被发布

    boolean exclude() default false;

}

@WebParam

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.PARAMETER})

public @interface WebParam {

    //请求参数名,修改<s:sequence>下<xs:element>的name属性

    String name() default "";

    //修改<wsdl:part>的name属性

    String partName() default "";

    //指定返回值的 XML 名称空间

    String targetNamespace() default "";

    //此值表示此方法的参数流的方向

    WebParam.Mode mode() default WebParam.Mode.IN;

    //指定参数是在Http请求头还是请求体中

    boolean header() default false;

    public static enum Mode {

        IN,

        OUT,

        INOUT;

        private Mode() {

        }

    }

}

@WebResult

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

public @interface WebResult {

    //返回参数名,修改<s:sequence>下<xs:element>的name属性

    String name() default "";

    //指定 RPC 或 DOCUMENT/BARE 操作的结果的部件名称。缺省值为@WebResult.name。(字符串)

    String partName() default "";

    //指定返回值的 XML 名称空间

    String targetNamespace() default "";

    //指定响应头中是否附带结果

    boolean header() default false;

}


2.2.3 发布示例

@WebService

public interface JobService {

    public String getJob(String username);

}

@WebService(

        serviceName = "jobServiceWS",  //服务名

        portName = "jobServiceWsSoap",  //服务端口名

        name = "jobServiceWSSoapService",      //portType名

        targetNamespace = "http://job.ws.com" //命名空间 ,默认包名com.ws.job

//      endpointInterface = "com.ws.server.service.JobService"    //服务端点接口(Service EndPoint Interface),只发布该接口的方法

        )

public class JobServiceImpl implements JobService {

    @Override

    @WebMethod(exclude = false,operationName = "getUserJob")

    public @WebResult(name = "job") String getJob(@WebParam(name = "user") String username) {

        return "Java工程师";

    }

    @WebMethod(exclude = true)

    public String getAddress() {

        return "上海";

    }

    public static void main(String[] args) {

        Endpoint.publish("http://localhost:9090/jobService",new JobServiceImpl());

    }

}

2.2.3 CXF框架

Apache CXF 是一个开源的 Services 框架,CXF 帮助您来构建和开发 Services ,这些 Services 可以支持多种协议,比如:SOAP、POST/HTTP、RESTful HTTP, CXF 大大简化了 Service可以天然地和 Spring 进行无缝集成。Apache CXF是 Celtrix (ESB框架)和 XFire(webserivice) 合并而成。

特点:

与Spring、Servlet做了无缝对接,cxf框架里面集成了Servlet容器Jetty

支持注解的方式来发布webservice

能够显示一个webservice的服务列表

能够添加拦截器:输入拦截器、输出拦截器 :输入日志信息拦截器、输出日志拦截器、用户权限认证的拦截器

web.xml

<!-- 添加  CXF 的Servlet ,处理 webservice的请求,类似于SpringMVC的DispatcherServlet -->

  <servlet>

      <servlet-name>cxf</servlet-name>

      <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>

      <load-on-startup>0</load-on-startup>

  </servlet>

  <servlet-mapping>

      <servlet-name>cxf</servlet-name>

      <url-pattern>/ws/*</url-pattern>

  </servlet-mapping>

@WebService(serviceName="languageManager")

public interface LanguageService {

    public @WebResult(name="language")String getLanguage(@WebParam(name="position")int position);

}

public class LanguageServiceImpl implements LanguageService {

    /* (non-Javadoc)

    * @see cn.it.ws.cxf.a.LanguageService#getLanguage(int)

    */

    @Override

    public String getLanguage(int position){

        String language=null;

        switch (position) {

        case 1:

            language="java";

            break;

        case 2:

            language="C";

            break;

        case 3:

            language="Objective-C";

            break; 

        case 4:

            language="C#";

            break;

        default:

            break;

        }

        return language;

    }

}

/**通过cxf框架发布webservice

*  1. ServerFactoryBean

*    - 不设置注解也可以发布webservice服务, 不支持注解

*    - 不支持拦截器的添加

*  2. JaxWsServerFactoryBean

*    - 支持注解

*    - 可以添加拦截器

*  3. webservice 访问流程:

*    1. 检测本地代理描述的wsdl是否与服务端的wsdl一致 ,俗称为握手

*    2. 通过soap协议实现通信 ,采用的是post请求 , 数据封装在满足soap规约的xml中

*    3. 返回数据 同样采用的是soap通信,  数据封装在满足soap规约的xml中

*/

public class PubsherWS {

    public static void main() {

        LanguageService languageService=new LanguageServiceImpl();

        //ServerFactoryBean bean=new ServerFactoryBean();

        JaxWsServerFactoryBean bean=new JaxWsServerFactoryBean();

        //Endpoint :地址  , 实现对象

        bean.setAddress("http://192.168.114.10:9999/ws/cxf/languangeService");

        bean.setServiceClass(LanguageService.class);//对外提供webservcie的业务类或者接口

        bean.setServiceBean(languageService);//服务的实现bean

        //添加输入拦截器  :输入显示日志信息的拦截器,ServerFactoryBean 不支持

        bean.getInInterceptors().add(new LoggingInInterceptor());

        //添加输出拦截器  :输出显示日志信息的拦截器,ServerFactoryBean 不支持

        bean.getOutInterceptors().add(new LoggingOutInterceptor());

        bean.create();//创建,发布webservice

    }

}

实际使用中,WebService都应用于Web项目,需要在Tomcat服务器启动后发布。可以将bean注册到Spring IOC容器中:

<!-- 配置cxf

    地址:  http://192.168.43.185:8080/CXF_Server/ws/languageOder

    组成 :  http://192.168.43.185:8080 +CXF_Server( 项目名)+ws(过滤的路径)+/languageOder(自定义部分)

    服务类 :

    服务的实现类:

    拦截器

      -->

    <bean id="languageService" class="com.ws.cxf.LanguageServiceImpl"></bean>

    <jaxws:server serviceName="languageService" address="languageOder" serviceClass="com.ws.cxf.LanguageService">

        <jaxws:serviceBean>

            <ref bean="languageService"></ref>

        </jaxws:serviceBean>

        <!-- 配置输入显示日志信息的拦截器  -->

        <jaxws:inInterceptors>

            <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>

        </jaxws:inInterceptors>

        <!-- 配置输出显示日志信息的拦截器  -->

        <jaxws:outInterceptors>

            <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>

        </jaxws:outInterceptors>

    </jaxws:server>

---------------------

作者:yutao_Struggle

来源:CSDN

原文:https://blog.csdn.net/yutao_struggle/article/details/80829770

版权声明:本文为博主原创文章,转载请附上博文链接!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335