获取对象属性类型、属性名称、属性值的研究:反射和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
微信公众号: 猿人谷
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎关注微信公众号
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

目录
相关文章
|
1天前
|
JavaScript 前端开发
深入解析JavaScript中的面向对象编程,包括对象的基本概念、创建对象的方法、继承机制以及面向对象编程的优势
【6月更文挑战第12天】本文探讨JavaScript中的面向对象编程,解释了对象的基本概念,如属性和方法,以及基于原型的结构。介绍了创建对象的四种方法:字面量、构造函数、Object.create()和ES6的class关键字。还阐述了继承机制,包括原型链和ES6的class继承,并强调了面向对象编程的代码复用和模块化优势。
10 0
|
2天前
|
存储 算法 数据挖掘
深入解析力扣168题:Excel表列名称(进制转换法详解及模拟面试问答)
深入解析力扣168题:Excel表列名称(进制转换法详解及模拟面试问答)
|
14天前
|
Java 开发者
Java中的对象:深入解析与实践
Java中的对象:深入解析与实践
10 0
|
14天前
|
存储 数据处理 Python
Python中的字典(Dictionary)类型:深入解析与应用
Python中的字典(Dictionary)类型:深入解析与应用
|
17天前
|
存储 算法 Java
滚雪球学Java(42):探索对象的奥秘:解析Java中的Object类
【5月更文挑战第17天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
25 2
滚雪球学Java(42):探索对象的奥秘:解析Java中的Object类
|
19天前
|
测试技术 持续交付 数据处理
Python动态类型深度解析与实践
Python动态类型深度解析与实践
405 1
|
19天前
|
存储 Java
Java语言中的类与对象:深入解析与实战应用
Java语言中的类与对象:深入解析与实战应用
|
19天前
|
移动开发 iOS开发
非标准h5字符串的WKWebView展示前的解析与插入属性或标题头与解决WKWebView无法加载视频首帧问题
非标准h5字符串的WKWebView展示前的解析与插入属性或标题头与解决WKWebView无法加载视频首帧问题
26 1
|
22天前
|
域名解析 网络协议
【域名解析 DNS 专栏】DNS 记录类型全解析:A、MX、CNAME 与更多
【5月更文挑战第22天】DNS记录类型包括A、MX、CNAME等,用于确保域名与网络资源准确关联。A记录将域名指向IPv4地址,MX记录指定邮件服务器,CNAME则用于创建域名别名。其他记录如NS记录指定名称服务器,TXT记录用于验证和设置策略,SRV记录定义服务位置。正确配置DNS记录对网络运行至关重要,需注意信息准确性和及时更新。理解和运用这些记录能优化网络环境,支持各种在线服务。
【域名解析 DNS 专栏】DNS 记录类型全解析:A、MX、CNAME 与更多
|
25天前
|
XML 数据格式
XML Schema 复杂元素类型详解:定义及示例解析
在XML Schema(XSD)中,复杂元素包含其他元素和/或属性,分为4类:空元素、仅含元素、仅含文本和既含元素也含文本。定义复杂元素可通过直接声明或引用预定义的复杂类型。复杂空元素仅含属性,而仅含元素的类型则只包含其他子元素。XSD提供了`&lt;xs:sequence&gt;`、`&lt;xs:all&gt;`、`&lt;xs:choice&gt;`等指示器来规定元素顺序和出现次数,以及`&lt;xs:attributeGroup&gt;`和`&lt;xs:group&gt;`来组织元素和属性。
187 7

推荐镜像

更多