EaysPoi导出的时候根据权限动态导出列——反射实现
- EasyPOI
- 时间:2021-07-21 07:10
- 5676人已阅读
简介
前言: 前段时间,因为业务需求需要根据用户角色动态导出excel,不同角色看到的列不同。以前用到的方法基本是(或者有其他土方法),创建多个实体类,每个实体类对应的列不同,以此来实现动态导出,但显然这是个笨方法,虽然省时省力,但好像总觉得哪里不对。正片开始
🔔🔔🔔好消息!好消息!🔔🔔🔔
有需要的朋友👉:联系凯哥
前言: 前段时间,因为业务需求需要根据用户角色动态导出excel,不同角色看到的列不同。以前用到的方法基本是(或者有其他土方法),创建多个实体类,每个实体类对应的列不同,以此来实现动态导出,但显然这是个笨方法,虽然省时省力,但好像总觉得哪里不对。正片开始
举个栗子:
// 点击@Excel注解进去看到源码 /** * 是否需要隐藏该列 * @return */ public boolean isColumnHidden() default false;
可以看到,isColumnHidden中提供的默认值是false,也就是默认全部导出,不隐藏。假如我的权限是学生(ST),在登录教务系统时,导出班级学生信息时,不想让学生看到各班同学的年龄情况,可以把它设置成 true ,不要问我为什么不能看到年龄???这样所有导出都没有学生列,但是如果教师(TC)(你们可怕的班主任或者往上的教导主任)导出时时可以看到年龄信息的。
思路:
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。——百度百科
根据反射我们可以拿到一个类的所有属性和方法,同理,注解也是一个类,也是可以拿到它的属性和方法,拿到之后就好办了,直接修改它的默认值,然后根据每个角色调整,就可以达到一个类实现动态导出的目的
以上面 TestExcle 为例:
先创建一个工具类,传入TestExcle对象,获取注解值,并修改:
/** * 动态显示Excel导出列 * * @param <T> * @author young */ public class EasyPoiUtil<T> { /** * 需要被反射的对象,使用泛型规范传入对象 */ public T t; /** * 动态更改EasyPoi中控制列显示的值 * * @param columnName 需要转换的列属性名称 * @param target 默认true * @throws NoSuchFieldException * @throws IllegalAccessException */ public void hihdColumn(String columnName, Boolean target) throws Exception { if (t == null) { throw new ClassNotFoundException("TARGET OBJECT NOT FOUNT"); } if (StringUtils.isEmpty(columnName)) { throw new NullPointerException("COLUMN NAME NOT NULL"); } if (target == null) { target = true; } //获取目标对象的属性值 Field field = t.getClass().getDeclaredField(columnName); //获取注解反射对象 Excel excelAnnon = field.getAnnotation(Excel.class); //获取代理 InvocationHandler invocationHandler = Proxy.getInvocationHandler(excelAnnon); Field excelField = invocationHandler.getClass().getDeclaredField("memberValues"); excelField.setAccessible(true); Map memberValues = (Map) excelField.get(invocationHandler); memberValues.put("isColumnHidden", target); }
大大的完结!
EasyPoiUtil工具类:
package com.kaigejava.model.util; import cn.afterturn.easypoi.excel.annotation.Excel; import org.apache.commons.lang3.StringUtils; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.Map; /** * 动态显示Excel导出列 * * @param <T> * @author kaigejava */ public class EasyPoiUtil<T> { /** * 需要被反射的对象,使用泛型规范传入对象 */ public T t; /** * 动态更改EasyPoi中控制列显示的值 * * @param columnName 需要转换的列属性名称 * @param target 默认true * @throws NoSuchFieldException * @throws IllegalAccessException */ public void hihdColumn(String columnName, Boolean target) throws Exception { if (t == null) { throw new ClassNotFoundException("TARGET OBJECT NOT FOUNT"); } if (StringUtils.isEmpty(columnName)) { throw new NullPointerException("COLUMN NAME NOT NULL"); } if (target == null) { target = true; } //获取目标对象的属性值 Field field = t.getClass().getDeclaredField(columnName); //获取注解反射对象 Excel excelAnnon = field.getAnnotation(Excel.class); //获取代理 InvocationHandler invocationHandler = Proxy.getInvocationHandler(excelAnnon); Field excelField = invocationHandler.getClass().getDeclaredField("memberValues"); excelField.setAccessible(true); Map memberValues = (Map) excelField.get(invocationHandler); memberValues.put("isColumnHidden", target); } }
使用类:
/** * 动态设置excel表头的 * @param dto */ public static void setExcelTitleHidden(PurchaseDetailPageDTO dto){ EasyPoiUtil<PurchaseDetailPageDTO> easyPoiUtil = new EasyPoiUtil<>(); easyPoiUtil.t = dto; String startEndSize = dto.getStartEndSize(); if(StringUtils.isNotEmpty(startEndSize)){ List<String> dtoTitleList = Lists.newArrayList(startEndSize.split(",")); List<String> allTitleName = SizeGroupTileGroupSortEnum.getAllTitileSizeName(); for(String titleName:allTitleName){ try { //这里需要根据db的属性,转换成info的属性 String infoPropertyName = SizeGroupEnum.getInfoPropertyByDBName(titleName); if(StringUtils.isNotEmpty(infoPropertyName)){ if(!dtoTitleList.contains(titleName)){ easyPoiUtil.hihdColumn(infoPropertyName, true); }else { easyPoiUtil.hihdColumn(infoPropertyName, false); } }else{ log.info("当前titleName为:[{}],未找到对应的对象属性。",titleName); } } catch (Exception e) { log.info("设置列隐藏转换失败:{}", e.getMessage()); e.printStackTrace(); } } } } /** * 系统导出的时候,动态隐藏表头的。 * @param dto 对象 * @param titleMap 表头是否隐藏的。为了解决比如第一条中显示,第二条中就隐藏。最终不一致问题 * @return */ public static void setExcelTitleHiddenFromOrderSys(PurchaseDetailPageDTO dto,Map<String,Boolean> titleMap ){ EasyPoiUtil<PurchaseDetailPageDTO> easyPoiUtil = new EasyPoiUtil<>(); easyPoiUtil.t = dto; String startEndSize = dto.getStartEndSize(); if(StringUtils.isNotEmpty(startEndSize)){ List<String> dtoTitleList = Lists.newArrayList(startEndSize.split(",")); List<String> allTitleName = SizeGroupTileGroupSortEnum.getAllTitileSizeName(); for(String titleName:allTitleName){ try { //这里需要根据db的属性,转换成info的属性 String infoPropertyName = SizeGroupEnum.getInfoPropertyByDBName(titleName); if(StringUtils.isNotEmpty(infoPropertyName)){ if(titleMap.containsKey(titleName) && !titleMap.get(titleName)){ //设置表头显示 easyPoiUtil.hihdColumn(infoPropertyName, false); }else{ easyPoiUtil.hihdColumn(infoPropertyName, true); } }else{ log.info("当前titleName为:[{}],未找到对应的对象属性。",titleName); } } catch (Exception e) { log.info("设置列隐藏转换失败:{}", e.getMessage()); e.printStackTrace(); } } } }
下一篇: jdk1.8根据Map的值进行排序的