XFire体系及重要API(1)
ServiceFactory
ServiceFactory是XFire的核心类,它可以将一个POJO生成为一个Web Service。
通过ServiceFactory可以将POJO导出为Web Service:
XFire xfire = XFireFactory.newInstance().getXFire();
ServiceFactory factory = new ObjectServiceFactory(xfire.getTransportManager(), null);
Service service = factory.create(YourService.class);
这样我们就为YourService类创建基于SOAP 1.1封装的Web Service。
Service的输入输出参数如果为简单类型的对象(由String、int、long等基本类型组成),无须进行额外的映射设置,对于复杂类型的输入输出Service,XFire将会自动尝试将其序列化(通过Aegis绑定)。
紧接着,你就可以注册这个Service。
xfire.getServiceRegistry().register(service);
XFire推荐通过一个接口开放服务,此时,你可以指定一个具体的实现类:
service.setProperty(ObjectInvoker.SERVICE_IMPL_CLASS, YourServiceImpl.class);
Handler
一个Handler可以看成是XFire的一个加工套件。
XFire通过Handler定义SOAP发送和接收之前的各种加工处理逻辑。
如Handler可以对SOAP体的内容进行加工处理,或者SOAP头进行处理。可以简单地通过扩展AbstractHandler定义一个自己的Handler类:
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.handler.AbstractHandler;
public class YourHandler extends AbstractHandler
{
public void invoke(MessageContext context)
{
// Do Sth...
}
}
Handler可以注册到Service或Transport(代表SOAP输入输出的的传输对象)中。
在服务请求和响应管道里,Service和Transport注册的Handler将执行额外的处理操作。
你可以按如下方式注册Handler:
…
Servic s = factory.create(YourService.class);
s.addInHandler(new YourHandler1());①添加一个Handler,对输入SOAP进行处理
s.addOutHandler(new YourHandler2());②添加一个Handler,对输出SOAP进行处理
s.addFaultHandler(new YourHandler3());③添加一个Handler,对错误SOAP进行处理
…
下面的Handler对SOAP头进行处理,添加一些特定的信息:
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.handler.AbstractHandler;
public class YourHandler extends AbstractHandler
{
…
public QName[] getUnderstoodHeaders()
{
return new QName[] { new QName("YourHeader", "urn:your:header:ns") };
}
}
在管道中以流方式处理SOAP
XFire是完全基于流数据处理进行工作的系统,这意味着XFire不是将整个SOAP文档缓存在内存中,而是以管道的方式接收SOAP流数据。
这种工作方式的转变带来了可观的性能回报,同时节省了内存的占用。
对于习惯了Axis、GLUE等这些基于DOM处理模型Web Service框架的开发者来说,需要一些时间来适应这种转变。
XFire从管道中接收一个SOAP请求到返回一个SOAP响应,会经历一系列的阶段。在管道调用的任何一个阶段,
XFire都可以添加一些额外的Handler,在对消息进行加工处理后再传入到下一个阶段中。图1展示了XFire管道从接收SOAP请求到返回SOAP响应所经历的所有阶段:
(图一)
图1 XFire Web Service请求和响应的过程
在SOAP请求消息对Web Service发起真正调用之前,分别会经过传输(Transport)、预转发(PreDispatch)、转发(Dispatch)、策略实施(Policy)、用户信息处理(User)、预调用(PreInvoke)、服务调用(Service Invocation)等阶段。当,Web Service调用后,XFire生成响应SOAP消息并通过管道发送给客户端请求者,这一过程会先后经历调用后(PostInvoke)、用户信息处理(User)、策略实施(Policy)、传输(Transport)这四个阶段。每一个阶段都是一个可控点,通过编写并注册一些相应的Handler就可以实施一些额外处理逻辑,如审计、SOAP消息加密、签名、压缩等。
XFireExporter
XFire为Spring提供了方便易用的导出器XFireExporter,借助XFireExporter的支持,我们可以在Spring容器中将一个POJO导出为Web Service。
BbtForum是Baobaotao论坛业务服务类,它拥有众多的业务方法,我们现在希望将其提供查询最近几天精华帖子数的业务方法开放为Web Service。为了避免过多地开放不必要的接口方法,需要定义了一个BbtForumService窄接口,它定义那些需要开放为Web Service的业务方法:
package com.baobaotao.xfire.server;
public interface BbtForumService {
int getRefinedTopicCount(int lastDay);①查询最近几天论坛精华帖子数的服务接口
}
将一个业务类所有需要开放为Web Service的方法通过一个窄接口来描述是值得推荐的作法,这让Web Service的接口显得很“干净”。
其次,XFire的导出器也需要服务接口的支持,因为它采用基于接口的动态代理技术。真实的业务类当然需要实现Web Service窄接口:
package com.baobaotao.service;
import javax.jws.WebService;
import com.baobaotao.xfire.server.BbtForumService;
public class BbtForum implements BbtForumService{①实现Web Service窄接口
public int getRefinedTopicCount(int lastDay) {②该方法在窄接口中定义,导出为Web Service服务
if(lastDay <= 2) return 10;
else if(lastDay <= 5) return 20;
else return 32;
}
…
}
BbtForum中的方法在真实的系统中应该引用其它的业务类或DAO获取数据库中的真实数据,为了简化实例,我们通过一段简单的代码进行模拟,如②所示。
在拥有了窄接口之后中,剩余的工作就是在Spring配置文件中通过XFireExporter将BbtForum#getRefinedTopicCount()方法导出为Web Service,具体配置如代码清单1所示:
代码清单1 applicationContext.xml:将POJO导出Web Service
<beans>
①引入XFire预配置信息
<import resource="classpath:org/codehaus/xfire/spring/xfire.xml" />
②使用XFire导出器
<bean id="BbtForumService" class="org.codehaus.xfire.spring.remoting.XFireExporter">
<property name="serviceFactory" ref="xfire.serviceFactory" />②-1:引用xfire.xml中定义工厂
<property name="xfire" ref="xfire" />②-2:引用xfire.xml中定义的xfire实例
<property name="serviceBean" ref="bbtForum" />②-3:业务服务Bean
<property name="serviceClass"②-4:业务服务Bean的窄接口类
value="com.baobaotao.xfire.server.BbtForumService" />
<property name="name" value="BbtForumServiceUT"/>②-5:Web Service名称
</bean>
<bean id="bbtForum" class="com.baobaotao.service.BbtForum" />
</beans>
上面的配置将BbtForum所有定义在BbtForumService窄接口中的方法导出为Web Service。
在XFire核心JAR包中拥有一个预定义的Spring配置文件,它定义了XFire在Spring中必须用到的一些Bean和资源,需要引入这个预定义的配置文件,如①所示。
紧接着,就可以使用XFireExporter将业务类导出为Web Service了。②-1、②-2为导出器引入XFire环境,对于任何导出器,这都是标准的配置,所以如果有多个导出器,可以将这两个属性通过一个父<bean>标签进行抽象。而②-3、②-4分别定义了业务服务类及需要导出为Web Service方法的窄接口。Web Service的默认名称是窄接口的类名,即BbtForumService,你可以通过name属性显式指定Web Service的名称,如②-5所示。
通过这个简单的配置,就完成了将业务服务类开放为Web Service的工作,接下来,我们就可以通过配置Web 服务器的web.xml,将其通过HTTP传输协议开放出去。
配置web.xml
一般情况下,我们通过HTTP作为Web Service的传输协议,这样你只需启动一个Web服务器(如Tomcat),客户端就可以通过HTTP访问到Web Service服务了。
为了集成Spring容器,XFire专门提供一个XFireSpringServlet,我们可以在web.xml中配置该Servlet,将Spring容器中定义的Web Service在某个URI下发布,如代码清单2所示:
代码清单2 web.xml配置
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>①刚才配置的Spring文件
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>②配合Spring容器中XFire一起工作的Servlet
<servlet-name>xfireServlet</servlet-name>
<servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>xfireServlet</servlet-name>
<url-pattern>/service/*</url-pattern>③在这个URI下开放Web Service服务
</servlet-mapping>
</web-app>
首先,我们指定在代码清单1中所配置的Spring配置文件,如①所示。然后定义一个XFireSpringServlet,让其截取所有/service URI下的请求,如②和③所示。
创建一个Tomcat配置文件baobaotao.xml,并编写一行映射配置(这里使用Tomcat 5.5),这种方式无须将Web应用打包成WAR,方便开发测试:
<Context path="/baobaotao" docBase="D:/masterSpring/chapter16/webapp"/>
将baobaotao.xml放置到<TOMCAT_HOME>/conf/Catalina/localhost目录下,启动Tomcat服务,
键入http://localhost:8080/baobaotao/service/BbtForumService?wsdl,你将可以看到BbtForumService对应的WSDL。
阅读这个WSDL文档,我们可以知道BbtForum的getRefinedTopicCount已经被成功地发布为Web Service了。只要拿到这个WSDL就可以开发相应的客户端调用程序了。
转载于:https://blog.51cto.com/haidao/516733