由于逼人大量抄袭了另一篇神博文,所以在最开始吧原作地址奉上
http://blog.csdn.net/qjyong/article/details/2148558
最近学习了web service,感觉还是很牛逼的。
基于XML,所以是跨平台的,如果要实现跨防火墙的通信使用DCOM或者写一堆asp页面都是很麻烦的,用DCOM具体有多麻烦
我也不清楚,不过根据网上水友说,很麻烦,不过在局域网中使用DCOM或者.NETTremoting要效率得多,至于写一堆asp可
扩展性和可维护性都是很低的。
但是因为基于XML,传输过程中会出现大量无用的数据,大概占60%(网络水友统计)
简单来说web service = SOAP + HTTP + WSDL
SOAP就是 Simple Object Access Protocol 也是基于 XML 的
SOAP的基本结构是这样的
<? xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
...
...
</soap:Header>
<soap:Body>
...
...
<soap:Fault>
...
...
</soap:Fault>
</soap:Body>
</soap:Envelope>
Envelope是根元素,其中xmlns:soap属性的值一定是http://www.w3.org/2001/12/soap-envelope soap的命名空间
soap:encodingStyle表示文档中是用的数据类型。
它指明xml消息是一个soap消息
Header元素的actor属性用于把soap信息从一个断点传输到一个或多个特定的端点。
语法: soap:actor="URL"
mustUnderstands属性从字面意思理解就好了。
Body属性中包含的就是实际要发送的消息了
类似于这样,m:GetPrice 和 m:Item 是在程序中定义的。
<soap:Body>
<m:GetPrice xmlns:m="http://www.jsoso.net/prices">
<m:Item>Apples</m:Item>
</m:GetPrice>
</soap:Body>
一次SOAP响应过程
SOAP请求
POST /InStock HTTP/1.1
Host: www.jsoso.net
Content-Type: application/soap+xml; charset=utf-8
Content-Length: XXX
<? xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.jsoso.net/stock">
<m:GetStockPrice>
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
SOAP响应
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: XXX
<? xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.jsoso.net/stock">
<m:GetStockPriceResponse>
<m:Price>34.5</m:Price>
</m:GetStockPriceResponse>
</soap:Body>
</soap:Envelope>
WSDL 就是叫做 Web Service Sescription Language 的东西,为用户提供了详细的Web Service接口说明书。
WSDL的文档一般比较长。一般真人也不会去读。
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.jsoso.com/wstest"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://www.jsoso.com/wstest"
name="Example">
<types>
<xsd:schema>
<xsd:import
namespace="http://www.jsoso.com/wstest"
schemaLocation="http://localhost:8080/hello?xsd=1"></xsd:import>
</xsd:schema>
</types>
<message name="toSayHello">
<part name="userName" type="xsd:string"></part>
</message>
<message name="toSayHelloResponse">
<part name="returnWord" type="xsd:string"></part>
</message>
<message name="sayHello">
<part name="person" type="tns:person"></part>
<part name="arg1" type="xsd:string"></part>
</message>
<message name="sayHelloResponse">
<part name="personList" type="tns:personArray"></part>
</message>
<message name="HelloException">
<part name="fault" element="tns:HelloException"></part>
</message>
<portType name="Example">
<operation name="toSayHello" parameterOrder="userName">
<input message="tns:toSayHello"></input>
<output message="tns:toSayHelloResponse"></output>
</operation>
<operation name="sayHello" parameterOrder="person arg1">
<input message="tns:sayHello"></input>
<output message="tns:sayHelloResponse"></output>
<fault message="tns:HelloException" name="HelloException"></fault>
</operation>
</portType>
<binding name="ExamplePortBinding" type="tns:Example">
<soap:binding
transport="http://schemas.xmlsoap.org/soap/http"
style="rpc"></soap:binding>
<operation name="toSayHello">
<soap:operation soapAction="sayHello"></soap:operation>
<input>
<soap:body use="literal"
namespace="http://www.jsoso.com/wstest"></soap:body>
</input>
<output>
<soap:body use="literal"
namespace="http://www.jsoso.com/wstest"></soap:body>
</output>
</operation>
<operation name="sayHello">
<soap:operation soapAction="sayHello"></soap:operation>
<input>
<soap:body use="literal"
namespace="http://www.jsoso.com/wstest"></soap:body>
</input>
<output>
<soap:body use="literal"
namespace="http://www.jsoso.com/wstest"></soap:body>
</output>
<fault name="HelloException">
<soap:fault name="HelloException" use="literal"></soap:fault>
</fault>
</operation>
</binding>
<service name="Example">
<port name="ExamplePort" binding="tns:ExamplePortBinding">
<soap:address location="http://localhost:8080/hello"></soap:address>
</port>
</service>
</definitions>
其中有几个重要元素
message元素定义了web Service的函数参数表。
portType定义了 web Service的函数体
binding定义了传输数据的物理实现
service绑定了服务地址
Java Web Service
java中可以用一个叫做Annotation的东西来实现Web Service。
不过java要实现一个Web Service的Bean 必须遵从以下原则
这个类必须是public类
这些类不能是final的或者abstract
这个类必须有一个公共的默认构造函数
这个类绝对不能有finalize()方法
实现还是很简单的
服务端:
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(name="Example", targetNamespace="http://www.jsoso.com/wstest", serviceName="Example")
@SOAPBinding(style=SOAPBinding.Style.RPC)
public class HellowWebService {
private int num=0;
@WebMethod(operationName="toSayHello",action="sayHello",exclude=false)
public String sayHello(@WebParam(name="userName")String userName){
num++;
return "Hello:"+ userName+num;
}
}
其中@后面的一大堆东西其实就是定义了WSDL里的一些东西。
发布类:
import java.util.LinkedList;
import java.util.List;
import javax.xml.ws.Binding;
import javax.xml.ws.Endpoint;
import javax.xml.ws.handler.Handler;
public class startService {
public static void main(String[] args){
HellowWebService serverBean = new HellowWebService();
Endpoint endpoint = Endpoint.publish("http://localhost:8080/hello", serverBean);
Binding binding = endpoint.getBinding();
List<Handler> handlerChain = new LinkedList<Handler>();
//handlerChain.add(new TraceHandler());
binding.setHandlerChain(handlerChain);
System.out.println("服务已启动 http://localhost:8080/hello");
}
}
运行这个发布类,然后在浏览器打开http://localhost:8080/hello?wsdl 就可以看到WSDL了。
客户端:
import com.jsoso.wstest.*;
public class client {
public static void main(String[] args){
Example_Service service = new Example_Service();
Example server = service.getExamplePort();
System.out.println(server.toSayHello("wyl"));
}
}
客户端需要一个客户端框架,使用wsimport命令,这是一个JDK中的命令,并且适用于其他语言编写的服务端。
运行wsimport http://localhost:8080/hello?wsdl 生成两个 class,把这两个class导进客户端中,客户端就可以运行了。