在java中,解析、分装xml是一件非常“麻烦”的事。我们常常需要写大量的代理来解析不同的XML文件,然后将解析结果赋值给相关对象,便于更好的使用;或者将相关对象转换成XML格式进行输出。为了减去这繁琐的操作,笔者通过反射、注解的功能来实现 XML 与 JAVA对象 的相互转换。
同时,可能存在协议的变动,某些xml标签可能不在返回,这里也提供通过注解,快速屏蔽bean中某些属性的解析和分装。大大提高了转换的灵活度,以及便于最小程度的改动现有代码。
XML ——> bean
bean ——>XML
/** * 封装xml * @param c 目标对象Class类 * @param currentObj 被转换对象 * @param flag 是否需要xml头及root标签 * @return 解析后的xml * @throws Exception * @throws NoSuchMethodException */ @SuppressWarnings({ "unchecked","rawtypes" }) public static String packageXml(Class c,Object currentObj,boolean flag) throws Exception { if(currentObj == null) { return ""; } StringBuffer xml = new StringBuffer(); if(flag) { xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); String[] strs = c.getName().split("\\."); xml.append("<").append(strs[strs.length-1].toUpperCase()).append(">"); } Field[] fieldArray = c.getDeclaredFields(); for(Field field : fieldArray) { if(field.isAnnotationPresent(XmlTransformAnnotation.class)) { XmlTransformAnnotation xmlAnnotation = field.getAnnotation(XmlTransformAnnotation.class); if(XmlTransformAnnotation.FLASE.equals(xmlAnnotation.value())) { continue; } } Class basicType = getBasicType(field.getType()); if (basicType != null) { //分装基本类型(包括:String、Integer、Byte、Short、Long、Float、Double、Character、Boolean、int、byte、short、long、float、double、char、boolean) xml.append("<").append(field.getName().toUpperCase()).append(">"); String setMethod = "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1); Method method = c.getDeclaredMethod(setMethod); String value = method.invoke(currentObj) != null ? method.invoke(currentObj).toString() : ""; xml.append(value); xml.append("</").append(field.getName().toUpperCase()).append(">"); } else { if (isCollection(field.getType())) { //分装Collection String getMethod = "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1); Method method = c.getDeclaredMethod(getMethod); Object collectionObj = method.invoke(currentObj); Type returnType = method.getGenericReturnType(); if (returnType instanceof ParameterizedType) { ParameterizedType t = (ParameterizedType) returnType; Type pType = t.getActualTypeArguments()[0]; Class pc = Class.forName(((Class) pType).getName()); Collection collection = (Collection)collectionObj; if(collection != null) { for(Iterator iter = collection.iterator(); iter.hasNext();) { Object subObj = iter.next(); xml.append("<").append(field.getName().toUpperCase()).append(">"); String subXml = packageXml(pc,subObj,false); xml.append(subXml); xml.append("</").append(field.getName().toUpperCase()).append(">"); } } } } else { //分装对象 String[] strs = field.getName().split("\\."); strs = strs[strs.length - 1].split("\\$"); String className = strs[strs.length - 1]; xml.append("<").append(className.toUpperCase()).append(">"); String getMethod = "get" + className.substring(0,1).toUpperCase() + className.substring(1); Method method = c.getDeclaredMethod(getMethod); Object subObj = method.invoke(currentObj); String subXml = packageXml(field.getType(),false); xml.append(subXml); xml.append("</").append(className.toUpperCase()).append(">"); } } } if(flag) { String[] strs = c.getName().split("\\."); xml.append("</").append(strs[strs.length-1].toUpperCase()).append(">"); } return xml.toString(); }
辅助方法
/** * 判断Class的类型是不是基本类型。基本类型包括:String、Integer、Byte、Short、Long、Float、Double、Character、Boolean、int、byte、short、long、float、double、char、boolean * 如果是基本类型则返回对应的Class,否则返回null * @param type * @return */ @SuppressWarnings("rawtypes") private static Class getBasicType(Class type) { if (String.class.equals(type)) { return String.class; } else if (Integer.class.equals(type)) { return Integer.class; } else if (Byte.class.equals(type)) { return Byte.class; } else if (Short.class.equals(type)) { return Short.class; } else if (Long.class.equals(type)) { return Long.class; } else if (Float.class.equals(type)) { return Float.class; } else if (Double.class.equals(type)) { return Double.class; } else if (Character.class.equals(type)) { return Character.class; } else if (Boolean.class.equals(type)) { return Boolean.class; } else if(type.getName().equals(Constant.BASIC_TYPE_BOOLEAN)) { return Boolean.class; } else if(type.getName().equals(Constant.BASIC_TYPE_BYTE)) { return Byte.class; } else if(type.getName().equals(Constant.BASIC_TYPE_CHAR)) { return Character.class; } else if(type.getName().equals(Constant.BASIC_TYPE_DOUBLE)) { return Double.class; } else if(type.getName().equals(Constant.BASIC_TYPE_FLOAT)) { return Float.class; } else if(type.getName().equals(Constant.BASIC_TYPE_INT)) { return Integer.class; } else if(type.getName().equals(Constant.BASIC_TYPE_SHORT)) { return Short.class; } return null; } /** * 判断Class是不是Collection类型,这里之判断了List、Set两种 * @param type * @return * @throws Exception */ @SuppressWarnings("rawtypes") private static boolean isCollection(Class type) throws Exception { //isAssignableFrom(Class<?> cls)判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口。 if(List.class.isAssignableFrom(type)) { return true; } else if(Set.class.isAssignableFrom(type)) { return true; } return false; } /** * 根据class获取Collection * @param type Collection对应的Class * @return * @throws Exception */ @SuppressWarnings("rawtypes") private static Collection getCollectionByClass(Class type) throws Exception { Collection collection = null; if(type.isInterface()) { List list = new ArrayList(); Set set = new HashSet(); //isInstance(Object obj)判定指定的 Object 是否与此 Class 所表示的对象赋值兼容。 if (type.isInstance(list)) { collection = list; } else if(type.isInstance(set)) { collection = set; } }else { collection = (Collection)type.newInstance(); } return collection; }
完整代码链接:https://git.oschina.net/bayern.com/XmlTransformFrame.git