近段時間在做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語句,傳入後臺自行查詢,至於過濾那部分,應該是沒辦法抽取的,需要在各自的控制層處理一下。
記錄每一次的技術心得。