• 获取对象属性类型、属性名称、属性值的研究:反射和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("------------------------");
    	}
    
  • 相关阅读:
    SQL查询,所有的客户订单日期最新的前五条订单记录。
    session的原理
    @RequestMapping 注解用在类上面有什么作用?
    事务的概念,在JDBC编程中处理事务的步骤
    .Redis优势
    Spring框架中都用到了哪些设计模式?
    redis
    你为什么觉得自己能够在这个职位上取得成就?
    怎样理解团队?请举例并说明启示。
    物质待遇和工作条件是人们选择工作的重要因素之一,这次报考谈一谈你在选择工作时都考虑哪些因素?为什么?
  • 原文地址:https://www.cnblogs.com/heyonggang/p/6861910.html
Copyright © 2020-2023  润新知