`
shenyuc629
  • 浏览: 194086 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

cxf使用JAXB数据绑定以及cxf对Map的支持

    博客分类:
  • CXF
阅读更多

由于篇幅有限,此处生出源代码,如有需要的在评论里面留下联系的方式,笔者到时联系你。转载请标明读者链接,谢谢。

        一.JAXB简介

JAXB CXF 一个默认的数据绑定,如果你不指定其他数据绑定在你的 Spring 配置中或者在 API ,你可以得到 JAXB 的数据绑定。自从 2.3.x 版本以后默认的使用 JAXB2.2 maven 使用者运行在 jdk6 之上将需要使用 java 认证的重写机制来使用 JAXB2.2 来替代 JAXB2.1

JAXB 使用 java 注解结合文件路径在 XML Java 之间构建映射。 JAXB 支持编码优先和架构优先编程。架构优先支持创建客户代理、动态、运行时。详解见 CXF DynamicClientFactory 类。

CXF 使用 JAXB 引用实现。为了学习更多关于注解类或者怎样把一个 schema 生成实体类,详见官网。

二. 解组和编组

解组: unmarshalling )把数据从存储媒介上转化到内存中的过程,正好与编组相反。因此需要把 xml 文档解组到 Java VM 中。这里的复杂性不是在扁平数据中,因为这不是必需的,而在于从正确的数据到正确 Java 代码变量的映射。如果映射是错误的,就不可能正确的访问数据。当然,如果再尝试重新编组还会造成更大的问题,并且问题传播的很快。

       编组:<!-- [if gte mso 9]><xml> <o:OfficeDocumentSettings> <o:AllowPNG/> </o:OfficeDocumentSettings> </xml><![endif]--> marshalling )是把内存中的数据转化到存储媒介上的过程。因此在 java XML 环境中,编组就是把一些 Java 对象转换成一个或多个 XML 文档。在数据库环境中,则是把 Java 表示的数据存入数据库。显然,编组的秘密在于把 Java 实例中的面向对象结构转化成适用于 XML 的扁平结构,或者 RDBMS 中的关系结构。

       三.代码以及分析

首先需要加入cxf所需要的包,在本次测试中,笔者添加了cxf的lib中全部的包。

下面直接上代码:

package com.syc.jaxb;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;


@XmlJavaTypeAdapter(UserAdapter.class)
public interface User {
	String getName();
	
}

此处注释的XmlJavaTypeAdapter是对自定义编组使用实现XmlAdapter的适配器,即UserAdapter这个类,该类实现了XmlAdapter适配器,因此要实现解组和编组两个方法。可能有的初学读者会提到:为什么我们要实现编组和解组呢?原因很简单,CXF不能直接支持List、Map等。

package com.syc.jaxb;

import javax.xml.bind.annotation.XmlType;

@XmlType(name="User")
public class UserImpl implements User{
	String name;
	public UserImpl(){}
	public UserImpl(String n){
		this.name =n;
	}
	@Override
	public String getName() {
		return name;
	}
	public void setName(String n){
		this.name = n ;
	}
}

  该类是实现了User接口,并且重写getName()方法,此类可以看成一个User实体类,其实也没有什么区别。这里注释的XmlType是将UserImpl映射到 XML 模式类型,即我们得到的客户端的时候显示的类的名字是User。

package com.syc.jaxb;

import java.util.Map;

import javax.jws.WebService;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@WebService
public interface HelloWorld {
	String sayHi(String text);
	String sayHiToUser(User user);
	@XmlJavaTypeAdapter(UserMapAdapter.class)
	Map<Integer,User> getUsers();
}

  该接口是暴露的服务,该服务有三个方法,暴露的服务必须使用@WebService注释,不然在发布服务的时候找不到不要发布的服务类。由于第三个方法返回的是一个Map类型, JAXB 不能将一些 Java 类型自然映射到 XML 表示形式,例如 ,HashMap 或者其他非 JavaBean 类。如参数类型为接口,以及 Map ,这需要特殊的 XmlAdapter 类进行处理。因此这里我们需要注释成让XmlAdapter适配器来处理。

package com.syc.jaxb;

import java.util.LinkedHashMap;
import java.util.Map;

import javax.jws.WebService;
@WebService(endpointInterface="com.syc.jaxb.HelloWorld",
				serviceName="HelloWorld")
public class HelloWorldImpl implements HelloWorld {
	Map<Integer,User> users = new LinkedHashMap<Integer, User>();
	
	@Override
	public String sayHi(String text) {
		System.out.println("sayHello called...");
		return "Hello " +text;
	}

	@Override
	public String sayHiToUser(User user) {
		System.out.println("sayUserHello called...");
		users.put(users.size()+1, user);
		return "Hello"+ user.getName();
	}

	@Override
	public Map<Integer, User> getUsers() {
		System.out.println("getMapUsers called...");
		
		return users;
	}

}

  该类是服务类的一个实现。

package com.syc.jaxb;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class UserAdapter extends XmlAdapter<UserImpl, User>{

	@Override
	public User unmarshal(UserImpl v) throws Exception {
		
		return v;
	}

	@Override
	public UserImpl marshal(User v) throws Exception {
		if(v instanceof UserImpl){
			return (UserImpl)v;
		}
		return new UserImpl(v.getName());
	}

}

  在这里,UserImpl是value类型,User是alue类型。UserAdapter类继承了XmlAdapter类,因此需要重写marshal()和unmarshal()方法,即编组和解组,在此处,编组就是将bound类型修改为value类型,然后将value类型编组为xml表示形式;解组就是JAXB绑定框架首先将XML表示形式解组为value类型,然后将value类型修改为bound类型。在这里我们可以这么理解,编组即bound->value->xml形式,解组即xml形式->value->bound。

package com.syc.jaxb;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlType(name="UserMap")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserMap {
	@XmlElement(nillable=false,name="entry")
	List<UserEntry> entries = new ArrayList<UserEntry>();
	public List<UserEntry> getEntries() {
		return entries;
	}
	public void addEntry(UserEntry entry){
		entries.add(entry);
		
	}
	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlType(name="UserEntry")
	static class UserEntry{
		public UserEntry(){
			super();
		}
		
		public UserEntry(Map.Entry<Integer, User> entry){
			super();
			this.id = entry.getKey();
			this.user = entry.getValue();
		}
		public UserEntry(Integer id,User user){
			super();
			this.id = id;
			this.user = user;
		}
		@XmlElement(required=true,nillable=false)
		Integer id;
		User user;
		public Integer getId() {
			return id;
		}
		public void setId(Integer id) {
			this.id = id;
		}
		public User getUser() {
			return user;
		}
		public void setUser(User user) {
			this.user = user;
		}
		
	}
}

  UserMap类是让cxf支持MAP的关键,该类可以将map里面的key-value转换为User实体类,把key当作user的id值,把value当作user的name值,然后再把user保存到一个集合中,即实现了hash值到实体类的转换。

package com.syc.jaxb;

import java.util.LinkedHashMap;
import java.util.Map;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class UserMapAdapter extends XmlAdapter<UserMap, Map<Integer,User>>{

	@Override
	public Map<Integer, User> unmarshal(UserMap v) throws Exception {
		Map<Integer, User> map = new LinkedHashMap<Integer, User>();
		for(UserMap.UserEntry e : v.getEntries()){
			map.put(e.getId(), e.getUser());
		}
		return map;
	}

	@Override
	public UserMap marshal(Map<Integer, User> v) throws Exception {
		UserMap map = new UserMap();
		for(Map.Entry<Integer, User> e : v.entrySet()){
			UserMap.UserEntry u = new UserMap.UserEntry();
			u.setId(e.getKey());
			u.setUser(e.getValue());
			map.getEntries().add(u);
		}
		return map;
	}

}

  这里即对UserMap和Map对象的编组和解组。

package com.syc.jaxb;

import javax.xml.ws.Endpoint;

public class Server {
	public static void main(String[] args) {
		System.out.println("Starting Server... ");
		String address = "http://localhost:8899/hello";
		HelloWorldImpl implementor = new HelloWorldImpl();
		Endpoint.publish(address, implementor);
		try {
			Thread.sleep(5*60*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("Exiting Server... ");
		System.exit(0);
	}
}

用WSDL2JAVA生成的客户端,调用服务端代码
 package com.syc.jaxb.client;


import java.util.List;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

public class HelloClient {
	public static void main(String[] args) {
		JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean();
		factoryBean.setAddress("http://localhost:8899/hello");
		factoryBean.setServiceClass(HelloWorld.class);
		HelloWorld h = (HelloWorld) factoryBean.create();
		System.out.println(h.sayHi("shenyc"));
		User u = new User();
		u.setName("syc");
		System.out.println(h.sayHiToUser(u));
		User u1 = new User();
		u1.setName("ssss");
		System.out.println(h.sayHiToUser(u1));
		User u2 = new User();
		u2.setName("aaaaa");
		System.out.println(h.sayHiToUser(u2));
		UserMap users = h.getUsers();
		List<UserEntry> list = users.getEntry();
		for(UserEntry ue : list){
			System.out.println(ue.getId()+":"+ue.getUser().getName());
		}
	}
}
  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics