开发者社区> yuanrengu> 正文

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

简介: 同步发布:http://www.yuanrengu.com/index.php/20170511.html 先简单介绍下反射的概念:java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
+关注继续查看

 

同步发布:http://www.yuanrengu.com/index.php/20170511.html

先简单介绍下反射的概念: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("------------------------");
	}

 

img_e00999465d1c2c1b02df587a3ec9c13d.jpg
微信公众号: 猿人谷
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎关注微信公众号
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
访问对象的属性,你知道有哪些方法?
相信对象对于每个使用JavaScript的人来说都不陌生。访问对象的属性几乎日常开发每天都在用。下面我们一起探索下有哪些方式可以实现属性的访问。
62 0
对象中是否有某一个属性 in
对象中是否有某一个属性 in
49 0
18、属性描述对象
JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。这个内部数据结构称为“属性描述对象”(attributes object)。
56 0
【Kotlin】属性 与 幕后字段 ( 属性声明 | 属性初始化器 | 属性访问器 | field 属性幕后字段 | lateinit 延迟初始化属性 )
【Kotlin】属性 与 幕后字段 ( 属性声明 | 属性初始化器 | 属性访问器 | field 属性幕后字段 | lateinit 延迟初始化属性 )
102 0
属性和方法|学习笔记
快速学习 属性和方法
45 0
获取对象属性值改动的属性集合的正确姿势(拒绝大量If-else代码)
在业务场景中可能有这样的需求: 同一个类的两个对象(一个数数据库中获取的上一次的属性,一个是前端传来的修改过的属性),需要判断哪个属性被修改了。 那么有一些童鞋可能采用大量的if-else代码块对需要关注的属性进行判断。
67 0
Java反射得到属性和属性的值和设置属性的值
Java反射得到属性和属性的值和设置属性的值
2529 0
Java反射获取对象中特定属性的值
Java反射获取对象中特定属性的值 问题一:如何找到某个对象中特定属性的值? public static Object getFieldValueByObject (Object object , String targetFieldName) throws Exception { ...
10400 0
C#使用反射设置属性值
最近在Refix一个支持Excel文件导入导出功能时,发现有用到反射的相关技能。故而在网上查了些资料,通过代码调试加深下理解。 class Program { static void Main(string[] args) { ...
1208 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载