zoukankan      html  css  js  c++  java
  • 获取对象属性类型、属性名称、属性值的研究:反射和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("------------------------");
    	}
    
  • 相关阅读:
    【Spring学习笔记-MVC-6】SpringMVC 之@RequestBody 接收Json数组对象
    【Spring学习笔记-MVC-1.1--】@PathVariable与@RequestParam、@CookieValue等比较
    【Oracle学习笔记-1】Win7下安装Oracle 10g
    【Oracle学习笔记-3】关于Oracle 10g中各种服务解析
    【前端编程-学习-5】系统加载提示
    【EasyUI学习-3】Easyui tabs入门实践
    【EasyUI学习-2】Easyui Tree的异步加载
    【Hibernate学习笔记-6.1】无连接表的N-1关联(单向)
    ArcGIS 要素合并
    Nginx 链接
  • 原文地址:https://www.cnblogs.com/heyonggang/p/6861910.html
Copyright © 2011-2022 走看看