通过反射实现
过程并无甚复杂,通过反射实现接口。首先当然是遍历一下这些集合,无论 Map 还是 Bean。
/** * Bean 转换为 Map * @param obj * @return */ public static Map<String, Object> bean2map(Object obj) { if (obj == null) return null; Map<String, Object> map = new HashMap<>(); for (Method method : obj.getClass().getMethods()) { String methodName = method.getName(); if (methodName.startsWith("get")) { Object value = executeMethod(obj, method); // 反射获取值 if (value != null) map.put(getFieldName(methodName, "get"), value); } } return map; } /** * 调用方法,方法没有参数的 * * @param instance * 对象实例,bean * @param method * 方法对象 * @return 执行结果 */ public static Object executeMethod(Object instance, Method method) { try { return method.invoke(instance); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { return null; } } /** * 根据方法名称来截取属性名称 * @param methodName * 方法名称 * @param action * set|get * @return */ public static String getFieldName(String methodName, String action) { methodName = methodName.replace(action, ""); return Character.toString(methodName.charAt(0)).toLowerCase() + methodName.substring(1); }
对应地,就有 Map 转换为 Bean。
/** * Map 转换为 Bean * * @param map * @param obj */ public static void map2bean(Map<String, Object> map, Object obj) { if (obj != null || map != null) return null; for (Method method : obj.getClass().getMethods()) { String methodName = method.getName(); if (methodName.startsWith("set")) { methodName = getFieldName(methodName, "set"); if (map.containsKey(methodName)) executeMethod(obj, method, map.get(methodName)); } } } /** * 调用方法 * * @param instance * 对象实例,bean * @param method * 方法对象 * @param args * 参数列表 * @return 执行结果 */ public static Object executeMethod(Object instance, Method method, Object... args) { try { return method.invoke(instance, args); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { return null; } }
将 map 中数据填入到 obj 中。obj 是 POJO。 如果 POJO 有这个 setter,那就根据 setter 中 setXxx 获取 xxx,作为 map 的 key 读取 map 的那個 value。
Object 2 Bean Value
bean2map 过程中,值放到 map 中没类型转换的问题,因为 map 的范型是 <String, Object>,这时 map 好比 O 型血,什么都是用它,但反之 map2bean 则不然 bean 的 setter方法是有类型要求的,因此你传入 Object 的参数并不一定能匹配。如果不转换很容易会出现 java.lang.IllegalArgumentException: argument type mismatch 的异常。于是我们类构建更复杂的 map2bean 函数,让类型差不多的也能通过转换,转变为真正符合类型要求的类型。
import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import com.ajaxjs.util.DateTools; import com.ajaxjs.util.LogHelper; import com.ajaxjs.util.reflect.BeanUtil; import com.ajaxjs.util.reflect.Reflect; import com.ajaxjs.util.reflect.ReflectNewInstance; /** * 将 map 数据通过反射保存到 pojo(bean) 中。 * * @author frank * * @param <T> * 实体类型 */ public class Map2Pojo<T> extends BeanUtil { private static final LogHelper LOGGER = LogHelper.getLog(Map2Pojo.class); /** * 实体类型类对象 */ private Class<T> pojoClz; /** * 用于数组的分隔符 */ private char diver = ','; /** * * @param pojoClz * 实体类型类对象 */ public Map2Pojo(Class<T> pojoClz) { this.pojoClz = pojoClz; } /** * 把单个原始数据 map 转换为单个实体 * * @param map * 原始数据 * @param pojo * 实体 * @param fields * 反射出来的字段信息 */ private T map2pojo(Map<String, Object> map, List<Field> fields) { T pojo = ReflectNewInstance.newInstance(pojoClz); if(pojo == null) return null; for (Field f : fields) { String key = f.getName(); // 字段名称 Class<?> t = f.getType(); // 字段期望的类型 Object value = map.get(key); if (value != null) { // System.out.println(key + ":" + map.get(key).getClass().getName()); String methodName = "set" + firstLetterUpper(key); if (t == boolean.class) { // System.out.println("methodName:::::" + methodName); // 布尔型 methodName = key.replace("is", ""); methodName = "set" + firstLetterUpper(methodName); // System.out.println("methodName:::::" + "set" + Reflect.firstLetterUpper(methodName)); if(value instanceof String) { value = (String)value; if(value.equals("yes") || value.equals("true") || value.equals("1")) { value = true; } if(value.equals("no") || value.equals("false") || value.equals("0")) { value = false; } } executeMethod(pojo, methodName, t, (boolean) value); } else if (t == int.class || t == Integer.class) { if(value.getClass() == String.class) value = Integer.parseInt(value.toString()); // 整形 executeMethod(pojo, methodName, t, value); } else if (t == int[].class || t == Integer[].class) { // 复数 if (value instanceof String) { int[] intArr = strArr2intArr(value); executeMethod(pojo, methodName, t, intArr); } else { LOGGER.info("what's this!!? " + value); } } else if (t == String.class) { // 字符型 Reflect.executeMethod(pojo, methodName, t, value.toString()); } else if (t == String[].class) { // 复数 if (value instanceof String[]) { Reflect.executeMethod(pojo, methodName, t, value); } else if (value instanceof ArrayList) { @SuppressWarnings("unchecked") ArrayList<String> list = (ArrayList<String>) value; String[] arr = new String[list.size()]; executeMethod(pojo, methodName, t, list.toArray(arr)); } else if (value instanceof String) { String str = (String) value; executeMethod(pojo, methodName, t, str.split(getDiver() + "")); } else { LOGGER.info("what's this!!?" + value.getClass().getName()); } } else if (t == long.class || t == Long.class) { // LONG 型 executeMethod(pojo, methodName, t, Long.valueOf(value.toString())); } else if (t == Date.class) { if (value instanceof java.sql.Timestamp) { long time = ((java.sql.Timestamp) value).getTime(); executeMethod(pojo, methodName, t, new Date(time)); } else { executeMethod(pojo, methodName, t, DateTools.Objet2Date(value)); } } else { // System.out.println("------------" + t.getName()); executeMethod(pojo, methodName, value); } } } return pojo; } /** * '["1", "2", ...]' --> [1, 2, ...] * @param value * @return */ private int[] strArr2intArr(Object value) { String str = (String) value; // 当它们每一个都是数字的字符串形式 String[] strArr = str.split(getDiver() + ""); int[] intArr = new int[strArr.length]; for (int i = 0; i < strArr.length; i++) intArr[i] = Integer.parseInt(strArr[i]); return intArr; } /** * 把原始数据 map 转换为实体 * * @param maps * 原始数据 * @param fields * 反射出来的字段信息 * @return 转换后的实体列表 */ // public List<T> map2pojo(List<Map<String, Object>> maps, List<Field> fields) { // List<T> list = new ArrayList<>(); //// T[] a = (T[])java.lang.reflect.Array.newInstance(pojoClz, maps.size()); //// list.toArray(T[]); // // for (Map<String, Object> map : maps) // list.add(map2pojo(map, fields)); // // return list; // } /** * 把原始数据 maps 转换为实体 * * @param maps * 原始数据 * @return 转换后的实体列表 */ public List<T> map2pojo(List<Map<String, Object>> maps) { List<Field> fields = getDeclaredField(pojoClz); List<T> list = new ArrayList<>(); // T[] a = (T[])java.lang.reflect.Array.newInstance(pojoClz, maps.size()); // list.toArray(T[]); for (Map<String, Object> map : maps) list.add(map2pojo(map, fields)); return list; // return map2pojo(maps, Reflect.getDeclaredField(pojoClz)); } /** * 把原始数据 map 转换为实体 * * @param map * 原始数据 * @return 转换后的实体 */ public T map2pojo(Map<String, Object> map) { return map2pojo(map, getDeclaredField(pojoClz)); } /** * @return {@link #diver} */ public char getDiver() { return diver; } /** * @param diver {@link #diver} */ public void setDiver(char diver) { this.diver = diver; } }
通过 Bean 内省实现
后来发现反射性能不是很好,于是我们试试 Java Bean 的内省功能也可以转换。
/** * map 转实体 * * @param map * @param clz * 实体类 * @return 实体 bean 对象 */ public static <T> T map2Bean(Map<String, Object> map, Class<T> clz) { T bean = ReflectNewInstance.newInstance(clz); try { BeanInfo beanInfo = Introspector.getBeanInfo(clz); for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) { String key = property.getName(); if (map.containsKey(key)) { Object value = map.get(key); // 得到property对应的setter方法 Method setter = property.getWriteMethod(); setter.invoke(bean, value); } } } catch (IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } return bean; } /** * Bean 转为 Map * * @param bean * 实体 bean 对象 * @return */ public static <T> Map<String, Object> bean2Map(T bean) { Map<String, Object> map = new HashMap<String, Object>(); try { BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) { String key = property.getName(); // 过滤 class 属性 if (!key.equals("class")) { // 得到 property 对应的 getter 方法 Method getter = property.getReadMethod(); Object value = getter.invoke(bean); map.put(key, value); } } } catch (IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } return map; }
时间: 2024-10-27 04:24:28