关于jibx结合ant的使用。结合网上相关资料整理。
[参考资料](http://www.codeweblog.com/jibx-1-2-6-maven%E9%A1%B9%E7%9B%AE-ant%E7%BC%96%E8%AF%91%E7%9A%84%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/)
[参考资料](http://blog.csdn.net/hills/article/details/46741643)
[参考资料](http://www.cnblogs.com/hoojo/archive/2011/04/27/2030205.html)
1. 准备阶段相关jar
<!-- https://mvnrepository.com/artifact/org.jibx/jibx-bind -->
<dependency>
<groupId>org.jibx</groupId>
<artifactId>jibx-bind</artifactId>
<version>1.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jibx/jibx-tools -->
<dependency>
<groupId>org.jibx</groupId>
<artifactId>jibx-tools</artifactId>
<version>1.2.6</version>
</dependency>
2.开始构建。
step 1 :
创建实体类Address.java
package nettyJiBX.jn;
import java.util.List;
public class Address {
private String street1;
private String street2;
private String city;
private String state;
private String postCode;
private String country;
private List<Order> listOrder;
// private HashMap<String,Order> map;
// private String[] strArr;
get set 方法省略...
}
创建Customer.java
public class Customer {
private long customerNumber;
private String firstName;
get set 方法省略...
}
创建Order.java
package nettyJiBX.jn;
public class Order {
private long OrderNumber;
private Customer customer;
get set 方法略...
}
step 2 生成xml相关信息:
网上的好多文章第二步基本上就通过cmd窗口操作了。但是这里没有用那种方 法,因为可能需要好多依赖jar包如果配置不好,很容易就报错。所以直接在 myeclips中找到这个类执行main方法就好了(外面的cmd窗口执行原理是一样 的)。 第二步应该找到org.jibx.binding.generator.BindGen
这个时候需要先配置启动参数
- t:表示xml和xsd输出路径 - v:运行时打印输出信息 - b: 设置输出的xml的名称 如果需要有多个类需要xml和bean互转可以写多个。 "-t""G:\jibx-out""-v""nettyJiBX.jn.Address""nettyJiBX.jn.Order""nettyJiBX.jn.Customer" 然后执行。 生成的文件如下:
step 3 执行ant:
这一步就需要执行ant了,直接上ant相关配置。
<?xml version="1.0" encoding="utf-8"?>
<project default="main" basedir=".">
<path id="classpath">
<dirset dir="${basedir}/target/classes" />
<dirset dir="${basedir}/target/test-classes" />
<fileset dir="E:/maven/maven-jars/org/jibx/jibx-run/1.2.5/" includes="*.jar" />
<fileset dir="E:/maven/maven-jars/org/jibx/jibx-bind/1.2.5/" includes="*.jar" />
<fileset dir="E:/maven/maven-jars/bcel/bcel/5.1/" includes="*.jar" />
<fileset dir="E:/maven/maven-jars/org/jibx/jibx-extras/1.2.6/" ncludes="*.jar"/>
<fileset dir="E:/maven/maven-jars/xpp3/xpp3_min/1.1.4c/" includes="*.jar"/>
</path>
<target name="main" depends="compile,binggen, bind" description="Main target" />
<target name="compile" description="Compilation target">
<echo>Building file.</echo>
<echo>${basedir}</echo>
<javac srcdir="${basedir}/src/main/java/nettyJiBX/jn" destdir="${basedir}/target/classes/nettyJiBX/jn" includeantruntime="true" />
</target>
<target name="binggen">
<echo message="Running BindGen tool" />
<java classpathref="classpath" fork="true" failonerror="true" classname="org.jibx.binding.BindingGenerator">
<arg value="nettyJiBX.jn.Address" />
<arg value="nettyJiBX.jn.Order" />
<arg value="nettyJiBX.jn.Customer" />
</java>
</target>
<target name="bind">
<echo message="Running bind" />
<taskdef name="bind" classname="org.jibx.binding.ant.CompileTask">
<classpath refid="classpath"/>
</taskdef>
<bind binding="${basedir}/map.xml">
<classpath refid="classpath"/>
</bind>
</target>
</project>
map.xml就是我们通过org.jibx.binding.generator.BindGen生成的。
到此,所有的准备工作都已经完成了。
- step 4 测试:
package nettyJiBX.jn;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import org.jibx.runtime.BindingDirectory;
import org.jibx.runtime.IBindingFactory;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class JnTest {
private IBindingFactory factory = null;
private StringWriter writer = null;
private StringReader reader = null;
private Address bean = null;
@Before
public void init() {
bean = new Address();
bean.setCity("city");
bean.setCountry("country");
bean.setPostCode("postCode");
bean.setState("state");
bean.setStreet1("street1");
bean.setStreet2("street2");
Order order1 = new Order();
Customer cus1 = new Customer();
cus1.setCustomerNumber(500L);
order1.setCustomer(cus1);
order1.setOrderNumber(100L);
Order order2 = new Order();
Customer cus2 = new Customer();
cus2.setCustomerNumber(1000L);
order2.setCustomer(cus2);
order2.setCustomer(null);
order2.setOrderNumber(200L);
List<Order> list = new ArrayList<Order>();
list.add(order2);
list.add(order1);
// bean.setListOrder(list);
try {
factory = BindingDirectory.getFactory(Address.class);
} catch (JiBXException e) {
e.printStackTrace();
}
}
@After
public void destory() {
bean = null;
try {
if (writer != null) {
writer.flush();
writer.close();
}
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void bean2XML() {
try {
writer = new StringWriter();
// marshal 编组
IMarshallingContext mctx = factory.createMarshallingContext();
mctx.setIndent(2);
mctx.marshalDocument(bean, "UTF-8", null, writer);
fail(writer);
reader = new StringReader(writer.toString());
//unmarshal 解组
IUnmarshallingContext uctx = factory.createUnmarshallingContext();
Address acc = (Address) uctx.unmarshalDocument(reader, null);
fail(acc);
} catch (Exception e) {
e.printStackTrace();
}
}
public void fail(Object o) {
System.out.println(o);
}
public void failRed(Object o) {
System.err.println(o);
}
}
简单总结:
jibx实现转换的时候主要涉及到三个类(中的main方法):
- org.jibx.binding.generator.BindGen
- org.jibx.binding.BindingGenerator
org.jibx.binding.Compile
我把自己研究结果的基本流程跟大家分享一下:
- 第一步:
通过指定的实体类生成xml文件,这一步主要是通过
org.jibx.binding.generator.BindGen
org.jibx.binding.BindingGenerator
上面的这两个类来实现的,但是通过尝试发现BindingGenerator这个类生成的会好一点儿。因为如果这个实体中有Map那么BindingGenerator也能生成,但是用BindGen就会报错
Exception in thread "main" java.lang.IllegalStateException:
。
No way to handle type java.util.HashMap, referenced from nettyJiBX.jn.MapBean
at org.jibx.binding.generator.BindGen.expandReferences(BindGen.java:227)
at org.jibx.binding.generator.BindGen.findReferences(BindGen.java:1010)
at org.jibx.binding.generator.BindGen.generate(BindGen.java:1124)
at org.jibx.binding.generator.BindGen.main(BindGen.java:1302) - 第二步:
就是通过第一步生成的xml生成一些类
第二步生成的class主要是通过org.jibx.binding.Compile中的compile方法
我们上面的ant文件中的org.jibx.binding.ant.CompileTask也就是
<target name="bind">
<echo message="Running bind" />
<taskdef name="bind" classname="org.jibx.binding.ant.CompileTask">
<classpath refid="classpath"/>
</taskdef>
<bind binding="${basedir}/map.xml">
<classpath refid="classpath"/>
</bind>
</target>
其实也是调用了org.jibx.binding.Compile中的compile方法
所以其实上面的ant文件中的
<target name="binggen">
<echo message="Running BindGen tool" />
<java classpathref="classpath" fork="true" failonerror="true" classname="org.jibx.binding.BindingGenerator">
<arg value="nettyJiBX.jn.Address" />
<arg value="nettyJiBX.jn.Order" />
<arg value="nettyJiBX.jn.Customer" />
</java>
</target>
可以去掉,因为如果前面已经生成了xml这一步就没什么用了,当然如果可以一起集成到ant中也是极好的,
因为对ant用的较少还不是很6。
还有一个常见的异常:
org.jibx.runtime.JiBXException: Base element type java.lang.Long must be mapped
at org.jibx.binding.BindingGenerator.defineFields(BindingGenerator.java:360)
at org.jibx.binding.BindingGenerator.defineStructure(BindingGenerator.java:624)
at org.jibx.binding.BindingGenerator.createMapping(BindingGenerator.java:739)
at org.jibx.binding.BindingGenerator.generate(BindingGenerator.java:891)
at org.jibx.binding.BindingGenerator.main(BindingGenerator.java:1092)
这种异常可以在调用main方法中增加参数“java.lang.Long”就可以了,以此类推(java.lang.String);(PS:感觉这种解决方法不是很好,等待更好的方法)。
还有一个解决实体中Map转换的问题。
只需要加一个类。
package nettyJiBX.jn;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.jibx.runtime.IAliasable;
import org.jibx.runtime.IMarshallable;
import org.jibx.runtime.IMarshaller;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.IUnmarshaller;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.impl.MarshallingContext;
import org.jibx.runtime.impl.UnmarshallingContext;
public class HashMapper implements IMarshaller, IUnmarshaller, IAliasable{
private static final String SIZE_ATTRIBUTE_NAME = "size";
private static final String ENTRY_ELEMENT_NAME = "entry";
private static final String KEY_ATTRIBUTE_NAME = "key";
private static final int DEFAULT_SIZE = 10;
private String m_uri;
private int m_index;
private String m_name;
public HashMapper() {
m_uri = null;
m_index = 0;
m_name = "hashmap";
}
public HashMapper(String uri, int index, String name) {
m_uri = uri;
m_index = index;
m_name = name;
}
/* (non-Javadoc)
* @see org.jibx.runtime.IMarshaller#isExtension(int)
*/
// public boolean isExtension(int index) {
// return false;
// }
//
/* (non-Javadoc)
* @see org.jibx.runtime.IMarshaller#marshal(java.lang.Object,
* org.jibx.runtime.IMarshallingContext)
*/
@Override
public void marshal(Object obj, IMarshallingContext ictx)
throws JiBXException {
// make sure the parameters are as expected
if (!(obj instanceof HashMap)) {
throw new JiBXException("Invalid object type for marshaller");
} else if (!(ictx instanceof MarshallingContext)) {
throw new JiBXException("Invalid object type for marshaller");
} else {
// start by generating start tag for container
MarshallingContext ctx = (MarshallingContext)ictx;
HashMap map = (HashMap)obj;
ctx.startTagAttributes(m_index, m_name).
attribute(m_index, SIZE_ATTRIBUTE_NAME, map.size()).
closeStartContent();
// loop through all entries in hashmap
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
ctx.startTagAttributes(m_index, ENTRY_ELEMENT_NAME);
if (entry.getKey() != null) {
ctx.attribute(m_index, KEY_ATTRIBUTE_NAME,
entry.getKey().toString());
}
ctx.closeStartContent();
if (entry.getValue() instanceof IMarshallable) {
((IMarshallable)entry.getValue()).marshal(ctx);
ctx.endTag(m_index, ENTRY_ELEMENT_NAME);
} else {
throw new JiBXException("Mapped value is not marshallable");
}
}
// finish with end tag for container element
ctx.endTag(m_index, m_name);
}
}
/* (non-Javadoc)
* @see org.jibx.runtime.IUnmarshaller#isPresent(org.jibx.runtime.IUnmarshallingContext)
*/
@Override
public boolean isPresent(IUnmarshallingContext ctx) throws JiBXException {
return ctx.isAt(m_uri, m_name);
}
/* (non-Javadoc)
* @see org.jibx.runtime.IUnmarshaller#unmarshal(java.lang.Object,
* org.jibx.runtime.IUnmarshallingContext)
*/
@Override
public Object unmarshal(Object obj, IUnmarshallingContext ictx)
throws JiBXException {
// make sure we're at the appropriate start tag
UnmarshallingContext ctx = (UnmarshallingContext)ictx;
if (!ctx.isAt(m_uri, m_name)) {
ctx.throwStartTagNameError(m_uri, m_name);
}
// create new hashmap if needed
int size = ctx.attributeInt(m_uri, SIZE_ATTRIBUTE_NAME, DEFAULT_SIZE);
HashMap map = (HashMap)obj;
if (map == null) {
map = new HashMap(size);
}
// process all entries present in document
ctx.parsePastStartTag(m_uri, m_name);
while (ctx.isAt(m_uri, ENTRY_ELEMENT_NAME)) {
Object key = ctx.attributeText(m_uri, KEY_ATTRIBUTE_NAME, null);
ctx.parsePastStartTag(m_uri, ENTRY_ELEMENT_NAME);
Object value = ctx.unmarshalElement();
map.put(key, value);
ctx.parsePastEndTag(m_uri, ENTRY_ELEMENT_NAME);
}
ctx.parsePastEndTag(m_uri, m_name);
return map;
}
@Override
public boolean isExtension(String arg0) {
return false;
}
}
再改一下第一步生成的xml文件就好了。
至此,常用数据的xml转换就都能进行了。
一些执行类的参数留着以后自己看:
各位同仁发现什么问题,可以评论中告诉我,共同学习.