java反射獲取對象的屬性值和對象屬性中的子屬性值

近段時間在做web項目,前端使用的是jQuery EasyUI。

爲方便需要,準備做一個前端通用的Datagird導出Excel功能,博主也考慮過思路和最終功能,1、前端選中行導出;2、當前頁導出;3、當前過濾條件導出。

想偷懶在網上找找已有的代碼改改,發現大部分只能滿足個別需求,使用JS導出只能滿足前端,使用代碼才能實現3功能。

。。。。。。


好了,說了一堆廢話,迴歸正題,本文是在做通用自定義字段導出時所需要,根據屬性名去查找對象和子對象,找到對應屬性值,抓取回來放到Excel中。


直接上代碼,已經封裝好,直接調用即可:

import java.lang.reflect.Field;


/**
 * 屬性(對象)值反射獲取工具類
 * @author 周圍
 * @date 2016-8-14
 */
public class ParamsReflect {
	
	public static final String FILE_FIELD = "nameB,";

	/**
	 * 獲取當前對象對應字段的屬性(對象)
	 * 聲明,需要注意在NoSuchFieldException異常捕捉中捕獲自己需要的屬性字段進行攔截,告訴當查詢這些屬性名的時候,指定是查找的哪些對象,如果不告訴它,它是不知道的
	 * @param obj	當前對象
	 * @param field	需要獲取的屬性名,可以是當前對象中的屬性名, 也可以是當前對象中的對象的屬性名
	 * @return	Object  當前對象指定屬性值
	 */
	public static Object getFieldValue(Object obj, String field) {
		Class<?> claz = obj.getClass();
		Field f = null;
		Object fieldValue = null;
		try {
			f = claz.getDeclaredField(field);
			f.setAccessible(true);
			fieldValue = f.get(obj);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			//此處異常捕獲爲:找不到屬性名異常。
			//注意在此處我們要手工去幫它找到field應該對象到哪個對象裏的值,因爲我們不知道它們之間的關係,所以需要手工指定關係,找哪個對象去關聯
			if(FILE_FIELD.indexOf(field) != -1) fieldValue = getCustomChildObj(obj, claz, B.class, field);
			else fieldValue = null;
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return fieldValue;
	}
	
	
	/**
	 * 獲取自定義子屬性對象,傳入指定對象名,在當前對象中找到子對象,再通過field找到子屬性
	 * @param obj	父對象名稱
	 * @param claz	父對象class反射
	 * @param customClass	自定義判斷的子對象類型
	 * @param field	屬性名
	 * @return Object
	 */
	public static Object getCustomChildObj(Object obj, Class<?> claz, Class<?> customClass, String field) {
		Field[] fs = claz.getDeclaredFields();
		Field f = null;
		for (int i = 0; i < fs.length; i++) {
			f = fs[i];
			if(f.getType().equals(customClass)) {
				return getChildObjectParam(obj, f, field);
				//return claz.getDeclaredField(f.getName());
			}
		}
		return null;
	}
	
	
	/**
	 * 通過找到的子對象,獲取到當前的屬性,傳入所需的屬性名,得到屬性值
	 * @param o	父對象
	 * @param f	父對象下的子對象的Field對象
	 * @param field	所需要獲取的屬性名
	 * @return	Object
	 */
	public static Object getChildObjectParam(Object o, Field f, String field)  {
		f.setAccessible(true);
		Object obj = null;
		Class<?> childClass = null;
		Field childF = null;
		Object fieldValue = null;
		try {
			obj = f.get(o);
			childClass = obj.getClass();
			childF = childClass.getDeclaredField(field);
			childF.setAccessible(true);
			fieldValue = childF.get(obj);
			
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
		return fieldValue;
	}
}

模擬測試:

對象A中有屬性name,子對象B,對象B中有屬性id,nameB。

B b = new B();

b.setId("b");

b.setNameB("b-name");


A a = new A();

a.setName("a-name");

a.setB(b);


Object value1 = ParamsReflect.getFieldValue(a, "name"); //獲取a中的屬性

Object value2 = ParamsReflect.getFieldValue(a, "nameB"); //獲取b中的屬性



功能比較簡單,並不靈活,爲應付功能,先做了一個這樣的版本,以後繼續完善,也留幾個問題。

1、目前的版本只控制到了需要自己傳入對應的子對象.class,博主還未想到怎麼樣設定自動匹配對應的屬性值。(也想過直接對該對象和裏面的所有子對象進行掃描,拿需要獲取值得字段進去得,但是發現一個問題,不同對象中的屬性,可能存在屬性名相同,所以掃描無法控制唯一性)


2、以上版本是用於EasyUI中的Datagrid,該控件中的field屬性無法命名爲"b.nameB",不能直接用子對象去獲取子屬性,博主也嘗試改過EasyUI的JS源碼,讓其支持子對象.屬性的方式,但又存在其他的問題不兼容這個方式,所以以這個方案實施,有大神有其他辦法嗎。


3、最終版,作者是準備在空閒的時候完善升級它,不侷限於Datagrid,所有都支持的導出Excel功能。這裏準備做的是,先將對象傳入後臺,並進入數據庫查詢,將對應實體的表,字段名,字段類型全部獲取到。之後處理成對應格式,是子對象的,用子對象屬性名.子對象屬性拼接好,返回前臺,讓用戶選擇需要導出的列,選擇完畢後返回後臺,拼接這些字段,生成SQL語句,傳入後臺自行查詢,至於過濾那部分,應該是沒辦法抽取的,需要在各自的控制層處理一下。


記錄每一次的技術心得。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章