理论学完了,该实战了哈。
1、建立一个基于xfire的WS工程
对外提供的服务接口:
public interface CalService {
int add(int a, int b);
int minus(int a, int b);
int multi(int a, int b);
int div(int a, int b);
}
实现类:
public int add(int a, int b) {
System.out.println("add invoked");
return a + b;
}
@Override
public int minus(int a, int b) {
System.out.println("minus invoked");
return a - b;
}
@Override
public int multi(int a, int b) {
System.out.println("multi invoked");
return a * b;
}
@Override
public int div(int a, int b) {
System.out.println("div invoked");
return a / b;
}
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<display-name>XFire Servlet</display-name>
<servlet-name>XFireServlet</servlet-name>
<servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/servlet/XFireServlet/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
Xfire的配置文件Services.xml:
加入我们提供的服务及实现类,给起个名字
<beans xmlns="http://xfire.codehaus.org/config/1.0">
<service>
<name>calcService</name>
<serviceClass>com.zhaozh.service.CalService</serviceClass>
<implementationClass>com.zhaozh.service.impl.CalServiceImpl</implementationClass>
</service>
</beans>
2、运行
先给它跑起来,控制台输出:
2011-4-28 10:45:46 org.codehaus.xfire.spring.ServiceBean afterPropertiesSet
信息: Exposing service with name {http://service.zhaozh.com}calcService
说明我们已经将我们的服务calcService暴露给外面了,可以供其他应用程序使用。
接着在FF里输入http://localhost:8080/myxfire/services/,出现下面的界面:
打开连接[wsdl]
http://localhost:8080/myxfire/services/calcService?wsdl看到一个xml的文档,ok这个就是WSDL描述的Web Services(文档内容参见——wsdl 学习)。
这就是我们对外提供服务的窗口了。其他的应用程序和平台就可以使用我们提供的这个简单的服务。
到这里我们的WS服务已经提供好了。接下来就是用WS的调用访问。
3、建立wsclient客户端,使用提供的服务。
当然了有现成的工具帮我们生成,我们只需要写一个客户端访问程序直接调用就ok。目录结构如下。ClientTest是我们的测试类。很简单的,就像在本地调用我们的程序是一模一样的。
public class ClientTest {
public static void main(String args[]){
calserviceClient client = new calserviceClient();//new 一个client对象
calservicePortType portType = client.getcalserviceHttpPort();//获取WS上面的操作类
System.out.println(portType.add(1,2));//直接调用
System.out.println(portType.minus(1,2));//直接调用
System.out.println(portType.multi(1,2));//直接调用
System.out.println(portType.div(1,2));//直接调用
}
}
运行这个简单的客户端测试下
Console输出:
3
-1
2
0
Ok,我们使用的服务已经将正确结果返回给我们了。
再回到我们的WS服务器端查看console输出:
add invoked
minus invoked
multi invoked
div invoked
到这里说明已经有应用程序(wsclient)调用我们提供的服务啦。
4、通过.NET平台调用WS(嗯体现了WS跨平台协作的优势)
新建一个C#的控制台应用程序,加入web引用,可以看到,输入我们的
URL:http://localhost:8080/myxfire/services/calcService?wsdl后,找到了一个服务calcService.,把这引用添加进来,起个名字叫做xfireService。
然后书写对ws服务的调用,就行在本地操作是一样一样滴。
嗯运行下试试:
结果出来了,再回到服务器端瞅瞅:
add invoked
minus invoked
multi invoked
div invoked
加减乘除都调用了。嗯说明有一个外部应用程序调用我们的服务了。是谁调用的我不知道,也没必要知道,你只管提供服务就ok。
5、分析
到此为止,算是明白的ws到底是个什么东东,那么ws跟wsclient之间到底是怎么通信的呢?凭什么.NET跟其他的平台可以调用我提供的服务呢?这就是需要分析的另外一步了。其实他们之间的通信协议已经在wsdl里面指定了(参见WSDL学习)。这里截取一点点片段说明:没错就这个片段
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
这里指定了通信用的协议就是SOAP,底层通过HTTP传送具体的SOAP报文。
我们用tcpmon来监控一下这里面通信的细节:这里要改下我们客户端调用的接口,改成8888,然后启动tcpmon,建立一个monitor。抓取http调用的请求跟响应;看看里面到底发生了什么。(我们就以一个add操作为例,其他类似)
请求:
POST /myxfire/services/calcService HTTP/1.1
SOAPAction: ""
Content-Type: text/xml; charset=UTF-8
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; XFire Client +http://xfire.codehaus.org)
Host: 127.0.0.1:8888
Expect: 100-continue
Content-Length: 305
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><ns1:add xmlns:ns1="http://service.zhaozh.com"><ns1:in0>1</ns1:in0><ns1:in1>2</ns1:in1></ns1:add></soap:Body></soap:Envelope>
http请求头略过不谈主要看看请求体:我们可以看到很熟悉的soap的内容了,其实就是这样的,通过把对ws的请求转换为saop的xml格式来进行通信的。看看soap body内容,子元素是不是指定了操作“add”,然后还有操作参数,1跟2,就是我们在client的时候调用的两个参数。
再看看服务器给我们返回的响应:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/xml;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 28 Apr 2011 03:44:24 GMT
12d
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><ns1:addResponse xmlns:ns1="http://service.zhaozh.com"><ns1:out>3</ns1:out></ns1:addResponse></soap:Body></soap:Envelope>
响应头略过不谈,看看response的具体内容,也是很熟悉的soap的xml格式吧。里面看body子元素addResponse表明是哪个操作的响应,以及out子元素,内容是3,这就是我们的返回结果了。
结论就是ws底层的通信使用了soap协议在http上传输的。
总结:到此为止总算是把Web Services了解一个大概了,具体的还要到实际的项目中得到具体的应用了。学习总结下,欢迎批评指正。