获取对象属性类型、属性名称、属性值的研究:反射和JEXL解析引擎详解编程语言

 

先简单介绍下反射的概念:java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以在运行时装配。在实际的业务中,可能会动态根据属性去获取值。

工具类如下:

 

package com.yaoguang.common.utils.field; 
 
import java.beans.BeanInfo; 
import java.beans.Introspector; 
import java.beans.PropertyDescriptor; 
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.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
 
/** 
 * 实体属性操作工具类 
 *  
 * @author heyonggang 
 * @date 2017年5月10日下午5:56:59 
 */ 
public class ObjectFieldUtil { 
 
	private static Logger log = LoggerFactory.getLogger(ObjectFieldUtil.class); 
 
	/** 
	 * 根据属性名获取属性值 
	 *  
	 * @param fieldName  字段名 
	 * @param o 实体 
	 * @return 
	 */ 
	public static Object getFieldValueByName(String fieldName, Object o) { 
		try { 
			String firstLetter = fieldName.substring(0, 1).toUpperCase(); 
			String getter = "get" + firstLetter + fieldName.substring(1); 
			Method method = o.getClass().getMethod(getter, new Class[] {}); 
			Object value = method.invoke(o, new Object[] {}); 
			return value; 
		} catch (Exception e) { 
			log.error(e.getMessage(), e); 
			return null; 
		} 
	} 
 
	/** 
	 * 获取属性名数组 
	 *  
	 * @param o 实体 
	 * @return 
	 */ 
	public static String[] getFiledName(Object o) { 
		Field[] fields = o.getClass().getDeclaredFields(); 
		String[] fieldNames = new String[fields.length]; 
		for (int i = 0; i < fields.length; i++) { 
			System.out.println(fields[i].getType()); 
			fieldNames[i] = fields[i].getName(); 
		} 
		return fieldNames; 
	} 
 
	/** 
	 * 获取属性类型(type),属性名(name),属性值(value)的map组成的list 
	 *  
	 * @param o 实体 
	 * @return 
	 */ 
	public static List<Map<String, Object>> getFiledsInfo(Object o) { 
		Field[] fields = o.getClass().getDeclaredFields(); 
//		String[] fieldNames = new String[fields.length]; 
		List<Map<String, Object>> list = new ArrayList<>(); 
		Map<String, Object> infoMap = null; 
		for (int i = 0; i < fields.length; i++) { 
			infoMap = new HashMap<String, Object>(); 
			infoMap.put("type", fields[i].getType().toString()); 
			infoMap.put("name", fields[i].getName()); 
			infoMap.put("value", getFieldValueByName(fields[i].getName(), o)); 
			list.add(infoMap); 
		} 
		return list; 
	} 
 
	/** 
	 * 获取对象的所有属性值,返回一个对象数组 
	 *  
	 * @param o  实体 
	 * @return 
	 */ 
	public static Object[] getFiledValues(Object o) { 
		String[] fieldNames = getFiledName(o); 
		Object[] value = new Object[fieldNames.length]; 
		for (int i = 0; i < fieldNames.length; i++) { 
			value[i] = getFieldValueByName(fieldNames[i], o); 
		} 
		return value; 
	} 
 
	/** 
	 * 根据对象属性名设置属性值 
	 *  
	 * @param fieldName 字段名 
	 * @param value 字段值 
	 * @param o 实体 
	 * @return 
	 */ 
	public static void setFieldValueByName(String fieldName, Object o,Object value) { 
		try { 
			BeanInfo obj =Introspector.getBeanInfo(o.getClass(), Object.class); 
			PropertyDescriptor[] pds = obj.getPropertyDescriptors(); 
			for (PropertyDescriptor pd : pds) { 
				if(pd.getName().equals(fieldName)){ 
					pd.getWriteMethod().invoke(o, value); 
					break; 
				} 
			} 
		} catch (Exception e) { 
			log.error(e.getMessage(), e); 
		} 
	} 
} 

 

 测试用例如下:

