获取对象属性类型、属性名称、属性值的研究:反射和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 ...
随机推荐
- eclipse 按住ctrl 按钮没有反映
以下是修改为XML Editior打开方法Window -> Preferences -> General -> Editors -> File Associations Fi ...
- CCF系列之模板生成系统( 201509-3 )
试题名称: 模板生成系统 试题编号: 201509-3 时间限制: 1.0s 内存限制: 256.0MB 问题描述 成成最近在搭建一个网站,其中一些页面的部分内容来自数据库中不同的数据记录,但是页面的 ...
- word:Can't find the word document templant:WordToRqm.doc
问题:打开word文件时弹出提示 Cannot find the Word template:WordToRqm.dot 原因:安装了power designer. 解决:运行regedit.exe ...
- 洛谷 P1078 文化之旅
P1078 文化之旅 题目描述 有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家).不同的国家可能 ...
- 频繁更换ip会影响SEO优化吗?
网站更换ip会不影响SEO的效果,其实网站更换ip是正常的(但不能频繁更换),搜索引擎抓取是根据网站的域名进行的,不是根据ip来抓取你的网站.在短时间内更换IP对SEO的效果并没有很大的影响. 如果是 ...
- Hystrix-异常处理
异常的传播和捕获 传播:在HystrixCommand实现的run()方法中跑出异常时,除了HystrixBadRequestException之外,其他异常均会被Hystrix认为命令执行失败并处罚 ...
- eclipse-java开发实用快捷键
Expand All:ctrl+小键盘* Collapse All:ctrl+shift+小键盘/
- windows 查看端口被哪个程序占用
比如查看端口8080 1. 查看占用端口8080对应的PID,输入命令:netstat -aon|findstr "8080" (加入查到pid为111222) 2. 继续输入ta ...
- web开发概述
1 Web概述 Web,在英语中表示网页的额意思,它用于表示Internet主机上供外界访问的资源. 2 Web的分类 按照服务器上的资源分类: 静态资源:指的是web页面中供人们浏览的数据是始终不变 ...
- ( ! ) Parse error: syntax error, unexpected '' (T_ENCAPSED_AND_WHITESPACE), expecting identifier (T_STRING) or variable (T_VARIABLE) or number (T_NUM_STRING) in D:\demo\code\yolo\index\index.php on li
sql语句为:$sql="select count(*) from com where a_id=$v['id']"; 出现以下错误: 原因: 变量没有用花括号引起来 改为: $ ...