获取对象属性类型、属性名称、属性值的研究:反射和JEXL解析引擎
同步发布: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("------------------------");
}
获取对象属性类型、属性名称、属性值的研究:反射和JEXL解析引擎的更多相关文章
- js中如何获取对象的长度和名称
js如何获取对象长度和名称 一.总结 一句话总结:对象的长度不能用.length获取,用js原生的Object.keys可以获取到 var obj = {'name' : 'Tom' , 'sex' ...
- typescript 关于class属性类型定义被属性默认值覆盖的问题及解决方式
问题来源于 React.component的第二个参数的类型定义问题,我构建了以下简化demo,方便描述问题: class P<STATE> { public state: STATE; ...
- C#中通过反射方法获取控件类型和名称
这个方法是简单的也是神奇的. 有木有想过,将自己项目中的所有类型,包括自定义类型的命名空间和名称全部获取出来? 有木有想过,有一种简便的方法可以自动化管理项目中的控件和窗体? 有木有想过... 首先, ...
- 获取httpservletrequest所有参数的名称和值
1.方法 private Map showParams(HttpServletRequest request) { Map map = new HashMap(); Enumeration param ...
- 精确获取对象的类型:Object.prototype.toString()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
- C#获取EF实体对象或自定义属性类的字段名称和值
在年前上班的时候遇到了一个问题是这样描述的:我前台设计一个页面,是标签和文本框,当用户修改了哪个文本框的值,将该修改前的值.修改后的值,该值对应的字段,该值对应的行id获取到保存到数据库的某张表里.现 ...
- 【java】java获取对象属性类型、属性名称、属性值
java获取对象属性类型.属性名称.属性值 获取属性 修饰符:[在Field[]循环中使用] String modifier = Modifier.toString(fields[i].getModi ...
- java获取对象属性类型、属性名称、属性值
/** * 根据属性名获取属性值 * */ private Object getFieldValueByName(String fieldName, Object o) { try { String ...
- java获取对象属性类型、属性名称、属性值 【转】
/** * 根据属性名获取属性值 * */ private Object getFieldValueByName(String fieldName, Object o) { try { String ...
随机推荐
- Number()和new Number()的区别以及一种简单实现
看MDN Beginners文档的时候注意到了这种用法 var n1 = Number(123); , 冒出的第一个疑问就是和 var n2 = new Number(123); 有什么区别呢? 首先 ...
- mybatis配置多个数据源事务(Transaction)处理
当mybatis配置文件中只有一个数据源的时候,按照正常的事务注解形式@Transaction是没有问题的,但是当配置文件中有多个数据源的时候发现事务不起作用了,怎么解决这个问题呢?看下面的案例:
- AI_深度学习概论
什么是是神经网络? 假如有6间房屋的数据集,已知房子的面积,单位是平方米或平方英尺,已知房子的价格.如果通过这6间房子的价格和房子的面积,预测房子的价格,首先要建立起一个数据模型 ,x轴为价格,y轴为 ...
- 基于BCGP库的界面效果
- 自己模拟的一个简单的web服务器
首先我为大家推荐一本书:How Tomcat Works.这本书讲的很详细的,虽然实际开发中我们并不会自己去写一个tomcat,但是对于了解Tomcat是如何工作的还是很有必要的. Servlet容器 ...
- libev学习代码
- Linux下passwd和shadow文件内容详解
一./etc/passwd /etc/passwd 文件是一个纯文本文件,每行采用了相同的格式: name:password:uid:gid:comment:home:shell name 用户登录名 ...
- jenkins插件安装与升级[三]
标签(linux): jenkins 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 默认的插件 Folders Plugin OWASP Markup Form ...
- Effective Java 之 --- 用私有构造器或者枚举类型强化Singleton属性
Singleton指仅仅被实例化一次的类,通常用来代表那些本质上唯一的系统组件,实现Singleton有三种方法: 1)公有静态成员是个final域,享有特权的用户可以调用AccessibleObje ...
- Django中模板的用法简介
1. 模板系统的介绍 Django作为一个Web框架,其模板所需的HTML输出静态部分以及动态内容插入 模板由HTML代码和逻辑控制代码构成 Django框架的模板语言的语法格式: {{var_nam ...