- 浏览: 31551 次
- 性别:
- 来自: 厦门
最新评论
<转>XFire生火指南(下)
请先阅读:XFire生火指南(上)
1. JSR181
JSR181式通过annotated POJO ,零配置文件的导出Web服务,是BEA倡导的,JavaEE5里的正规方式, XFire作了良好的支持。
但是,XFire关于JSR181方式的文档还不够清晰,请完整阅读本节以避免其中的陷阱。
1.1 参考文章
Spring, Hibernate and XFire
Webservices with Spring, XFire and jsr181
Basic Spring Web services with XFire and JSR 181
XFire JSR181参考文档
1.2 ApplicationContext.xml
因为Web服务配置都写在了annotation,applicationContext.xml文件的内容变得比较固定。需要注意JSR181WebAnnotations与HandlerMapping不能lazy init。
<beans default-autowire="byName">
<!--引入XFire的预配置文件-->
<import resource="classpath:org/codehaus/xfire/spring/xfire.xml"/>
<!-- 获得applicationContext中所有bean的JSR181 annotation -->
<bean id="webAnnotations" class="org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations" lazy-init="false"/>
<!-- 定义handler mapping,将所有JSR181定义的bean导出为web service -->
<bean id="jsr181HandlerMapping" class="org.codehaus.xfire.spring.remoting.Jsr181HandlerMapping" lazy-init="false">
<property name="xfire" ref="xfire"/>
<property name="webAnnotations" ref="webAnnotations"/>
</bean>
</beans>
1.3 Interface+Impl模式
不同于XFire传统模式,窄接口不是必须的,只是考虑到有个接口,配置都在接口上做,对原来的Manager类侵入较少。
如果采用Interface,Interface将担任主要的配置工作。
首先定义@WebService,可定义自己的NameSpace,如果不定义将采用默认的生成算法。
接口中的函数将默认全部导出,不需要再用@WebMethod注释,也可以如下例般进行关于Param,Result的更进一步配置:
@WebService(targetNamespace = "http://www.springside.org.cn")
public interface BookService {
@WebResult(name = "SearchResult")
List<Book> findBooksByCategory(@WebParam(name = "category", header = true)String cateoryId);
}
Manager不是纯粹的POJO,需要带上@WebService注释,指明接口。
@WebService(serviceName = "BookService", endpointInterface = "org.springside.bookstore.components.xfire.server.jsr181.BookService")
public class BookManager implements BookService {
...
}
陷阱一:XFire JSR181参考文档 中在Interface中以@WebService(name="BookService")来定义ServiceName,这个做法看起来也比较合理,但实际上需要在Manager中以@WebService(serviceName ="BookService") 来定义,比较古怪。
1.4 纯POJO模式
参考文档中的例子,需要配置@WebMethod 指定需要导出的函数。
@WebService(name = "EchoService", targetNamespace = "http://www.openuri.org/2004/04/HelloWorld")
public class Jsr181EchoService
{
@WebMethod(operationName = "echoString", action = "urn:EchoString")
@WebResult(name = "echoResult")
public String echo(@WebParam(name = "echoParam", header = true) String input)
{
return input;
}
}
1.5 Client注意事项
陷阱二:和传统模式的client有一点最大的区别,serviceModel需要实际的Manager类而不是接口类来做参数:
Service serviceModel = new AnnotationServiceFactory().create(BookManager.class);
2. Client
XFire的Client并不算强项,一共有三种模式:
2.1 Client开发者拥有Web服务端的class
Client与Server是同一个开发团队也好,Server端团队以jar形式提供开发包也好,反正如果能拿到服务端的接口Class和Entity类及aegis 配置文件的话。
传统POJO模式:
Service serviceModel = new ObjectServiceFactory().create(BookService.class);
BookService service = (BookService) new XFireProxyFactory().create(serviceModel, serviceURL);
service.findBooksByCategory(cateoryId);
JSR181模式,注意这里Server端开发组需要向Client提供BookService的实现类BookManager,而不止于接口,有点危险:
Service serviceModel = new AnnotationServiceFactory().create(BookManager.class);
BookService = (BookService) new XFireProxyFactory().create(serviceModel, serviceURL);
service.findBooksByCategory(cateoryId);
SpringSide 用泛型封装了一个XFireClientFactory,调用代码如下:
BookService service = XFireClientFactory.getClient(serviceURL, BookService.class);
BookService service = XFireClientFactory.getJSR181Client(serviceURL, BookService.class, BookManager.class);
2.2 动态模式
动态模式不需要服务端的class,不过性能和复杂对象映射等估计做得不会太好。
Client client = new Client(new URL("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL"));
Object[] results = client.invoke("ConversionRate", new Object[] {"BRL", "UGX"});
2.3 根据WSDL生成Client Stub
这才是Web Service Client的王道,可以访问任意语言编写的Web Service,将在下一个版本中演示。
可以用XFire的Ant Task来生成,但使用MyEclipse的XFire集成会更加方便。生成的代码必须是JDK5.0的版本。
3. 测试
XFiire很重要的一个特性是提供了无须启动Web容器也能进行单元测试的能力。
原理就是利用XFire的JVM模式,以xfire.local://BookService channel而不是http://localhost/service/BookService来访问服务。
测试的方式分两种:
一种是纯服务器角度,不编写客户端代码,以SOAP XML形式发送请求,返回的也是SOAP XML字串,直接对XML进行测试。
一种是编写2.1 中Client代码来进行测试。
前一种的测试的隔离度较高,而后一种比较简便。
3.1 测试基类
无论那种方式,都使用Xfire的AbstractXFireSpringTest基类,实现createContext()回调函数。
protected ApplicationContext createContext() { return ClassPathXmlApplicationContext(new String[]{"classpath*:applicationContext*.xml"});
}
另外测试基类还要完成一个很重要的工作就是要解决Hibernate的LazyLoad问题,做到OpenSession In Test。因此,SpringSide专门封装了一个XFireTestCase的基类。
3.2 用Client代码直接测试
下文直接用client代码调用findBooksByCategory方法,得到返回值后进行各种Assert判断。
注意和普通client code的两处区别:servericeURL换成local,factory须加入getXFire()作参数。
Service serviceModel = new ObjectServiceFactory().create(BookService.class);
XFireProxyFactory factory = new XFireProxyFactory(getXFire());
BookService service = (BookService) factory.create(serviceModel, "xfire.local://BookService");
List list = service.findBooksByCategory("0");
assertNotNull(list);
...
3.3 纯服务端测试
编写一段SOAP XML,以任意命名保存,下文以"Java"作参数,调用findBooksByName方法。
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<findBooksByName xmlns="http://www.springside.org.cn">
<in1>Java</in1>
</findBooksByName>
</env:Body>
</env:Envelope>
测试代码调用前面的XML,返回XML Document对象,再用基类提供的一些Assert方法检查结果
Document doc = invokeService("BookService","/org/springside/xfire/BookService.FindBooksByName.xml");
assertNoFault(doc);
addNamespace("ss", "http://domain.commons.bookstore.springside.org");
assertValid("//ss:Book/ss:category/ss:descn= \"Java Book\"", doc);
请先阅读:XFire生火指南(上)
1. JSR181
JSR181式通过annotated POJO ,零配置文件的导出Web服务,是BEA倡导的,JavaEE5里的正规方式, XFire作了良好的支持。
但是,XFire关于JSR181方式的文档还不够清晰,请完整阅读本节以避免其中的陷阱。
1.1 参考文章
Spring, Hibernate and XFire
Webservices with Spring, XFire and jsr181
Basic Spring Web services with XFire and JSR 181
XFire JSR181参考文档
1.2 ApplicationContext.xml
因为Web服务配置都写在了annotation,applicationContext.xml文件的内容变得比较固定。需要注意JSR181WebAnnotations与HandlerMapping不能lazy init。
<beans default-autowire="byName">
<!--引入XFire的预配置文件-->
<import resource="classpath:org/codehaus/xfire/spring/xfire.xml"/>
<!-- 获得applicationContext中所有bean的JSR181 annotation -->
<bean id="webAnnotations" class="org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations" lazy-init="false"/>
<!-- 定义handler mapping,将所有JSR181定义的bean导出为web service -->
<bean id="jsr181HandlerMapping" class="org.codehaus.xfire.spring.remoting.Jsr181HandlerMapping" lazy-init="false">
<property name="xfire" ref="xfire"/>
<property name="webAnnotations" ref="webAnnotations"/>
</bean>
</beans>
1.3 Interface+Impl模式
不同于XFire传统模式,窄接口不是必须的,只是考虑到有个接口,配置都在接口上做,对原来的Manager类侵入较少。
如果采用Interface,Interface将担任主要的配置工作。
首先定义@WebService,可定义自己的NameSpace,如果不定义将采用默认的生成算法。
接口中的函数将默认全部导出,不需要再用@WebMethod注释,也可以如下例般进行关于Param,Result的更进一步配置:
@WebService(targetNamespace = "http://www.springside.org.cn")
public interface BookService {
@WebResult(name = "SearchResult")
List<Book> findBooksByCategory(@WebParam(name = "category", header = true)String cateoryId);
}
Manager不是纯粹的POJO,需要带上@WebService注释,指明接口。
@WebService(serviceName = "BookService", endpointInterface = "org.springside.bookstore.components.xfire.server.jsr181.BookService")
public class BookManager implements BookService {
...
}
陷阱一:XFire JSR181参考文档 中在Interface中以@WebService(name="BookService")来定义ServiceName,这个做法看起来也比较合理,但实际上需要在Manager中以@WebService(serviceName ="BookService") 来定义,比较古怪。
1.4 纯POJO模式
参考文档中的例子,需要配置@WebMethod 指定需要导出的函数。
@WebService(name = "EchoService", targetNamespace = "http://www.openuri.org/2004/04/HelloWorld")
public class Jsr181EchoService
{
@WebMethod(operationName = "echoString", action = "urn:EchoString")
@WebResult(name = "echoResult")
public String echo(@WebParam(name = "echoParam", header = true) String input)
{
return input;
}
}
1.5 Client注意事项
陷阱二:和传统模式的client有一点最大的区别,serviceModel需要实际的Manager类而不是接口类来做参数:
Service serviceModel = new AnnotationServiceFactory().create(BookManager.class);
2. Client
XFire的Client并不算强项,一共有三种模式:
2.1 Client开发者拥有Web服务端的class
Client与Server是同一个开发团队也好,Server端团队以jar形式提供开发包也好,反正如果能拿到服务端的接口Class和Entity类及aegis 配置文件的话。
传统POJO模式:
Service serviceModel = new ObjectServiceFactory().create(BookService.class);
BookService service = (BookService) new XFireProxyFactory().create(serviceModel, serviceURL);
service.findBooksByCategory(cateoryId);
JSR181模式,注意这里Server端开发组需要向Client提供BookService的实现类BookManager,而不止于接口,有点危险:
Service serviceModel = new AnnotationServiceFactory().create(BookManager.class);
BookService = (BookService) new XFireProxyFactory().create(serviceModel, serviceURL);
service.findBooksByCategory(cateoryId);
SpringSide 用泛型封装了一个XFireClientFactory,调用代码如下:
BookService service = XFireClientFactory.getClient(serviceURL, BookService.class);
BookService service = XFireClientFactory.getJSR181Client(serviceURL, BookService.class, BookManager.class);
2.2 动态模式
动态模式不需要服务端的class,不过性能和复杂对象映射等估计做得不会太好。
Client client = new Client(new URL("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL"));
Object[] results = client.invoke("ConversionRate", new Object[] {"BRL", "UGX"});
2.3 根据WSDL生成Client Stub
这才是Web Service Client的王道,可以访问任意语言编写的Web Service,将在下一个版本中演示。
可以用XFire的Ant Task来生成,但使用MyEclipse的XFire集成会更加方便。生成的代码必须是JDK5.0的版本。
3. 测试
XFiire很重要的一个特性是提供了无须启动Web容器也能进行单元测试的能力。
原理就是利用XFire的JVM模式,以xfire.local://BookService channel而不是http://localhost/service/BookService来访问服务。
测试的方式分两种:
一种是纯服务器角度,不编写客户端代码,以SOAP XML形式发送请求,返回的也是SOAP XML字串,直接对XML进行测试。
一种是编写2.1 中Client代码来进行测试。
前一种的测试的隔离度较高,而后一种比较简便。
3.1 测试基类
无论那种方式,都使用Xfire的AbstractXFireSpringTest基类,实现createContext()回调函数。
protected ApplicationContext createContext() { return ClassPathXmlApplicationContext(new String[]{"classpath*:applicationContext*.xml"});
}
另外测试基类还要完成一个很重要的工作就是要解决Hibernate的LazyLoad问题,做到OpenSession In Test。因此,SpringSide专门封装了一个XFireTestCase的基类。
3.2 用Client代码直接测试
下文直接用client代码调用findBooksByCategory方法,得到返回值后进行各种Assert判断。
注意和普通client code的两处区别:servericeURL换成local,factory须加入getXFire()作参数。
Service serviceModel = new ObjectServiceFactory().create(BookService.class);
XFireProxyFactory factory = new XFireProxyFactory(getXFire());
BookService service = (BookService) factory.create(serviceModel, "xfire.local://BookService");
List list = service.findBooksByCategory("0");
assertNotNull(list);
...
3.3 纯服务端测试
编写一段SOAP XML,以任意命名保存,下文以"Java"作参数,调用findBooksByName方法。
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<findBooksByName xmlns="http://www.springside.org.cn">
<in1>Java</in1>
</findBooksByName>
</env:Body>
</env:Envelope>
测试代码调用前面的XML,返回XML Document对象,再用基类提供的一些Assert方法检查结果
Document doc = invokeService("BookService","/org/springside/xfire/BookService.FindBooksByName.xml");
assertNoFault(doc);
addNamespace("ss", "http://domain.commons.bookstore.springside.org");
assertValid("//ss:Book/ss:category/ss:descn= \"Java Book\"", doc);
发表评论
-
装饰模式与代理模式的区别(转载)
2013-04-22 11:28 612学习AOP时,教材上面都说使用的是动态代理,可是在印 ... -
《转》用JPDA轻松调试Java代码
2012-12-05 10:09 669在无法访问运行中的实例时,调试一个Java程序可能相当麻烦;当 ... -
《转》Java入门-高手对 CLASSPATH 的详解
2012-12-05 09:54 0Java入门-高手对 CLASSPATH 的详解 来源: 作者 ... -
java并发中Lock和Synchronized的异同
2011-11-27 14:15 7795java中可以使用Lock和Synchronized的可以实现 ... -
《转》再说final变量
2011-11-23 09:36 741再说final变量 分类: 【 ... -
myeclipse7.0注册码算法
2011-09-19 21:25 829package com.edj.sessionbean; ... -
(转)cursor 与refcursor及sys_refcursor的区别
2011-09-14 08:56 0(转)cursor 与refcursor及sys_refcur ... -
BigDecimal不整除的一个异常
2011-09-13 09:37 2864BigDecimal不整除的一个异 ... -
(转)由MyEclipse内存不足谈谈JVM内存
2011-09-06 09:07 703原文出处: http://www.javatang.com/a ... -
Property文件的六种读取发放
2011-08-26 16:41 1106Java读取properties文件 【转】 使用J2SE ... -
Eclipse debug 的五个技巧
2011-08-26 16:38 1352Logical Structure The logical s ... -
tomcat端口被占用
2011-08-25 16:02 796关于tomcat端口占用的问题,怎么在myeclipse中启动 ... -
java中标签跳转
2011-08-23 14:02 1020continue语句 1.continue语句用来结束本次 ... -
java一些书籍
2011-08-23 08:56 800深入理解java虚拟机 第二版 深入理解Java虚拟机:JVM ... -
主从表中从主表保存修改的子表
2011-08-22 18:09 1128我们从数据库中查出主表Class,连带它的子表Set<S ... -
java序列化深度克隆
2011-08-18 09:24 784publicObject copy() throwsI ...
相关推荐
<xfire:service id="calculator" bean="#calculatorService"> <xfire:binding> <xfire:jaxws/> </xfire:binding> <xfire:endpoint address="/calculator"/> </xfire:bean> ``` 5. **启动Web服务**: 配置完成...
里面包括了3个PDF文档<br>1:Xfire-野猪书-开发指南<br>2:xfiretutorial<br>3:xfire-spring<br>为你的工程提供一个更好的远程服务,做好数据交换第一步<br>XFire是当前J2EE领域非常流行的Web Service框架,以其卓越的...
<groupId>org.codehaus.xfire</groupId> <artifactId>xfire-aegis</artifactId> <version>1.2.6</version> </dependency> <dependency> <groupId>org.codehaus.xfire</groupId> <artifactId>xfire-core</...
<groupId>org.codehaus.xfire</groupId> <artifactId>xfire-all</artifactId> <version>1.2.6</version> </dependency> </dependencies> ``` 3. **定义服务接口和服务实现**:创建一个Java接口,声明要公开的...
<param-value>classpath:spring/app.xml,classpath:org/codehaus/xfire/spring/xfire.xml</param-value> </context-param> <!--配置xfire ws--> <servlet> <servlet-name>XFireServlet</servlet-name> ...
这个文件位于源代码的`META-INF/xfire`目录下,用于定义Web服务的元数据: ```xml <beans xmlns="http://xfire.codehaus.org/config/1.0"> <service> <name>helloWorld</name> <namespace>...
<servlet-name>AxisServlet</servlet-name> <servlet-class> org.apache.axis.transport.http.AxisServlet </servlet-class> </servlet> <servlet> <servlet-name>AdminServlet</servlet-name> ...
<servlet-name>xfire</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>xfire</servlet-name> <url-pattern>/...
<groupId>org.codehaus.xfire</groupId> <artifactId>xfire-all</artifactId> <version>1.2.6</version> </dependency> ``` ```xml <xfire> <services> <service name="CalculatorService" serviceClass=...
<servlet-name>xfire</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>xfire</servlet-name> <url-pattern>*....
<param-value>classpath:org/codehaus/xfire/spring/xfire.xml, classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context....
<groupId>org.codehaus.xfire</groupId> <artifactId>xfire-all</artifactId> <version>1.2.6</version> </dependency> <!-- 其他相关依赖 --> </dependencies> ``` **创建 Web 服务** 在 XFire 中,Web 服务...
<artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.x.x</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.x.x....
包括两个项目 服务器项目和客户端项目 测试的时候先发布服务器项目,然后运行客户端main方法测试。 测试内容: /*Aegis支持的类型*/ ...public List<List<UserBean>> getUserListOfList(List<List<UserBean>> a);
<dwType>被定位手机号码的类型</dwType> </info> ``` 3. **返回的XML信息格式**: 服务响应包括定位的电话号码、结果状态码、纬度、经度、高度、半径、模式以及文本描述位置信息。例如: ``` <?xml version="1.0...
<servlet-name>xfire</servlet-name> <servlet-class>org.codehaus.xfire.transport.http.XFireServlet</servlet-class> <init-param> <param-name>xfire.config</param-name> <param-value>/WEB-INF/xfire-...
默认情况下,Aegis会将集合转换为XML的`<array>`或`<list>`元素,每个元素根据其类型转换为相应的XML结构。 在处理集合时,你可能还需要关注一些高级特性,比如集合的分页、过滤或排序。这可能需要通过自定义序列化...
<servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>XFireServlet</servlet-name> <url-pattern>/services/*</url-...