最近有一个需求分下来里边涉及到多个地方的Map和JavaBean的互转,要用的地方很少的话我就会原地利用get set进行处理了,但是这次由于涉及的地方多就想着抽个工具类,然后就想起了java的内省,其实原理就是利用反射获取到javaBean的成员属性然后进行相应的操作,活不多说上代码。
/**
* @Description: 内省进行数据转换
* @Author: LiuBing
* @Date: 17:31 2018/8/29
*/
public class DataConvertUtil {
/**
* javaBean转map
* @param obj
* @return
* @throws Exception
*/
public static Map<String,Object> javaBeanToMap(Object obj) throws Exception{
Map<String, Object> map =new HashMap<>();
// 获取javaBean的BeanInfo对象
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass(),Object.class);
// 获取属性描述器
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
// 获取属性名
String key = propertyDescriptor.getName();
// 获取该属性的值
Method readMethod = propertyDescriptor.getReadMethod();
// 通过反射来调用javaBean定义的getName()方法
Object value = readMethod.invoke(obj);
map.put(key, value);
}
return map;
}
里边涉及到几个重要的Api,BeanInfo,PropertyDescriptor等等,代码里边注释也很明确。
/**
* map转javaBean
* @param map
* @param clazz
* @param <T>
* @return
* @throws Exception
*/
public static <T>T mapToJavaBean(Map<String,Object> map , Class<T> clazz) throws Exception{
// new 出一个对象
T obj = clazz.newInstance();
// 获取javaBean的BeanInfo对象
BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class);
// 获取属性描述器
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
// 获取属性名
String key = propertyDescriptor.getName();
Object value = map.get(key);
Method writeMethod = propertyDescriptor.getWriteMethod();
if (map.containsKey(key)){
// 解决 argument type mismatch 的问题,转换成对应的javaBean属性类型
String typeName = propertyDescriptor.getPropertyType().getTypeName();
// System.out.println(key +"<==>"+ typeName);
if ("java.lang.Integer".equals(typeName)){
value = Integer.parseInt(value.toString());
}
if ("java.lang.Long".equals(typeName)){
value = Long.parseLong(value.toString());
}
if ("java.util.Date".equals(typeName)){
value = new SimpleDateFormat("yyyy-MM-dd").parse(value.toString());
}
}
// 通过反射来调用javaBean定义的setName()方法
writeMethod.invoke(obj,value);
}
return obj;
}
这里我在测试的时候遇到一个问题,也就是注释中argument type mismatch的问题,为什么呢,因为前段给我传过来的数据都是以表单形式进来的,到服务端就都是字符串的类型了,所以这块做了统一处理:根据javaBean常用的数据类型做了对应匹配,为的是将字符串转换为对应的javaBean属性类型,这里小小的优化可以将多个if判断换成switch case会好一点,对于时间Date类型的属性的格式也可以做成灵活可配置的而不必写死,ok,今天就到这。