同步发布: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("------------------------"); }