近段时间在做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语句,传入后台自行查询,至于过滤那部分,应该是没办法抽取的,需要在各自的控制层处理一下。
记录每一次的技术心得。
本文出自 “around” 博客,请务必保留此出处http://around.blog.51cto.com/10926575/1837847
原文:http://around.blog.51cto.com/10926575/1837847