`
酷的飞上天空
  • 浏览: 521716 次
  • 性别: Icon_minigender_1
  • 来自: 无锡
社区版块
存档分类
最新评论

通过反射把map中的属性赋值到实体类bean对象中

    博客分类:
  • J2EE
阅读更多

使用过struts2后感觉最方便的就是这个框架能自动把表单的参数赋值到action里面的对象中

但现在主要使用Spring框架的MVC,虽然也有@ModelAttribute可以使用但是明显感觉不方便。

好吧,那就自己再造一个轮子吧。

原理都知道,就是利用反射进行字段的赋值,下面贴代码

主要类如下:

 

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class MapToEntryConvertUtils {
	
	private static Log log = LogFactory.getLog(MapToEntryConvertUtils.class);
	
	/**
	 * 缓存类的属性信息
	 */
	private static Map<String,ConvertEntryItem> convertItemCache = new HashMap<String,ConvertEntryItem>(); 

	/**
	 * Map转换为Entry
	 * @param <T>
	 * @param valueMap 泛型类型为<String,Object>
	 * @param entityClass
	 * @param prefix 从map中取值的key为   prefix + attr
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static <T> T convert(Map valueMap,Class<T> entityClass,String prefix){
		ConvertEntryItem convertItem = convertItemCache.get(entityClass.getName());
		if(convertItem == null){
			convertItem = ConvertEntryItem.createConvertItem(entityClass);
			convertItemCache.put(entityClass.getName(), convertItem);
		}
		
		//entityClass 的可访问字段名
		List<String> fieldNameList = convertItem.getFieldNameList();
		//字段名和对应的set方法映射
		Map<String,Method> fieldSetMethodMap = convertItem.getFieldSetMethodMap();
		
		T entity = null;
		try {
			entity = entityClass.newInstance();
		} catch (InstantiationException e) {
			log.error("create "+entityClass.getName()+" instance failed, Do it has a empty constructed function ?", e);
			return null;
		} catch (IllegalAccessException e) {
			log.error("create "+entityClass.getName()+" instance failed, Do it has a empty constructed function ?", e);
			return null;
		}
		
		Object fieldValue = null;
		Method m;
		Class<?>[] parameterTypes;
		Object targetValue;
		if(prefix == null) prefix = "";
		//遍历字段列表,分别调用每个字段的set方法
		for(String fieldName: fieldNameList){
			fieldValue = valueMap.get(prefix+fieldName);
			if(fieldValue == null) continue;
			m = fieldSetMethodMap.get(fieldName);
			if(m == null) continue;
			
			//set方法的参数类型
			parameterTypes = m.getParameterTypes();
			if(parameterTypes.length != 1) continue;  //只支持单个参数的set方法
		
			//如果第一个参数类型和当前类型相同,则直接使用
			if(parameterTypes[0].isAssignableFrom(fieldValue.getClass())){
				targetValue = fieldValue;
			}else{
				//转换当前的值为目标参数类型
				targetValue = ConvertFactory.convert(parameterTypes[0], fieldValue);
			}
			
			if(targetValue != null){
				try {
					//调用set方法进行赋值
					m.invoke(entity, targetValue);
				} catch (Exception e) {
					log.error("set value failed:{method="+m.getName()+",value="+targetValue+"}", e);
				}
			}
		}
		return entity;
	}
	
	static class ConvertEntryItem{
		private List<String> fieldNameList = new ArrayList<String>();
		private Map<String,Method> fieldSetMethodMap = new HashMap<String, Method>();
		
		private ConvertEntryItem(){}
		
		public List<String> getFieldNameList() {
			return fieldNameList;
		}

		public Map<String, Method> getFieldSetMethodMap() {
			return fieldSetMethodMap;
		}
		
		private void parseEntry(Class<?> cls){
			Field[] allField = cls.getDeclaredFields();
			Method m = null;
			String methodName;
			for(Field f: allField){
				methodName = f.getName();
				methodName = "set"+methodName.substring(0, 1).toUpperCase()+methodName.substring(1);
				try {
					//只返回和当前字段类型相符的set方法,不支持多参数以及不同类型的set方法
					m = cls.getDeclaredMethod(methodName, f.getType());
					if(m != null){
						fieldNameList.add(f.getName());
						fieldSetMethodMap.put(f.getName(), m);
					}
				} catch (SecurityException e) {
					log.error("parseEntry failed: SecurityException", e);
				} catch (NoSuchMethodException e) {
					log.info("NoSuchMethod in "+cls.getName()+": "+methodName);
				}
			}
			
		}

		public static ConvertEntryItem createConvertItem(Class<?> cls){
			ConvertEntryItem ci = new ConvertEntryItem();
			ci.parseEntry(cls);
			return ci;
		}
	}
}
 

 

转换接口贴上,实话实说,偷的Spring里面的接口

 

/**
 * 类型转换接口
 * @param <S> 源类型
 * @param <T> 目标类型
 */
public interface Convert<S,T> {

	T convert(S source);
}

 

 

再来个具体调用转换的类:

 

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ConvertFactory {
	
	private static Log log = LogFactory.getLog(ConvertFactory.class);

	public static Map<String,Convert<?,?>> convertHandlers = new HashMap<String, Convert<?,?>>();
	
	/**
	 * 注册转换器
	 */
	static{
		convertHandlers.put(String[].class.getName()+"To"+Float[].class.getName(), new ObjectArrToFloatArrConvert());
		convertHandlers.put(String[].class.getName()+"To"+float[].class.getName(), new ObjectArrToFloaArrConvert());
		
		convertHandlers.put(String[].class.getName()+"To"+Double[].class.getName(), new ObjectArrToDoubleArrConvert());
		convertHandlers.put(String[].class.getName()+"To"+double[].class.getName(), new ObjectArrToDoublArrConvert());
		
		convertHandlers.put(String[].class.getName()+"To"+Integer[].class.getName(), new ObjectArrToIntegerArrConvert());
		convertHandlers.put(String[].class.getName()+"To"+int[].class.getName(), new ObjectArrToIntArrConvert());
		
		convertHandlers.put(String.class.getName()+"To"+Date.class.getName(), new ObjectToDateConvert());

		convertHandlers.put(String.class.getName()+"To"+Double.class.getName(), new ObjectToFloatConvert());
		convertHandlers.put(String.class.getName()+"To"+double.class.getName(), new ObjectToFloatConvert());
		
		convertHandlers.put(String.class.getName()+"To"+Float.class.getName(), new ObjectToFloatConvert());
		convertHandlers.put(String.class.getName()+"To"+float.class.getName(), new ObjectToFloatConvert());
		
		convertHandlers.put(String.class.getName()+"To"+Integer.class.getName(), new ObjectToIntegerConvert());
		convertHandlers.put(String.class.getName()+"To"+int.class.getName(), new ObjectToIntegerConvert());
		
		Set<Entry<String, Convert<?,?>>> entites = convertHandlers.entrySet();
		StringBuilder b = new StringBuilder();
		b.append("{");
		for(Entry<String, Convert<?,?>> entry: entites){
			b.append(entry.getKey()).append("=").append(entry.getValue()).append(",");
		}
		b.append("}");
		log.debug("all support convert type: "+b.toString().replaceFirst(",}", "}"));
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> T convert(Class<T> clazz,Object val){
		Convert cv = convertHandlers.get(val.getClass().getName()+"To"+clazz.getName());
		if(cv == null){
			log.info(clazz.getName()+"To"+val.getClass().getName()+ " convert failed: unsupport type");
			return null;
		}
		return (T)cv.convert(val);
	}
}
 

 

下面贴出来各种转换实现类:

 

import org.apache.commons.logging.LogFactory;

public class ObjectArrToDoublArrConvert implements Convert<Object[],double[]> {

	@Override
	public double[] convert(Object[] source) {
		if(source == null) return null;
		double[] res = new double[source.length];
		for(int i=0;i<source.length;i++){
			try {
				res[i] = Double.parseDouble(source[i].toString());
			} catch (NumberFormatException e) {
				LogFactory.getLog(getClass()).info("ObjectArrToDoublArrConvert failed, bad value: "+source[i].toString(), e);
				return null;
			}
		}
		return res;
	}
}
 

 

 

import org.apache.commons.logging.LogFactory;

public class ObjectArrToDoubleArrConvert implements Convert<Object[],Double[]> {

	@Override
	public Double[] convert(Object[] source) {
		if(source == null) return null;
		Double[] res = new Double[source.length];
		for(int i=0;i<source.length;i++){
			try {
				res[i] = Double.parseDouble(source[i].toString());
			} catch (NumberFormatException e) {
				LogFactory.getLog(getClass()).info("ObjectArrToDoubleArrConvert failed, bad value: "+source[i].toString(), e);
				return null;
			}
		}
		return res;
	}

}
 

 

 

import org.apache.commons.logging.LogFactory;

public class ObjectArrToFloaArrConvert implements Convert<Object[],float[]> {

	@Override
	public float[] convert(Object[] source) {
		if(source == null) return null;
		float[] res = new float[source.length];
		for(int i=0;i<source.length;i++){
			try {
				res[i] = Float.parseFloat(source[i].toString());
			} catch (NumberFormatException e) {
				LogFactory.getLog(getClass()).info("ObjectArrToFloaArrConvert failed, bad value: "+source[i].toString(), e);
				return null;
			}
		}
		return res;
	}

}
 

 

 

import org.apache.commons.logging.LogFactory;

public class ObjectArrToFloatArrConvert implements Convert<Object[],Float[]> {

	@Override
	public Float[] convert(Object[] source) {
		if(source == null) return null;
		Float[] res = new Float[source.length];
		for(int i=0;i<source.length;i++){
			try {
				res[i] = Float.parseFloat(source[i].toString());
			} catch (NumberFormatException e) {
				LogFactory.getLog(getClass()).info("ObjectArrToFloatArrConvert failed, bad value: "+source[i].toString(), e);
				return null;
			}
		}
		return res;
	}

}

 

 

import org.apache.commons.logging.LogFactory;

public class ObjectArrToIntArrConvert implements Convert<Object[],int[]> {

	@Override
	public int[] convert(Object[] source) {
		if(source == null) return null;
		int[] res = new int[source.length];
		for(int i=0;i<source.length;i++){
			try {
				res[i] = Integer.parseInt(source[i].toString());
			} catch (NumberFormatException e) {
				LogFactory.getLog(getClass()).info("ObjectArrToIntArrConvert failed, bad value: "+source[i].toString(), e);
				return null;
			}
		}
		return res;
	}

}
 

 

import org.apache.commons.logging.LogFactory;

public class ObjectArrToIntegerArrConvert implements Convert<Object[],Integer[]> {

	@Override
	public Integer[] convert(Object[] source) {
		if(source == null) return null;
		Integer[] res = new Integer[source.length];
		for(int i=0;i<source.length;i++){
			try {
				res[i] = Integer.parseInt(source[i].toString());
			} catch (NumberFormatException e) {
				LogFactory.getLog(getClass()).info("ObjectArrToIntegerArrConvert failed, bad value: "+source[i].toString(), e);
				return null;
			}
		}
		return res;
	}

}

 

public class ObjectArrToStringArrConvert implements Convert<Object[],String[]> {

	@Override
	public String[] convert(Object[] source) {
		if(source == null) return null;
		String[] res = new String[source.length];
		for(int i=0;i<source.length;i++){
			res[i] = source[i].toString();
		}
		return res;
	}

}

 

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Pattern;

import org.apache.commons.logging.LogFactory;

/**
 *支持的日期格式为:<br>
 *yyyy-MM-dd<br>
 *yyyy-MM-dd HH:mm<br>
 *yyyy-MM-dd HH:mm:ss<br>
 *yyyy/MM/dd<br>
 *yyyy/MM/dd HH:mm<br>
 *yyyy/MM/dd HH:mm:ss<br>
 */
public class ObjectToDateConvert implements Convert<Object,Date> {
	
	Object[][] patterns = {
			{Pattern.compile("^\\d+-\\d+-\\d+$"),"yyyy-MM-dd"},
			{Pattern.compile("^\\d+-\\d+-\\d+ \\d+:\\d+$"),"yyyy-MM-dd HH:mm"},
			{Pattern.compile("^\\d+-\\d+-\\d+ \\d+:\\d+:\\d+$"),"yyyy-MM-dd HH:mm:ss"},
			{Pattern.compile("^\\d+/\\d+/\\d+$"),"yyyy/MM/dd"},
			{Pattern.compile("^\\d+/\\d+/\\d+ \\d+:\\d+$"),"yyyy/MM/dd HH:mm"},
			{Pattern.compile("^\\d+/\\d+/\\d+ \\d+:\\d+:\\d+$"),"yyyy/MM/dd HH:mm:ss"}
	};
	
	@Override
	public Date convert(Object source) {
		if(source == null) return null;
		String val = source.toString();
		val = val.trim();
		
		String format = null;
		Pattern p;
		for(Object[] item:patterns){
			p = (Pattern)item[0];
			if(p.matcher(val).matches()){
				format = item[1].toString();
				break;
			}
		}
		
		if(format == null) {
			LogFactory.getLog(getClass()).info("ObjectToDateConvert failed, unsupport value: "+source);
			return null;
		}
		
		try {
			return new SimpleDateFormat(format).parse(val);
		} catch (ParseException e) {
			LogFactory.getLog(getClass()).info("ObjectToDateConvert failed, bad value: "+source,e);
			return null;
		}
	}

}

 

import org.apache.commons.logging.LogFactory;

public class ObjectToFloatConvert implements Convert<Object,Float> {

	@Override
	public Float convert(Object source) {
		if(source == null) return null;
		try {
			return Float.parseFloat(source.toString().trim());
		} catch (NumberFormatException e) {
			LogFactory.getLog(getClass()).info("ObjectToFloatConvert failed: "+source, e);
			return null;
		}
	}

}
 

 

import org.apache.commons.logging.LogFactory;

public class ObjectToIntegerConvert implements Convert<Object,Integer> {

	@Override
	public Integer convert(Object source) {
		if(source == null) return null;
		try {
			return Integer.parseInt(source.toString().trim());
		} catch (NumberFormatException e) {
			LogFactory.getLog(getClass()).info("ObjectToIntegerConvert failed: "+source, e);
			return null;
		}
	}

}

 

使用方法如下:

		Map<String,Object> map = new HashMap<String, Object>();
		map.put("intVal", "1");
		map.put("integerVal", "1");
		map.put("floatVal", "1.0");
		map.put("doubleVal", "1.0");
		map.put("dateVal", "2012-12-12 23:00:00");
		map.put("intArr", new String[]{"1","2"});
		map.put("integerArr", new String[]{"1","2"});
		map.put("strArr", new String[]{"A","B"});
		map.put("floatArr", new String[]{"1.0","1.0"});
		
		MapToEntryConvertUtils.convert(map, TestEntry.class, "");
		MapToEntryConvertUtils.convert(map, TestEntry.class, "");

 

第一次转换比较慢,但是第二次因为缓存了类的属性信息所以很快

分享到:
评论
1 楼 Tair 2017-10-20  

相关推荐

    将Map转换成Java实体

    在转换Map到实体时,我们需要获取实体类的属性信息,然后根据Map中的键值对设置这些属性的值,这就需要用到反射。 下面是一个简单的工具类`CollectionTools`的示例代码,它使用泛型和反射实现了Map到实体的转换: ...

    通过java反射实现map与bean之间互转

    在给定的标题“通过java反射实现map与bean之间互转”中,我们要探讨的是如何利用Java反射机制将Map对象转换为Java Bean对象,以及反过来,将Java Bean对象转换为Map对象。这个过程在数据处理和序列化中非常常见。 ...

    MapUtils工具类,轻松转换map数据与实体类

    例如,如果`Map`中的键"username"对应于`User`类的`username`属性,那么`MapUtils`会自动将这个值设置到新创建的`User`对象上。 在`MapUtils.java`文件中,我们可以看到这些功能的实现。通常,该类会使用反射机制...

    java中将数据库中数据赋值给Map对象源代码

    然后,我们可以创建一个Java类,使用JdbcTemplate执行SQL查询并把结果转换为Map对象。以下是一个简单的示例: ```java import org.springframework.beans.factory.annotation.Autowired; import org.spring...

    Map和Bean灵活转换工具类

    这个工具类提供了一系列的方法,如`copyProperties()`,可以将一个Bean的属性值复制到另一个Bean中,实现了对象间的属性映射。此外,`BeanUtils`还可以将Bean转换为Map,这样我们就可以轻松地获取Bean的所有属性及其...

    基于java8新特性+反射机制实现list不同实体类互转.zip

    通过反射,我们可以根据源实体类的对象,创建目标实体类的对象并复制相应的属性值。 要实现不同实体类的List之间的转换,首先我们需要知道源列表(SourceList)和目标列表(TargetList)中实体类的结构关系。通常,...

    java Map转换成bean,利用java反射以及java和bean包

    `mapToBean`方法接受一个Map和目标Bean的Class对象,首先检查参数是否有效,然后创建一个新的Bean实例,遍历Map中的每一个键值对,通过反射找到Bean中对应的Field,设置其可访问,最后调用`set()`方法设置属性值。...

    各种转换,xml,实体bean,动态bean,map等

    标题和描述中提到的"各种转换,xml,实体bean,动态bean,map等"涉及了Java编程语言中的一些核心概念,这些概念在企业级应用开发中非常常见。下面我们将详细探讨这些知识点。 1. **XML(Extensible Markup Language)*...

    List转换为List

    3. **复制属性到Map**:从Bean对象中获取属性值,将这些值放入Map中。键通常是属性名,值是属性值。 4. **将Map添加到新的List中**:每当创建完一个Map后,将其添加到一个新的List&lt;Map&gt;集合中。 5. **返回新的List...

    Java Bean对象和Map相互转换.zip

    其次,BeanMap是Apache Commons Lang库中的一个工具类,它允许我们把Java Bean对象直接转换为Map,同时也支持从Map创建Java Bean。 3. **BeanMap进行Java Bean到Map的转换**: ```java import org.apache.commons...

    map 和 bean 之间的转换

    map 和 bean 之间的转换,可以利用反射的原理实现

    java bean和map之间的互转

    转换Java Bean到Map的过程通常是通过反射机制来实现的。以下是一个简单的示例: ```java import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class BeanToMapConverter { ...

    任意XML转实体类 实体类 转XML 方法 JAVA

    总结一下,XML转实体类和实体类转XML涉及的主要知识点有:Java反射API、XML解析(DOM、SAX、StAX、JAXB),以及对象的序列化和反序列化。在实际开发中,我们需要根据项目需求选择合适的工具和方法,确保数据的准确...

    实体对象属性动态化(私有属性来源为map)代码.rar

    本示例中的"实体对象属性动态化(私有属性来源为map)"是一个具体的应用场景,它利用Map来存储实体类的私有属性,从而实现属性的动态添加、修改和访问。下面我们将详细探讨这一技术。 1. **Map接口**:在Java中,Map...

    java Map转Bean Bean转Map Map排序

    java Map转Bean Bean转Map Map排序

    Bean与Map转换工具类BeanMapConverter.java

    Bean与MAP间互转换的工具类。 1.将一个 Map 对象转化为一个 JavaBean,可指定BEAN的类型; 2.将一个 JavaBean 对象转化为一个 HashMap;

    通用适配器(实体类+map)

    在标题中提到的"实体类+Map"方式,就是指适配器既可以处理自定义的实体类对象,也可以处理基于Map的数据结构。实体类通常用于封装业务逻辑中的数据,而Map则提供了键值对存储,便于快速查找和操作数据。 对于描述中...

    在Java 8中将List转换为Map对象方法

    但是,如果List中有重复的empId,映射到Map时,Key不能重复的,这时我们可以使用BinaryOperator方法来解决这个问题: Map, String&gt; mapOfEmployees = employees.stream().collect( Collectors.toMap( e -&gt; e....

    spring bean 属性总结

    - **id属性**:是Bean在BeanFactory中的唯一标识符,用于通过BeanFactory获取Bean实例。例如,`&lt;bean id="myBean" class="com.example.MyClass"&gt;`。 - **name属性**:类似于`id`属性,但可以定义多个别名。例如,`...

    Java_Bean2Map

    Java_Bean2Map,将实体类转化成对应的map的工具类

Global site tag (gtag.js) - Google Analytics