/** 
	 * 根据实体和属性名获取值 
	 */ 
	@Test 
	public void testGetField(){ 
		TruckBills truckBills = iTruckBillsService.geTruckBills("02cb5069b44f45dca578e5ada08bf513", "88"); 
		 
		String orderSn = (String) ObjectFieldUtil.getFieldValueByName("orderSn", truckBills); 
		String shipper = (String) ObjectFieldUtil.getFieldValueByName("shipper", truckBills); 
		 
		String[] fieldNames = ObjectFieldUtil.getFiledName(truckBills); 
		 
		List<Map<String, Object>> listMap = ObjectFieldUtil.getFiledsInfo(truckBills); 
		 
		System.out.println("---------------------------"); 
		System.out.println(orderSn); 
		System.out.println(shipper); 
		System.out.println(Arrays.toString(fieldNames)); 
		for (Map<String, Object> map : listMap) { 
			System.out.println("---------------------------"); 
			Set<Entry<String, Object>> entrySet = map.entrySet(); 
			for (Entry<String, Object> entry : entrySet) { 
				System.out.println(entry.getKey() + "-----" + entry.getValue()); 
			} 
			System.out.println("---------------------------"); 
		} 
	} 

 

还有一种将字符串转换成java代码并执行的方法:Java Expression Language (JEXL) 是一个表达式语言引擎,可以用来在应用或者框架中使用

JEXL受Velocity和JSP 标签库 1.1 (JSTL) 的影响而产生的,需要注意的是,JEXL 并不时 JSTL 中的表达式语言的实现。

需要先添加jar包,maven配置如下:

 

		<dependency> 
			<groupId>org.apache.commons</groupId> 
			<artifactId>commons-jexl</artifactId> 
			<version>2.0</version> 
		</dependency> 

 

 核心代码如下:

public class DyMethodUtil { 
	 
	/** 
	 * 将字符串转换成java代码并执行 
	 *  
	 * @param jexlExp 需要转换的字符串 
	 * @param map 参数集合 
	 * @return 方法执行结果 
	 * 如: 
	 * String jexlExp="testService.save(person)";  
	 * map.put("testService",testService);   
	 * map.put("person",person);   
	 */ 
	public static Object invokeMethod(String jexlExp, Map<String, Object> map) { 
		JexlEngine jexl = new JexlEngine(); 
		Expression e = jexl.createExpression(jexlExp); 
		JexlContext jc = new MapContext(); 
		for (String key : map.keySet()) { 
			jc.set(key, map.get(key)); 
		} 
		if (null == e.evaluate(jc)) { 
			return ""; 
		} 
		return e.evaluate(jc); 
	} 
} 

 测试示例如下:

/** 
	 * 动态构建 
	 */ 
	@Test 
	@Rollback(false) 
	public void testTemple(){ 
		//1.拿到结果集 
		//2.构建语言表达式 
		//3.动态构建 
		 
		TruckBills truckBills = iTruckBillsService.geTruckBills("02cb5069b44f45dca578e5ada08bf513", "88"); 
		 
		List<TruckGoodsAddr> truckGoodsAddrs = truckBills.getTruckGoodsAddrs(); 
		TruckOther truckOther = truckBills.getTruckOther(); 
		 
		Map<String, Object> map = new HashMap<>(); 
		map.put("truckBills", truckBills); 
		 
		System.out.println("------------------------"); 
		System.out.println(JsonBinder.buildNormalBinder().toJson(map)); 
		System.out.println("------------------------"); 
		 
		String expression = "truckBills.getTruckGoodsAddrs().get(0).getBillsId()"; 
		 
		Object aa = DyMethodUtil.invokeMethod(expression, map); 
		System.out.println("------------------------"); 
		System.out.println(JsonBinder.buildNormalBinder().toJson(aa)); 
		System.out.println("------------------------"); 
	} 

 

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/16131.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论