WebServices和Xfire学习总结
来源:互联网 发布:云安全软件怎么样 编辑:程序博客网 时间:2024/06/05 08:33
那么,它们是如何运作的呢?比如,一个应用程序(A)需要和另一个应用程序(B)在SOAP的帮助下进行彼此通讯。它们将使用下面的框架图来完成这个过程:
这个SOAP信封(SOAP envelope)是一个包含以下内容的XML文档:
<?xml version=1.0 encoding=UTF-8?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/
soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/
XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns1:sayHi xmlns:ns1="urn:HelloWorld_SOAPService"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/
soap/encoding/">
<ourName xsi:type="xsd:string">Superman</ourName>
</ns1:sayHi>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>:
从SOAP Service接收的SOAP Envelope
<?xml version=1.0 encoding=UTF-8?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/
soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/
XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns1:sayHiResponse xmlns:ns1="urn:HelloWorld_SOAPService"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.
org/soap/encoding/">
<return xsi:type="xsd:string">Hello my friend, Superman!
Glad to see you!</return>
</ns1:sayHiResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
要理解SOAP Envelope中的所有标签的含义,需要花一点时间阅读 http://www.w3.org/2001/06/soap-envelope 命名空间规范。
其实在后面的学习中,因为Java提供了各种XML的API(JDOM),再搭配上XFire这个SOAP架构,所以一般只需要知道SOAP的工作原理就够了,基本上不会涉及到自己去写一个SOAP信封。
你会怎样向别人介绍你的Web service有什么功能,以及每个函数调用时的参数呢?你可能会自己写一套文档,你甚至可能会口头上告诉需要使用你的Web service的人。这些非正式的方法至少都有一个严重的问题:当程序员坐到电脑前,想要使用你的Web service的时候,他们的工具(如Visual Studio)无法给他们提供任何帮助,因为这些工具根本就不了解你的Web service。解决方法是:用机器能阅读的方式提供一个正式的描述文档。Web service描述语言(WSDL)就是这样一个基于XML的语言,用于描述Web service及其函数、参数和返回值。因为是基于XML的,所以WSDL既是机器可阅读的,又是人可阅读的,这将是一个很大的好处。一些最新的开发工具既能根据你的Web service生成WSDL文档,又能导入WSDL文档,生成调用相应Web service的代码。
XFire
XFire是一个开源的SOAP框架,用它可以快速开发WS。
它在Eclipse下的配置也是相当简单,甚至你可能都不需要做什么配置。
在Eclipse下新建一个Web Service Project工程,这个工程与传统的Web Project工程不同的不过是通过向导添加XFire以及services.xml。
* HelloWorldService 中声明需要发布成 Web 服务的所有 Java 方法 HelloWorldService 作为Web服务接口
*/
public interface HelloWorldService {
/**
* sayHello 方法声明了 Web 服务对外暴露的接口
*
* @return 返回给客户端的字符串
*/
public String sayHello(String name);
}
* HelloWorldServiceImpl 中为 Web 服务接口中声明的所有 Java 方法提供具体实现 HelloWorldServiceImpl
* 作为 Web 服务的实现类
*/
public class HelloWorldServiceImpl implements HelloWorldService {
* sayHello 方法为 HelloWorldService 服务接口定义的 sayHello 方法提供具体实现
*
* @see org.vivianj.XFire.pojo.HelloWorldService#sayHelloToXFire()
*/
public String sayHello(String name) {
return "Hello World!"+name;
}
关于services.xml各元素信息,请参阅官方文档http://xfire.codehaus.org/services.xml+Reference。
现在我们的Web服务已经配置好了,我们可以在地址栏中输入http://localhost:8080/SimpleWSExam/services,可以看到
单击wsdl连接,可以看到关于这个WS的WSDL。在XFire下配置WS就是这么简单!
现在我们来写客户端,
HelloWorldClient.java
public class HelloWorldClient {
public static void main(String args[]){
String serviceURL = "http://localhost:8080/SimpleWSExam/services/HelloWorldService";
Service serviceModel = new ObjectServiceFactory().create(HelloWorldService.class,null,"http://localhost:8080/SimpleWSExam/services/HelloWorldService",null);
XFireProxyFactory serviceFactory = new XFireProxyFactory();
try {
HelloWorldService hello=(HelloWorldService)serviceFactory.create(serviceModel, serviceURL);
System.out.println(hello.sayHello("Jackal Wood"));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
一个众人皆知的道理是,WS是只读的,也就是说,WS不能有setxxx()。
如果取的值是List或者是Map,则需要在与源文件相同的目录下创建名为xxxx.aegis.xml的文件,其中xxxx是服务的类名,比如我们在接口中添加public List getList();并实现之,如果客户端想调用这个函数,需要写HelloWorldService.aegis.xml:
Aegis 是 XFire 的缺省的绑定方式,可以将 XML 映射成 POJO。,在官方例子中,aegis文件中对类的描述基本是全部的,不像我这里只是写上必须的描述。关于aegis,请见其它更详细的资料。当然XFire不仅仅可以绑定aegis,它还支持JAXB2、XMLBeans、Castor、Jibx。
身份验证
XFire提供了四种身份验证的方式,分别是http验证,JSR181,Handler验证,WS-Security。
这里我们只谈Handler验证。
SOAP的原理告诉我们一个WS交互的流程是客户端发送请求->服务器接收请求->服务器发送数据->客户端接收数据,handler可以让我们在这四个操作中之前进行编码,所以,我们的验证进行在客户端发送请求和服务器接收请求的时候,因此,我们要写两个handler,然后把它们装配上就可以了。
服务器接收请求:
AuthentificationHandler.java:
package org.vivianj.xfire.handlers;
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.handler.AbstractHandler;
import org.jdom.Element;
import org.jdom.Namespace;
public class AuthentificationHandler extends AbstractHandler {
public void invoke(MessageContext cfx) throws Exception {
// TODO Auto-generated method stub
if(cfx.getInMessage().getHeader() == null)
{
throw new org.codehaus.xfire.fault.XFireFault("请求必须包含验证信息",org.codehaus.xfire.fault.XFireFault.SENDER);
}
Element token=cfx.getInMessage().getHeader().getChild("AuthenticationToken");
if (token == null)
{
throw new org.codehaus.xfire.fault.XFireFault("请求必须包含身份验证信息",
org.codehaus.xfire.fault.XFireFault.SENDER);
}
String username = token.getChild("Username").getValue();
String password = token.getChild("Password").getValue();
try
{
//进行身份验证
if(username.equals("jackal") && password.equals("talent"))
//这语句不显示
System.out.println("身份验证通过");
else throw new Exception();
// 身份验证通过
// cfx.setProperty(User_KEY, user);
}
catch (Exception e)
{
throw new org.codehaus.xfire.fault.XFireFault("非法的用户名和密码", org.codehaus.xfire.fault.XFireFault.SENDER);
}
}
}
客户端发送请求:
ClientAuthenticationHandler.java
package org.vivianj.xfire.handlers;
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.handler.AbstractHandler;
import org.jdom.Element;
import org.jdom.Namespace;
public class ClientAuthenticationHandler extends AbstractHandler {
private String username = null;
private String password = null;
public ClientAuthenticationHandler() {
}
public ClientAuthenticationHandler(String username,String password) {
this.username = username;
this.password = password;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void invoke(MessageContext context) throws Exception {
Element el = new Element("header");
context.getOutMessage().setHeader(el);
Element auth = new Element("AuthenticationToken");
Element username_el = new Element("Username");
username_el.addContent(username);
Element password_el = new Element("Password");
password_el.addContent(password);
auth.addContent(username_el);
auth.addContent(password_el);
el.addContent(auth);
}
}
可以看到,客户端在发送数据前做的事情是:往SOAP信封里加入了一个头信息,并在这个头信息中包含了AuthenticationToken属性,它又包含了Username以及Password两个属性,而用户名和密码的值通过形参穿过来。这里面用到了JDOM,JDOM是一个针对JAVA的轻量级的文档对象模型。
服务器接受到SOAP信封后先找到这个验证信息,然后验证它。
装配:
客户端装配:
只需要在客户端程序HelloWorldClient.java中加入
Client client = Client.getInstance(hello);
client.addOutHandler(new ClientAuthenticationHandler("jackal","talent"));
服务器端装配:
需要在services.xml中开始写入,重写后的文件
services.xml:
如果你有Spring+Struts的经验,你会发现XFire+Spring和它很像。
web.xml:
这个web.xml有这几点要注意:
1.XFire的servlet-class已经不是 org.codehaus.xfire.transport.http.XFireConfigurableServlet,而是org.springframework.web.servlet.DispatcherServlet。
2.在contextConfigLocation中我们又加载了XFire自身的xfire.xml。
xfire-servlet.xml:
如果你有struts+spring的经验,你一定对action-servlet.xml不陌生,没错,这里我们需要xfire-servlet.xml,"xfire"映射web.xml文件中<servlet-name>,而且他的路径应该是根目录下
META-INF/xfire/service.xml文件可以省略了,因为web服务的定义在xfire-servlet.xml中可以找到。
下面要做的工具就是配置了。
这个文件的上半部分将HelloWorldService这个URL和hello这个bean联系在一起。下半部分定义了Web服务的bean和服务接口。其中HelloWorldBean是我们在applicationContext.xml中配置的那个Bean。
最后来看看applicationContext.xml
如果有兴趣的朋友,还可以看看SpringSide2.0中关于这部分的源码。
最后说一句,与spring集成后,就不能通过http://localhost:8080/services或者http://localhost:8080/services/HelloService查看是否通,而只能通过http://localhost:8080/services/HelloService?wsdl.
- WebServices和Xfire学习总结
- XFire-WebServices学习资料
- java使用xfire创建和调用webservices
- [webservices开发]XFire实战
- [webservices开发]配置XFire
- Eclipse构建WebServices[XFire]
- Eclipse构建WebServices(XFire)
- tomcat发布xfire webservices
- Xfire spring webservices开发
- REST风格webservices学习总结
- wss4j+xfire+spring 学习总结三(密钥生成和配置)
- xfire 集成spring的webservices
- xfire-在客户端调用WebServices
- 使用XFire开发WebServices服务端
- 使用XFire开发WebServices客户端
- 使用XFire开发WebServices服务端
- axis和xfire以及CXF三种方式实现WebServices分别有什么优缺
- axis和xfire以及CXF三种方式实现WebServices分别有什么优缺
- IBatis.Net怎么使用VS 2005来做单元测试
- 用Pop3收取gmail的邮件(摘录)
- Criteria 进阶查询
- 利用XMLBean轻读写XML(摘录)
- 百度知道
- WebServices和Xfire学习总结
- 重要网络资源
- ASN.1 encoding rules
- NetBeans 快速开发 Web Application(摘录)
- 文档模版 下载
- 如何无交互的自动安装Solaris软件包
- 程序员的岁数是问题吗?
- .Net给图片加上文字
- 与DotNet数据对象结合的自定义数据对象设计(IBatisNet)