`
冰火特蕾莎
  • 浏览: 20446 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

Apache CXF入门范例以及对传递List<Map>类型的疑惑

    博客分类:
  • SOA
阅读更多

在选择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们是怎么做的呢?

分享到:
评论
7 楼 weilikk 2014-05-05  
楼主你好,我正卡在传递List<map>上面。
感谢你的分享,我想请教一下这个的实现是在传递之前,
遍历list把所有的map转换成MapConvertor类型吗?
但是我这里报“无法转换”的错误,
是一个个new MapConvertor吗 ?具体怎么操作呢?
6 楼 darrendu 2010-10-22  
kiki 写道
这样更省事
package cn.com.pansky.dss.common.ws;

import java.util.HashMap;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
/**
 * XML to Map及Map to XML序列化
 * @author shenwujie
 *
 */
public class MapAdapter extends XmlAdapter<String,HashMap> {

	@Override
	public String marshal(HashMap map) throws Exception {
		XStream xs = new XStream(new DomDriver());
		return xs.toXML(map);
	}

	@Override
	public HashMap unmarshal(String xmlData) throws Exception {
		XStream xs = new XStream(new DomDriver());
		return (HashMap) xs.fromXML(xmlData);
	}

}



这种方式要求客户端也要发送一个xml字符串,让为客户端也xStream转码?还是你告诉调用者map类型数据,就转成对应的xml?
5 楼 7454103 2010-09-15  
这娃比较懒! 嘎嘎
4 楼 hepx 2010-07-05  
楼主,用MAP作为数据传递的能数。在客户端是要构建一个MapConvertor将MapEntry作为他的参数。MapEntry只能是一对key,value.要是要多个要用List<MapEntry>。再把这个List<MapEntry>赋给MapConvertorr的entries。楼主是这样的吗。
MapEntry不能像MAP这样添加多组<key,value>。如何能实现这样的功能。
3 楼 yangkai1217 2010-03-02  
如果方法中用了这种map 会提示一下内容,请问该如何解决呢
警告: {http://service.ws.upc.red.com/}findUser requires a wrapper bean but problems with ASM has prevented creating one.  Operation may not work correctly.
2 楼 taiwei.peng 2010-02-02  
博主,你的
@WebMethod 
List<User> getJavaBean();
这个方法是怎么弄的啊?????????????????
1 楼 kiki 2009-12-05  
这样更省事
package cn.com.pansky.dss.common.ws;

import java.util.HashMap;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
/**
 * XML to Map及Map to XML序列化
 * @author shenwujie
 *
 */
public class MapAdapter extends XmlAdapter<String,HashMap> {

	@Override
	public String marshal(HashMap map) throws Exception {
		XStream xs = new XStream(new DomDriver());
		return xs.toXML(map);
	}

	@Override
	public HashMap unmarshal(String xmlData) throws Exception {
		XStream xs = new XStream(new DomDriver());
		return (HashMap) xs.fromXML(xmlData);
	}

}

相关推荐

    spring,cxf,restful发布webservice传递List,Map,List&lt;Map&gt;

    spring,cxf,restful发布webservice传递复杂对象,例如List,Map,List&lt;Map&gt;

    springboot+cxf实现webservice示例

    &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt; &lt;artifactId&gt;cxf-spring-boot-starter-jaxws&lt;/artifactId&gt; &lt;version&gt;3.1.7&lt;/version&gt; &lt;/dependency&gt; &lt;!-- CXF webservice --&gt; &lt;dependency&gt; &lt;groupId&gt;org.spring...

    wsdl2java源码-springboot-apachecxf-client:本项目演示了如何在Springboot中实现apachecxf

    &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt; &lt;artifactId&gt;cxf-codegen-plugin&lt;/artifactId&gt; &lt;version&gt;3.2.0&lt;/version&gt; &lt;executions&gt; &lt;execution&gt; &lt;id&gt;generate-sources&lt;/id&gt; &lt;phase&gt;g

    Apache CXF

    Apache CXF Apache CXF Apache CXF Apache CXF Apache CXF Apache CXF Apache CXF Apache CXF Apache CXF

    基于Apache CXF构建SOA应用

    Apache CXF 框架是一个比较有前途的开源 Web Services 框架,也是构建 SOA 架构应用的利器。本书采用案例源码和解说形式全面介绍 Apache CXF 框架的功能。 本书共 15 章,大致分为三个部分。第一部分介绍关于 SOA 和...

    基于Apache CXF构建SOA应用 随书源代码

    2013版的 &lt;基于Apache CXF构建SOA应用&gt; 源码 Apache CXF是一个开放源码的Web服务框架,提供了一个易于使用,用于开发Web Services标准为基础的编程模型。本书主要介绍Apache CXF在构建SOA架构各个方面的应用说明和...

    apache cxf 用户手册

    apache cxf 2.1.3 的用户手册

    Developing Web Services with Apache CXF and Axis2(3rd Edition).zip

    CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First...

    CXF WebService整合Spring示例工程代码demo

    &lt;servlet-class&gt;org.apache.cxf.transport.servlet.CXFServlet&lt;/servlet-class&gt; &lt;/servlet&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;CXFService&lt;/servlet-name&gt; &lt;url-pattern&gt;/*&lt;/url-pattern&gt; &lt;/servlet-...

    Apache CXF Web service 资料

    详细的从入门到精通, 手把手的教你做WEB SERVICE 该资源借花献佛,是一个高手写的,我在这里借花献佛,推广推广,让大家多一个学习的机会,吃水不忘挖井人,轻大家也谢谢写该文档的高手

    apache-cxf-3.5.0.zip

    Apache CXF 是一个开放源代码框架,提供了用于方便地构建和开发 Web 服务的可靠基础架构。

    apache-cxf-3.1.8.zip

    apache cxf 3.1.8 java web service 开源框架

    apache-cxf-3.0.4

    CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First...

    Apache CXF Web Service Development

    Apache CXF Web Service Development

    WebService with Apache CXF

    Apache CXF = Celtix + XFire,Apache CXF 的前身叫 Apache CeltiXfire,现在已经正式更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且...

    apache-cxf 2.2.8版本下载

    apache-cxf 2.2.8 支持webservice 反正生成服务端代码,附带一个文本文件。希望有需要的小伙伴可以下载来看。

    apache cxf 一个helloworld的例子

    apache cxf 一个helloworld的例子

    两本关于apache cxf的书籍,英文

    Apache CXF Web Service Development Developing+Web+Services+with+Apache+CXF+and+Axis2+(3rd+Edition)

    apache cxf_jar包

    java通过cxf实现webservice所需jar包。java通过cxf实现webservice所需jar包。

Global site tag (gtag.js) - Google Analytics