一、前言
国庆假期临近,工作动力不强。所以写几篇之前项目中自己用到的一些可能有用的东西分享出来。
今天分享的是Xml与javaBean互转的自定义实现。
先说几种我知道的Xml与javaBean互转的方式:
1、可以利用StringBuilder执行拼接,这样比较费时且复用性低
2、利用JAXB、jackson等一些公开API调用进行转换,这样最方便最简单
3、利用Dom4j实现
这三种一般来说肯定优先选第二种。
但是出于学习的目的。我在之前的项目中自己利用Dom4j完成xml与javaBean的互转。
由于使用场景还不多,代码健壮性目前有待完善。后续使用在更多场景下会一步一步优化完善,如果有朋友有一些优化建议
欢迎在评论区指出。
**二、公共类 ReflectDTO **
这个接口这里主要作用是一个标识作用.
如果需要控制类中某些属性无需转换。可以加一些注解之类的来控制,由于我没有这种需求所以没有实现这功能。
需要转换的对象来实现这个接口,在处理过程中会将实现该接口的类信息转换
import java.io.Serializable; /** * @author hhb * @date :2021/8/20 14:23 */ public interface ReflectDTO extends Serializable { }
三、Xml转JavaBean
3.1、方法入口。首先 利用Dom4j 将String格式的xml转化成Document类型的对象,然后通过递归、反射实现转化
/** * 将Xml格式的字符串转换为java对象 * @param xml * @param cls * @return * @throws DocumentException * @throws IllegalAccessException */ public static <T> T parseXml(String xml,Class<T> cls) throws DocumentException,IllegalAccessException { //xml格式字符串转Dom4j的Document Document document = DocumentHelper.parseText(xml); //递归处理子元素 return (T)handleElement(document.getRootElement(), cls,null,null); }
3.2、递归方法。递归处理Document元素,将element里面的text匹配上对象的属性并赋值
/** * 递归处理元素 * @param root * @param rootClz * @param rootObj * @param rootField * @return * @throws IllegalAccessException */ private static Object handleElement(Element root, Class rootClz, Object rootObj,Field rootField) throws IllegalAccessException { //创建对象公共方法 Object fieldObj = creatObj(rootClz); List<Element> elements = root.elements(); //获取带转换类已声明的属性 Field[] fields = rootClz.getDeclaredFields(); for (Element e:elements){ //细节处理,后续可进一步完善属性可能的类型 handleDetail(fields,e,fieldObj); } if (null!=rootObj&&null!=rootField){ rootField.set(rootObj,fieldObj); } return fieldObj; }
3.3、 基础方法。根据对象的class信息生成新的对象,还有根据Element的名称匹配对象中
对应的相应属性信息。
/** * 根据类信息生成对象 * @param cls * @return */ private static Object creatObj(Class cls){ try { return cls.getConstructor().newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return null; } /** * Documet元素标签匹配对象属性 * @param fields * @param name * @return */ private static Field matchFields(Field[] fields, String name) { for (Field field: fields){ if (field.getName().equals(name)){ return field; } } return null; }
3.4、 处理核心方法。主要是根据对象属性的类型采取对应的处理方式目前已实现的有,
实现了ReflectDTO接口的对象、String、List。后面如果还有其他类型可以
自己按照已有示例进行扩展
/** * 处理核心 * @param fields * @param e * @param fieldObj * @throws IllegalAccessException */ private static void handleDetail(Field[] fields,Element e,Object fieldObj) throws IllegalAccessException { //匹配属性,没匹配上直接返回 Field field=matchFields(fields,e.getName()); if (null==field){ return; } field.setAccessible(true); Class<?> fieldType = field.getType(); //如果是List if (fieldType.equals(List.class)&&field.getGenericType() instanceof ParameterizedType){ List list = handleListDetail(e, field); field.set(fieldObj,list); return; } //获得属性值 Object childFieldValue = creatObj(fieldType); //如果是String if (fieldType.equals(String.class)){ field.set(fieldObj,e.getText()); } //todo 这里还可以扩展,比如BigDecimal、LocalDateTime、Double等等 //需要转换的对象 if (childFieldValue instanceof ReflectDTO){ Object o=handleElement(e,fieldType,fieldObj,field); field.set(fieldObj,o); } }
3.5、处理特殊方法。如果待生成属性是list时的一些处理方法,主要有获取List里面的对象的实际类型方法,
处理List属性时的明细方法。
/** * 列表类型处理明细 * @param listElement * @param field * @return * @throws IllegalAccessException */ private static List handleListDetail(Element listElement,Field field) throws IllegalAccessException { ArrayList objList = new ArrayList<>(); Class<?> classInList = getClassInList(field.getGenericType()); for (Element e: listElement.elements()){ Object objInList = handleElement(e, classInList, null, null); objList.add(objInList); } return objList; } /** * 获得List里面的对象类型 * @param fieldType * @return */ private static Class<?> getClassInList(Type fieldType){ ParameterizedType paramType = (ParameterizedType) fieldType; Type[] genericTypes = paramType.getActualTypeArguments(); if (genericTypes != null && genericTypes.length > 0) { if (genericTypes[0] instanceof Class<?>) { return (Class<?>) genericTypes[0]; } } return null; }
四、 javaBean转Xml的实现
由于该篇篇幅较长,这个实现将放在下一篇进行说明.