比较全的WebService 笔记

WebService

1、概念

1.1 WebService

Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。是:通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI进行注册。 说白了 WebService 是一种跨编程语言、跨操作系统平台的远程调用技术。

连接不同系统之间的一个桥梁/纽带,可以实现不同编程语言,不同系统之间的交互。

本质就是XML流的解析

1.1.1 远程调用技术

远程调用是指一台设备上的程序A可以调用另一台设备上的方法B。比如:银联提供给商场的pos刷卡系统,商场的pos机转账调用的转账方法的代码其实是跑在银行服务器上的。再比如,amazon,天气预报系统,淘宝网,校内网,百度等把自己的系统服务以WebService服务的形式暴露出来,让第三方网站和程序可以调用这些服务功能,这样扩展了自己系统的市场占有率。

1.1.2 跨操作系统平台

  • 从表面上看

    • WebService是指一个应用程序向外界暴露了一个能通过Web调用的API接口,我们把调用这个WebService的应用程序称作客户端,把提供这个WebService的应用程序称作服务端。

  • 从深层上看

    • WebService是建立可互操作的分布式应用程序的新平台,是一个平台,是一套标准。它定义了应用程序如何通过Web实现互操作性,通过WebService标准对服务进行查询和访问。

1.2 WebService(SAOP)与HTTP接口的区别

1.2.1 什么是SAOP

SAOP请求是HTTP POST 的一个专用版本,遵循一种特殊的xml消息格式Content-type 设置为:text/xml 任何数据都可以xml化,也都能JSON化

1.2.2 WebService 作用

大多数对外接口会实现webService方法而不是http方法,如果不会,那就没有办法对接

1.2.3 WebService 相对http(post/get)好处

  • 接口中实现的方法和要求参数一目了然
  • 不用担心大小写问题
  • 不用担心中文urlencode问题
  • 代码中不用多次声明认证(账号,密码)参数
  • 传递参数可为数组,对象等

1.2.4 WebService 相对http的速度

相对http较慢,因为要对xml进行解析

1.2.5 WebService 可以被http(post/get)代替么?

可以,开放平台都是使用http实现的

1.2.6 总结

  • HTTP Service 通过post和get 得到你想要的东西
  • WebService就是使用soap协议得到你想要的东西,相比httpService能处理些更加复杂的数据类型
  • http协议传输的都是字符串了,WebService则是包装成了更复杂的对象

1.3 XML与JSON的区别

1.3.1 XML

  • XML 指可扩展标记语言(EXtensible Markup Language)
  • XML 是一种可扩展标记语言,HTML就是基于XML演变而来的
  • XML 的设计宗旨是传输数据,而非显示数据
  • XML 标签没有被预定义。需要自行定义标签
  • XML 被设计为具有自我描述性
  • XML 是W3C的推荐标准

