什么是web 服务
web 服务是网络化应用程序的一种,也就是说,这些应用程序主要基于Http之上交付。通常一个web服务可以理解为一种“分布式”应用程序: 其所包含的组件模块在不同的设备之上被发布和执行
web 服务可以分为两大类:基于SOAP协议和基于REST风格,但是区别并不明显。在http协议之上,基于SOAP协议的WEB服务可以看作是一种特殊类型的Rest风格的服务类型。
SOAP本来是提供一种“简单对象访问”的一种协议(不过是一个XML 语言片段,其中信息以消息形式存放),现在已经是SOA(面向服务架构)的一种协议
除非在测试模式下,无论基于SOAP协议还是Rest风格的web 服务,客户端很少是浏览器这样的客户端,大多数情况下是没有界面的某种应用客户端,客户端可以根据提供的开发包使用任何语言开发。web 服务的一个重要特定就是语言无关性,服务的实现和调用的客户端可以使用不一样的编程语言来实现
web 服务语言无关性需要有一个中间层来处理服务和调用者二者之间不同编程语言数据类型差异,而能提供结构化文档交换和处理的XML技术就充当了这个中间层
在一个基于SOAP协议的web 服务中,客户端可以简单的向web 服务者发送一个SOAP 文档作为请求,而服务端可只是简单的发送另一个SOAP文档作为回应
first demo
服务端点接口(service endpoint interface)sei
服务实现bean (service implement bean) sib
sei
package ch01.ts;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)//默认是SOAPBinding.Style.DOCUMENT
public interface TimeService {
@WebMethod
String getTimeAsString();
@WebMethod
long getTimeAsElapsed();
}
sib
package ch01.ts;
import javax.jws.WebService;
import java.util.Date;
@WebService(endpointInterface = "ch01.ts.TimeService")
public class TimeServiceImpl implements TimeService{
@Override
public String getTimeAsString() {
return new Date().toString();
}
@Override
public long getTimeAsElapsed() {
return System.currentTimeMillis();
}
}
通常在一个完整的应用产品模式下,web 服务可能发布在jBoss等其他不同的web服务器中,当然也可以让一个简单的java 应用程序担任(不足的是同一时刻一次只能处理一个客户请求)
publisher
package ch01.ts;
import javax.xml.ws.Endpoint;
public class TimeServicePublisher {
public static void main(String[] args) {
Endpoint.publish("http://localhost:9876/ts", new TimeServiceImpl());
}
}
测试是否发布成功 http://localhost:9876/ts?wsdl
wsdl(web service describe language )
返回
<!--
Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e.
-->
<!--
Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e.
-->
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ts.ch01/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ts.ch01/" name="TimeServiceImplService">
<types/>
<message name="getTimeAsString"/>
<message name="getTimeAsStringResponse">
<part name="return" type="xsd:string"/>
</message>
<message name="getTimeAsElapsed"/>
<message name="getTimeAsElapsedResponse">
<part name="return" type="xsd:long"/>
</message>
<portType name="TimeService">
<operation name="getTimeAsString">
<input wsam:Action="http://ts.ch01/TimeService/getTimeAsStringRequest" message="tns:getTimeAsString"/>
<output wsam:Action="http://ts.ch01/TimeService/getTimeAsStringResponse" message="tns:getTimeAsStringResponse"/>
</operation>
<operation name="getTimeAsElapsed">
<input wsam:Action="http://ts.ch01/TimeService/getTimeAsElapsedRequest" message="tns:getTimeAsElapsed"/>
<output wsam:Action="http://ts.ch01/TimeService/getTimeAsElapsedResponse" message="tns:getTimeAsElapsedResponse"/>
</operation>
</portType>
<binding name="TimeServiceImplPortBinding" type="tns:TimeService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
<operation name="getTimeAsString">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal" namespace="http://ts.ch01/"/>
</input>
<output>
<soap:body use="literal" namespace="http://ts.ch01/"/>
</output>
</operation>
<operation name="getTimeAsElapsed">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal" namespace="http://ts.ch01/"/>
</input>
<output>
<soap:body use="literal" namespace="http://ts.ch01/"/>
</output>
</operation>
</binding>
<service name="TimeServiceImplService">
<port name="TimeServiceImplPort" binding="tns:TimeServiceImplPortBinding">
<soap:address location="http://localhost:9876/ts"/>
</port>
</service>
</definitions>
执行的操作(porttype)
<portType name="TimeService">
<operation name="getTimeAsString">
<input wsam:Action="http://ts.ch01/TimeService/getTimeAsStringRequest" message="tns:getTimeAsString"/>
<output wsam:Action="http://ts.ch01/TimeService/getTimeAsStringResponse" message="tns:getTimeAsStringResponse"/>
</operation>
<operation name="getTimeAsElapsed">
<input wsam:Action="http://ts.ch01/TimeService/getTimeAsElapsedRequest" message="tns:getTimeAsElapsed"/>
<output wsam:Action="http://ts.ch01/TimeService/getTimeAsElapsedResponse" message="tns:getTimeAsElapsedResponse"/>
</operation>
</portType>
将服务提供的操作集中在一起描述,TimeService 有两项执行操作getTimeAsElapsed和getTimeAsString。就像是Java的一个接口,只提供了服务操作的抽象描述,而没有提供具体的实现细节。每个服务操作都包括input 消息和output 消息,input消息代表着服务的输入参数。在web服务运行时的环境中,每一个input output 消息都是一个SOAP文档
service
<service name="TimeServiceImplService">
<port name="TimeServiceImplPort" binding="tns:TimeServiceImplPortBinding">
<soap:address location="http://localhost:9876/ts"/>
</port>
</service>
location 中的url 代表的是请求服务的地址,客户端通过此才能访问到这个服务
对于客户端,wsdl可以提供很多帮助,不同开发语言一般都会提供从wsdl文档直接生成客户端开发相关代码支持的工具包,java提供了工具程序叫wsimport
java 客户端
wsimport -p ts.client -keep http://localhost:9876/ts?wsdl
生成对应的代码
测试主类
public class Main {
public static void main(String[] args) {
TimeServiceImplService timeServiceImplService = new TimeServiceImplService();
TimeService timeService = timeServiceImplService.getTimeServiceImplPort();
System.out.println(timeService.getTimeAsString());
}
}
python 测试
import suds
url = "http://localhost:9876/ts?wsdl"
client = suds.Client(url)
print(client.service.getTimeAsString())
soap请求回应分析
针对TimeService服务的请求
POST /ts HTTP/1.1
Accept: text/xml, multipart/related
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://ts.ch01/TimeService/getTimeAsStringRequest"
User-Agent: JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e
Host: 127.0.0.1:9999
Connection: keep-alive
Content-Length: 187
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:getTimeAsString xmlns:ns2="http://ts.ch01/"></ns2:getTimeAsString></S:Body></S:Envelope>
- 默认是post,get请求参数不放在请求体
- 在请求体中包含一个SOAP文档(SOAP信封),body中包含一个getTimeAsString的元素
针对web服务,收到http请求,将soap 信封拆包,分析出请求的服务操作,,然后调用对应的方法,将返回值包裹在Soap消息中,并且发回给客户端
HTTP/1.1 200 OK
Date: Wed, 27 Dec 2017 02:56:43 GMT
Transfer-encoding: chunked
Content-type: text/xml; charset=utf-8
f8
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:getTimeAsStringResponse xmlns:ns2="http://ts.ch01/"><return>Wed Dec 27 10:56:43 CST 2017</return></ns2:getTimeAsStringResponse></S:Body></S:Envelope>
网友评论