以下所有基本上都是从castor文档上copy过来的,只是在这次项目应用中遇到了这些问题,记录下。
castor虽然用起来很简单,可是用的好却不简单。这里只是提一些使用中的遇到的问题:
1.缩进问题和命名规范。
org.exolab.castor.indent=true
org.exolab.castor.xml.naming=mixed
加上上面的第一个属性就能使产生的xml有缩进,格式比较好看(调试的时候可以用用,正式环境还是去掉比较好)
第二属性设置后,生成的xml的元素名称就可以达到基本符合java的命名规范。
还可以使用<class name="com.acme.Foo" auto-complete="true"/> auto-complete来化繁为简(不用写具体的绑定配置拉)
2.性能问题
castor每次在loadingMapping的时候都会生成ClassDescriptorResolver(大概就是用来将xml的类配置信息映射到对象),如果用castor的quick start里的那种方式可能会有性能问题(其实差的不是很多,经过过我测试,序列化500个对象采用这种方式和后面将要用的新方式只是查了3倍左右。平均时间:10ms<->3ms),以下是缓存ClassDescriptorResolver的解决方案:
private static Log log = LogFactory.getLog(MappingUtils.class);
public static <T> T deserialize(Reader reader, Class<T> clazz) ...{
URL mappingFile = clazz.getResource(clazz.getSimpleName()
+ "-mapping.xml");
try ...{
ClassDescriptorResolver resolver = getCachedResolver(mappingFile);
Unmarshaller unmarshaller = new Unmarshaller();
unmarshaller.setResolver((XMLClassDescriptorResolver)resolver);
return clazz.cast(unmarshaller.unmarshal(reader));
} catch (Exception e) ...{
log.error("", e);
return null;
}
}
public static void serialize(Writer writer, Object obj) ...{
Class clazz = obj.getClass();
serialize(writer, obj, clazz.getResource(clazz.getSimpleName()
+ "-mapping.xml"));
}
public static void serialize(Writer writer, Object obj, URL mappingFile) ...{
Marshaller marshaller = new Marshaller();
try ...{
ClassDescriptorResolver resolver = getCachedResolver(mappingFile);
marshaller.setResolver((XMLClassDescriptorResolver) resolver);
marshaller.setWriter(writer);
marshaller.marshal(obj);
} catch (Exception e) ...{
log.error("", e);
}
}
private static Map<Object, ClassDescriptorResolver> resolverCache = new HashMap<Object, ClassDescriptorResolver>();
private static ClassDescriptorResolver getCachedResolver(URL mappingFile)
throws Exception ...{
ClassDescriptorResolver resolver = resolverCache.get(mappingFile
.getFile());
if (resolver == null) ...{
Mapping mapping = new Mapping();
mapping.loadMapping(mappingFile);
resolver = ClassDescriptorResolverFactory
.createClassDescriptorResolver(BindingType.XML);
MappingUnmarshaller mappingUnmarshaller = new MappingUnmarshaller();
MappingLoader mappingLoader = mappingUnmarshaller.getMappingLoader(
mapping, BindingType.XML);
resolver.setMappingLoader(mappingLoader);
resolverCache.put(mappingFile.getFile(), resolver);
}
return resolver;
}
}
3. 直接序列化List对象
castor支持序列化一个list到xml!其实我也是试出来的,本来以为所有序列化对象都要是xml中的带有map-to顶层元素类。
你只需要定义list中对象的类映射到mapping文件就可以直接序列化一整个list了,大概像下面的这段代码
XMLContext context = new XMLContext();
Mapping mapping = XMLContext.createMapping();
try ...{
mapping.loadMapping(mappingFile);
context.addMapping(mapping);
Marshaller marshaller = context.createMarshaller();
marshaller.setSuppressXSIType(true);//去掉xsi:type
marshaller.setRootElement("root");//给顶层元素改个名字
marshaller.setWriter(writer);
marshaller.marshal(obj);
} catch (Exception e) ...{
log.error("", e);
}
}