在选择WebService框架的过程中,偶最终选择了Apache CXF,純粹伿諟銦爲听说它与Spring的无缝整合
想当初用Axis的时候,因为没有太好的办法让Spring能够集成Axis,只好平白无故地多出一个WebService代理类,让偶的感觉很是不爽
偶要在此记载一下CXF的一些入门知识
首珗,倌網哋址諟http://cxf.apache.org/,里面可以找到User's Guide和download地址,偶的版本是目前最新的
apache-cxf-2.2.5
先来做一个最简单的入门级别例子吧,也就是经典的HelloWord
Server端代码
WebService接口HelloService.java
package cfx.server;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService
public interface HelloService {
@WebMethod
String sayHi(@WebParam String name);
}
实现类HelloServiceImpl.java
public class HelloServiceImpl implements HelloService {
public String sayHi(String name) {
System.out.println("HelloServiceImpl.sayHi called");
return "Hello"+name;
}
WebService配置文件:cxf-servlet.xml(可放置于WEB-INF目录下)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:soap="http://cxf.apache.org/bindings/soap"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:server id="jaxwsService" serviceClass="cfx.server.HelloService" address="/hello">
<jaxws:serviceBean>
<bean class="cfx.server.HelloServiceImpl" />
</jaxws:serviceBean>
</jaxws:server>
</beans>
web.xml代码,用于添加CXFServlet这个处理webservice请求的控制器类
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
Client端测试代码
public class CXF {
public static void main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setServiceClass(HelloService.class);
factory.setAddress("http://localhost:8080/cxf/services/hello");
HelloService client = (HelloService) factory.create();
String reply = client.sayHi("特蕾莎");
System.out.println("Server said: " + reply);
}
*****************************************************************************
怎么样,是不是很简单啊!现在再来一个和Spring整合的例子
注意,Server端和Client端都要通过Spring-bean的方式整合
Server端现在有四个文件,假设是
HelloService.java
HelloServiceImpl.java
HelloDao.java
HelloDaoImpl.java
在HelloServiceImpl中存在一个HelloDao的属性,代码省略如下
public class HelloServiceImpl implements HelloService {
private HelloDao dao;
public String sayHi(String name) {
System.out.println("HelloServiceImpl.sayHi called");
return dao.getString(name);
}
}
HelloDaoImpl用于处理持久化,代码省略咯
需要修改的是配置文件,此时可以这样改
首先在web.xml里加入Spring监听器
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
橪銗WEB-INF/cxf-servlet這個忟件可以省略咯
把一个标准的spring-bean文件放在src下(即classes目录下),要让人一看就知道spring大哥进来咯
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<bean id="helloDao" class="cfx.server.HelloDaoImpl" />
<jaxws:server id="jaxwsService" serviceClass="cfx.server.HelloService" address="/hello">
<jaxws:serviceBean>
<bean id="helloService" class="cfx.server.HelloServiceImpl">
<property name="dao" ref="helloDao" />
</bean>
</jaxws:serviceBean>
</jaxws:server>
</beans>
這樣啟動服務器的时候,spring就自动进行bean的注入以及WebService服务的发布了
接下来是客户端代码
銦爲諟普通Java,所以就简单配一下愙戸端的spring文件了
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd">
<bean id="HelloService" class="cfx.server.HelloService" factory-bean="clientFactory" factory-method="create" />
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="cfx.server.HelloService" />
<property name="address" value="http://localhost:8080/cxf/services/hello" />
</bean>
</beans>
CXFClientTest.java
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "cfx/client/client-beans.xml" });
HelloService client = (HelloService) context.getBean("HelloService");
testString(client);
}
static void testString(HelloService client) {
String reply = client.sayHi("特蕾莎");
System.out.println("Server said: " + reply);
}
*************************************************************************
然后是复杂数据类型的问题,经过测试,发觉基本数据类型和List都是没有问题的,我的测试方法包括
@WebMethod
String sayHi(@WebParam String name);
@WebMethod
List<Integer> getList(@WebParam List<String> strs);
@WebMethod
List<User> getJavaBean();
但是传递Map时,就出现问题了,所以参照了user's guide,得到如下解决办法
测试某个方法的参数和返回值都是Map类型
@WebMethod
@XmlJavaTypeAdapter(MapAdapter.class)
Map<String, String> getMap(@WebParam @XmlJavaTypeAdapter(MapAdapter.class) Map<String, String> map);
MapAdapter是我自己写的用於數據類型轉換的适配器类,代码如下
public class MapAdapter extends XmlAdapter<MapConvertor, Map<String, Object>> {
@Override
public MapConvertor marshal(Map<String, Object> map) throws Exception {
MapConvertor convertor = new MapConvertor();
for(Map.Entry<String, Object> entry:map.entrySet()){
MapConvertor.MapEntry e = new MapConvertor.MapEntry(entry);
convertor.addEntry(e);
}
return convertor;
}
@Override
public Map<String, Object> unmarshal(MapConvertor map) throws Exception {
Map<String, Object> result = new HashMap<String,Object>();
for(MapConvertor.MapEntry e :map.getEntries()){
result.put(e.getKey(), e.getValue());
}
return result;
}
}
MapConvertor.java Map格式转换类
@XmlType(name = "MapConvertor")
@XmlAccessorType(XmlAccessType.FIELD)
public class MapConvertor {
private List<MapEntry> entries = new ArrayList<MapEntry>();
public void addEntry(MapEntry entry){
entries.add(entry);
}
public static class MapEntry{
public MapEntry() {
super();
}
public MapEntry(Map.Entry<String,Object> entry) {
super();
this.key = entry.getKey();
this.value = entry.getValue();
}
public MapEntry(String key,Object value) {
super();
this.key = key;
this.value = value;
}
private String key;
private Object value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
public List<MapEntry> getEntries() {
return entries;
}
}
经过这个MapAdapter,算是完成了Map类型的数据传递
接下来,就是更为复杂的一点的这种情况了:List<Map<String,Object>>
这个情况实在不太好办,目前偶也没有找到更好的办法,偶只能这样做
@WebMethod
List<MapConvertor> getListMap(List<MapConvertor> listmap);
就是把MapConvertor当成Map来使,但偶觉得这不是一个很妥善的办法。
其实偶觉得,WebService里应该尽量减少使用javabean对象进行传输
一个JavaBean可以转换成一个Map
一个包含多个JavaBean的List可以转换成一个包含多个Map的List
所以如果对Map支持得好的话,就应该多用Map和List来实现数据传递
当然在调用的时候,也最好能够像Axis一样使用Call来实现无接口调用
这样在Client端就不需要得到Server提供的任何jar了
这样才是最松散耦合的系统
只可惜现在对Map支持得不是很好,最起码在List<Map>时用的方式感觉不太好
不知道各位GGJJ们是怎么做的呢?
分享到:
- 2009-11-28 23:59
- 浏览 8258
- 评论(7)
- 论坛回复 / 浏览 (6 / 15142)
- 查看更多
相关推荐
本文将深入探讨如何使用这些技术来发布Web服务,特别是涉及复杂对象如List、Map及List<Map>的传递。 首先,Spring框架是一个Java企业级应用开发的强大工具,它提供了众多模块,包括Spring MVC用于Web开发。在Spring...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-core</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.1.7</version> </dependency> <!-- CXF webservice --> <dependency> <groupId>org.spring...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.x.x</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>3.0.x</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.4.4</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>3.x.y</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf</artifactId> <version>2.5.2</version> <type>pom</type> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.4.x</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.1.11</version> </dependency> ``` 接下来,我们需要定义一个公共的返回实体类`BaseResult`: ```java...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.x.x</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.3.x</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>版本号</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.4.4</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.x.x</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.3.3</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin</artifactId> <version>3.2.0</version> <executions> <execution> <id>generate-sources</id> <phase>g
<groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.x.x</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-...
在本文中,我们将深入探讨如何使用Apache CXF框架来处理JavaBean式的复合类型以及List集合类型的参数和返回值。CXF是一个开源的、强大的Web服务框架,它支持多种Web服务标准,包括SOAP、RESTful等,并且允许开发者以...
<groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin</artifactId> <version>${cxf.version}</version> <executions> <execution> <id>generate-sources</id> <phase>generate-sources</phase...