近段时间在做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需要获取的属性名,可以是当前对象中的属性名, 也可以是当前对象中的对象的属性名
* @returnObject 当前对象指定属性值
*/
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
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所需要获取的属性名
* @returnObject
*/
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语句,传入后台自行查询,至于过滤那部分,应该是没办法抽取的,需要在各自的控制层处理一下。
记录每一次的技术心得。