1.3.2 JSON

  • JSON (JavaScript Object Notation) 是一种格式,一种轻量级的数据交换格式。
  • 易于人阅读和编写,同时也易于机器解析和生成。
  • JSON采用完全独立于语言的文本格式,但是也使用C语言家族的习惯(包括C,C++,C#,Java,JavaScript,Perl,Python)
  • 这些特性使其成为理想的数据交换语言

1.3.3 比较

  • XML 能做的 JSON都能做。

  • JSON 比XML 格式更简单,使用更方便,更加流行,占用带宽更小,传输速度更快,能直接为服务器端代码使用

  • JSON 对数据的描述性比XML较差

  • JSON只提供整体解析方案,而这种方法只在解析较少的数据时才能起到良好的效果;

  • XML提供了对大规模数据的逐步解析方案,这种方案很适合于对大量数据的处理。(DOM 和 SAX)

1.4 WSDL

  • WSDL 网络服务描述语言, 是一种基于XML用来描述WebService 以及如何访问WebService的语言
  • WSDL 文档包含一系列描述某个WebService的定义

1.4.1 WSDL 结构

WSDL 利用几个主要的元素来描述某个WebService的

元素作用
< portType >WebService执行的操作,即可调用的方法
< message >WebService 使用的消息
< types >WebService 使用的数据类型
< binding >WebService 使用的通信协议

除此之外,WSDL还可以包含其他的元素,比如extension、service元素

<definitions>
	<types>
        数据类型定义
	</types>
	<message>
        消息定义
    </message>
    <portType>
        操作,可调用的方法
    </portType>
	<binding>
        通信协议
    </binding>
</definitions>

完整的WSDL

XML里面的标签都是自己定义的,通过命名空间来进行限制

其中 标签里面的 xmlns:标签名=“URL” 这个是命名空间,给标签一个唯一的标识符,里面的URL 不解析,只是用来标识而已。

一般都是使用 < 命名空间:元素 > 这种前缀命名的方式来使用,这样在使用两个XML时,同名的元素不会发生命名冲突。

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
jaxb:version="2.0"
xmlns:ns0="http://hsc.itf.nc/TM"
targetNamespace="http://hsc.itf.nc/TM">
<jaxws:bindings>
	<jaxws:package name="nc.itf.hsc"/>
</jaxws:bindings>
<wsdl:types>
   <xsd:schema xmlns:ns="http://hsc.itf.nc/TM"
			attributeFormDefault="unqualified"
			elementFormDefault="unqualified"
			targetNamespace="http://hsc.itf.nc/TM" jaxb:version="2.0">
	<xsd:annotation>
    	<xsd:appinfo>
   			<jaxb:schemaBindings>
    			<jaxb:package name="nc.itf.hsc"/>
    		</jaxb:schemaBindings>
   		</xsd:appinfo>
   	</xsd:annotation>
	<xsd:element name="MY">
         <xsd:complexType>
            <xsd:sequence>
				<xsd:element name="string"  minOccurs="0" nillable="true" type="xsd:string"/>
             </xsd:sequence>  
         </xsd:complexType>
     </xsd:element>
	<xsd:element name="MYResponse">
         <xsd:complexType>
            <xsd:sequence>
				<xsd:element name="return"  minOccurs="0" nillable="true" type="xsd:string"/>
             </xsd:sequence>  
         </xsd:complexType>
     </xsd:element>
   </xsd:schema>
</wsdl:types>
    <wsdl:message name="MYRequest">
        <wsdl:part name="parameters"  element="ns0:MY"/>
    </wsdl:message>
    <wsdl:message name="MYResponse">
        <wsdl:part name="parameters"  element="ns0:MYResponse"/>
    </wsdl:message>

    <wsdl:portType name="TMPortType">
        <wsdl:operation name="MY">
            <wsdl:input message="ns0:MYRequest" wsaw:Action="urn:MY"/>
            <wsdl:output message="ns0:MYResponse" wsaw:Action="urn:MYResponse"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="TMSOAP11Binding" type="ns0:TMPortType">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
        <wsdl:operation name="MY">
            <soap:operation soapAction="urn:MY" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="TM">
        <wsdl:port name="TMSOAP11port_http" binding="ns0:TMSOAP11Binding">
            <soap:address location="http://localhost/uapws/service/TM"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

1.4.2 解读

一般而言,只需要关注三个地方就可以

  • < XXX:definitions targetNamespace=“URL” >

    在NC中,这个URL 一般指向 接口

    在用cxf+spring编写webservice的时候,targetNamespace要指向服务类的接口所在的包名而不是实现类的包名,否则,在客户端将不能识别可用的服务。

    这是个命名空间,子节点中也有targtNamespace

  • < xx:types >< xx:element name=“方法名”> < /xx:types >

    在这个元素里面可以知道 可掉用方法的名称,入参参数名与参数类型。参数名称按照WSDL中的参数名进行请求而不是接口中的参数名

    <xsd:element name="MY">
    <xsd:complexType>
      <xsd:sequence>
          <xsd:element name="string"  minOccurs="0" nillable="true" type="xsd:string"/>
      </xsd:sequence>  
    </xsd:complexType>
    </xsd:element>
    
  • < xxx:service >< xx:address localhost=“URL” />< /xxx:service >

    这里的URL是接口的请求地址

1.4.3 httpURLConnection方式调用

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
 
public class Test {
    public static void main(String[] args) throws IOException {  
        //第一步:创建服务地址,这里的请求地址就是上面第三个标签里面的请求地址 
        URL url = new URL("请求地址?wsdl");  
        //第二步:打开一个通向服务地址的连接  
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
        //第三步:设置参数  
        //3.1发送方式设置:POST必须大写  
        connection.setRequestMethod("POST");  
        //3.2设置数据格式:content-type  
        connection.setRequestProperty("content-type", "text/xml;charset=utf-8");  
        //3.3设置输入输出,因为默认新创建的connection没有读写权限,  
        connection.setDoInput(true);  
        connection.setDoOutput(true);  
  
        //第四步:组织SOAP数据,发送请求  
        String soapXML = getXML("参数值");  
        //将信息以流的方式发送出去
        OutputStream os = connection.getOutputStream();  
        os.write(soapXML.getBytes());  
        //第五步:接收服务端响应,打印  
        int responseCode = connection.getResponseCode();  
        if(200 == responseCode){//表示服务端响应成功  
            //获取当前连接请求返回的数据流
            InputStream is = connection.getInputStream();  
            InputStreamReader isr = new InputStreamReader(is);  
            BufferedReader br = new BufferedReader(isr);  
              
            StringBuilder sb = new StringBuilder();  
            String temp = null;  
            while(null != (temp = br.readLine())){  
                sb.append(temp);  
            }  
            
            /**
             * 打印结果
             */
            System.out.println(sb.toString());  
            
            is.close();  
            isr.close();  
            br.close();  
        }  
        os.close();  
    }  
 
 
    public static String getXML(String phone){  
    	
    	String soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"  
    	        +"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2003/XMLSchema-instance\" " 
    			+"xmlns:web=\"http://WebXml.com.cn/\"  " 
    	        +"xmlns:xsd=\"http://www.w3.org/2003/XMLSchema\" " 
    			+"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"  
    	            +"<soap:Body>"  
    	              +"<web:方法名>"    
    	              +"<xxx:参数名>"
            		  +phone//xml的格式,在前面加<![CDATA[xml]]>
            		  +"</xxx:参数名>"
    	              +"</web:方法名>"  
    	            +"</soap:Body>"  
    	        +"</soap:Envelope>";  
        return soapXML;  
    }  
}

2、使用

目前在用JDK1.5 开发NC,所以内容上显示偏向这个方面

2.1 发布

2.1.1 NC发布WeService 接口

2.1.1.1 写好接口于实现类代码

接口中方法的返回值,最好不要使用jar包中的类型,不然,在发布接口的时候不会生成WSDL文件,报null。建议用String作为返回值,

2.1.1.2 发布

找到要发布的接口,右击

填写接口名称

配置实现类

配置授权

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YjGvzfVx-1619061569653)(D:\存天地\Typora\WebService\image-20210421184016204.png)]

