注解xmlPath实现bean的映射
⼀、背景
xml⽂档节点⽐较多,结构层次复杂,⽽⽆需根据xml结构映射实体和取所有的节点内容(⼀两百个节点,只需取⼆⼗多个节点信息)。
⼆、实现思路
把xmlpath通⽤注释映射对应的字段。通过反射读取xmlPath,根据xmlPath读取xml⽂档对应节点内容后反射设值。
三、代码实现
1、缓存字段与xmlpath映射
import flect.Field;
import java.util.HashMap;
import java.util.Map;
import urrent.ConcurrentHashMap;
import urrent.ConcurrentMap;
/**
* 缓存解析过的xmlField
*
*/
public class XmlFieldBeanFactory {
private final static ConcurrentMap<Class<?>, Map<Field,XmlField>> xmlTypeMap = new ConcurrentHashMap<Class<?>,Map<Field,XmlField>>();
public static Map<Field,XmlField> getForClass(Class<?> type){
Map<Field,XmlField> xmlType = (type);
if(xmlType == null) {
xmlType = getXmlType(type);
xmlTypeMap.put(type, xmlType);
}
return xmlType;
}
private static Map<Field,XmlField> getXmlType(Class<?> type){
Map<Field,XmlField> xmlType = new HashMap<>();
while (type != null) {//当⽗类为null的时候说明到达了最上层的⽗类(Object类).
for (Field field : type .getDeclaredFields()) {
if(field.isAnnotationPresent(XmlField.class)){//判断成员变量是否有注解
xmlType.put(field, Annotation(XmlField.class));
}
}
type = Superclass(); //得到⽗类,然后赋给⾃⼰
}
return xmlType;
}
}
2、根据xmlPath获取body值或属性值
import java.io.InputStream;
import flect.Field;
import flect.ParameterizedType;
import flect.ParameterizedType;
import flect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apachemons.beanutils.BeanUtils;
import llections.CollectionUtils;
import org.apachemons.io.IOUtils;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
/**
* xml path 映射
*
*/
public class XmlPathUtil {
/**
* xml字符串转换Object
* @param xml
* @param clz 转换对象class
* @return
* @throws Exception
*/
public static <T> T convert(String xml,Class<T> clz) throws Exception{
InputStream in = null;
try {
in = InputStream(xml);
return convert(in,clz);
}finally {
IOUtils.closeQuietly(in);
}
}
/
**
* xml字符串转换Object
* @param xml xml字符串
* @param clz 转换对象class
* @param ns 命名空间
* @param alisa 别名
* @return
* @throws Exception
*/
public static <T> T convert(String xml,Class<T> clz,String ns,String alisa) throws Exception{ InputStream in = null;
try {
in = InputStream(xml);
return convert(in,clz,ns,alisa);
}finally {
IOUtils.closeQuietly(in);
}
}
/**
* inputStream xml转Object
* @param in
* @param clz
* @return
* @throws Exception
*/
public static <T> T convert(InputStream in,Class<T> clz) throws Exception {
public static <T> T convert(InputStream in,Class<T> clz) throws Exception {
Document doc = new SAXReader().read(in);
return convert(doc,clz);
}
/**
* inputStream xml转Object
* @param in
* @param clz
* @param ns 命名空间
* @param alisa 别名
* @return
* @throws Exception
*/
public static <T> T convert(InputStream in,Class<T> clz,String ns,String alisa) throws Exception {
SAXReader saxReader = new SAXReader();
Document doc = ad(in);
Map<String,String> map = new HashMap<>();
map.put(alisa,ns);
dom4j读取xml
return convert(doc,clz);
}
/**
* document 转 Object
* @param doc
* @param clz
* @return
* @throws Exception
*/
public static <T> T convert(Document doc,Class<T> clz) throws Exception {
T t = wInstance();
getValue(doc, t, clz,"");
return t;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private static void getValue(Document doc,Object obj,Class clz,String parentPath) throws Exception{ Map<Field,XmlField> xmlType = ForClass(clz);
for(Field field : xmlType.keySet()) {
XmlField xmlField = (field);
Object value = Type().newInstance();
BeanUtils.setProperty(obj, Name(), value);
if(!xmlField.haveSon()) {
if(Type())) {
Collection cl = (Collection) value;
List<Node> nodes = doc.selectNodes(parentPath+xmlField.path());
if(CollectionUtils.isNotEmpty(nodes)) {
for (Node node : nodes) {
cl.Text());
}
}
}else {
if(xmlField.isText()) {
Node node = doc.selectSingleNode(parentPath+xmlField.path());
if(node!=null) {
BeanUtils.setProperty(Name() , Text());
}
}else {
BeanUtils.setProperty(Name() , doc.valueOf(parentPath+xmlField.path()));
BeanUtils.setProperty(Name() , doc.valueOf(parentPath+xmlField.path()));
}
}
}else {
if(Type())){
Collection cl = (Collection) value;
List<Node> nodes = doc.selectNodes(parentPath+xmlField.path());
if(CollectionUtils.isNotEmpty(nodes)) {
for (Node node : nodes) {
Type genericType = GenericType();
if(genericType == null)
return; // 如果是泛型参数的类型
if(genericType instanceof ParameterizedType){
ParameterizedType pt = (ParameterizedType) genericType;//得到泛型⾥的class类型对象 Class<?> accountPrincipalApproveClazz = (Class<?>)pt.getActualTypeArguments()[0]; Object v = wInstance();
cl.add(v);
Document(), v,UniquePath()); }
}
}
}else {
Node node = doc.selectSingleNode(xmlField.path());
if(node != null) {
Object v = Type().newInstance();
getValue(doc, Type(),UniquePath());
}
}
}
}
}
private static boolean isCollection(Class<?> type) {
return Collection.class.isAssignableFrom(type);
}
}
3、xmlField注解
import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* ⽤于注解字段对应的xpath,进⾏解析xml
*
*/
@Retention(RUNTIME)
@Target(FIELD)
public @interface XmlField {
/**
* xml对应的xPath路径
* @return
*/
String path();
/**
* 是否嵌套对象
* @return
*/
boolean haveSon() default false;
/**
* 取属性值
* @return
*/
boolean isText() default true;
}
4、Test
实体类
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论