操作成功

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f9Hyvf2O-1619061569655)(D:\存天地\Typora\WebService\image-20210421184320653.png)]

2.1.1.3 测试

启动后访问 http://localhost/uapws/service,能够看到自己发布的接口

点击访问自己这个接口 显示WSDL就说明发布成功了

2.1.2 Spring 发布接口

这个以后写,先放着

2.2 调用

2.2.1 AXIS 调用

能够支持JDK1.5 jar包地址:https://pan.baidu.com/s/1rvg8M-YGAJ-bULPBPE7CIA 提取码:ylsp

2.2.1.1 NC 调用方法

一般直接的请求NC接口会直接返回wsdl文件的页面,并不会请求到方法

将上面全部解压,然后将lib文件夹下面的jar包全部导入进去,一个也不要少,不然会报错。

  • 生成对应类

运行下面类,生成可调用接口的对应类。

import org.apache.axis.wsdl.WSDL2Java;
public class Axis {
    public static void main(String[] args) throws Exception {
        String wsdl = "http://localhost/uapws/service/nc.intf.hsc.WebXXX?wsdl";
        
        WSDL2Java.main(new String[] { "-o", "src","-p",生成位置, 请求地址 });
    }
}

  • 调用接口
import nc.ws.intf.WebXXX.stub.WebXXX;
import nc.ws.intf.WebXXX.stub.WebXXXLocator;
import nc.ws.intf.WebXXX.stub.WebXXXPortType;
public class Mains {
    public static void main(String[] args) {
        try {
            WebXXX service = new WebXXXLocator();
            WebXXXPortType port = (WebXXXPortType) service.getWebXXXSOAP11port_http();
            System.out.println(port.WD("World").toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.2.2 SOAP调用 1.8可用

这个方式可以调用其他的WebService,但是不能调用NC发布的接口,下面代码中的地址是一个测试地址。

package com.duzq.ws;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

//1.5可用,但NC 有个锁,无法直接调用接口,需要加点其他的东西,这个要加的东西日后再学习
/**
 * @ClassName Soap4
 * @Description TODO
 * @Author TR_XHT
 * @Date 2021/4/20 16:01
 * @Version 1.0
 **/
public class Soap4 {

    public static void main(String[] args) throws IOException {
        //第一步:创建服务地址
        URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl");
        //第二步:打开一个通向服务地址的连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        //第三步:设置参数
        //3.1发送方式设置:POST必须大写
        connection.setRequestMethod("POST");
        //3.2设置数据格式:content-type
        connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
        //3.3设置输入输出,因为默认新创建的connection没有读写权限,
        connection.setDoInput(true);
        connection.setDoOutput(true);

        //第四步:组织SOAP数据,发送请求
        String soapXML = getXML("17321242779");
        //将信息以流的方式发送出去
        OutputStream os = connection.getOutputStream();
        os.write(soapXML.getBytes());
        //第五步:接收服务端响应,打印
        int responseCode = connection.getResponseCode();
        if (200 == responseCode) {//表示服务端响应成功
            // 获取当前连接请求返回的数据流
            InputStream is = connection.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);

            StringBuilder sb = new StringBuilder();
            String temp = null;
            while (null != (temp = br.readLine())) {
                sb.append(temp);
            }
            /**
             * 打印结果
             */
            System.out.println(sb.toString());

            is.close();
            isr.close();
            br.close();
        }
        os.close();
    }
    public static String getXML(String phone) {

        String soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                + "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2003/XMLSchema-instance\" "
                + "xmlns:web=\"http://WebXml.com.cn/\"  "
                + "xmlns:xsd=\"http://www.w3.org/2003/XMLSchema\" "
                + "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
                + "<soap:Body>"
                + "<web:getMobileCodeInfo>"
                + phone
                + "</web:getMobileCodeInfo>"
                + "</soap:Body>"
                + "</soap:Envelope>";
        return soapXML;
    }
}
<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>1.4</version>
</dependency>
<dependency>
	<groupId>commons-httpclient</groupId>
	<artifactId>commons-httpclient</artifactId>
	<version>3.1</version>
</dependency>

2.2.3 CXF 调用

这个方法在JDK1.8适用,但在JDK1.5 中用不了,可以调用NC接口

//JDK1.8可以调用到,1.5不行....
import com.alibaba.fastjson.JSON;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
public class Test {
    public static String callWebService(String wsdUrl, String operationName, String... params) {
        Object[] objects = new Object[0];
        try {
            JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
            Client client = dcf.createClient(wsdUrl);
            //如果存在加密情况的话
            //client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));
            // invoke("方法名",参数1,参数2,参数3....);
            objects = client.invoke(operationName, params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //log.info(wsdUrl + ",webservice服务返回信息{}", JSON.toJSONString(objects[0]));
        System.out.println(JSON.toJSONString(objects[0]));
        return JSON.toJSONString(objects[0]);
    }
}
//调用上面方法
Test.callWebService("http://localhost/uapws/service/nc.intf.hsc.WebXXX?wsdl","WD","ccc");
<dependency>
	<groupId>org.apache.cxf</groupId>
	<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
	<version>3.2.4</version>
	<exclusions>
		<exclusion>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>fastjson</artifactId>
	<version>1.2.75</version>
</dependency>

2.2.4 WSDL2JAVA

这个方法暂时没有用过,就先不写了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值