使用EasyPoi根據許可權動態匯出列——反射實現
阿新 • • 發佈:2019-12-31
前言: 前段時間,因為業務需求需要根據使用者角色動態匯出excel,不同角色看到的列不同。以前用到的方法基本是(或者有其他土方法),建立多個實體類,每個實體類對應的列不同,以此來實現動態匯出,但顯然這是個笨方法,雖然省時省力,但好像總覺得哪裡不對。正片開始
easypoi連結: EasyPoi官方檔案
我們使用的註解版的匯出 @Excel
,官方檔案中說明很詳細,預設大家都會用,不會用的,copy一下官網的,跑一下,調一下就行了。
舉個栗子:
@Data
@ExcelTarget("TestExcle")
public class TestExcle implements Serializable {
private static final long serialVersionUID = 4152437113488964399L;
@Excel(name = "名稱")
private String name;
@Excel(name = "年齡",isColumnHidden = true))
private String age;
@Excel(name = "學校")
private String school;
@Excel(name = "狀態",replace = { "畢業_1","在校_2" })
private Integer status;
}
複製程式碼
我們需要用到的是EasyPoi官方提供的這個屬性 isColumnHidden
屬性 | 型別 | 預設值 | 功能 |
---|---|---|---|
isColumnHidden | boolean | false | 匯出隱藏列 |
// 點選@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);
}
複製程式碼
然後在需要匯出的資料中更改對應角色能看到的列
//資料集合,一般都是從資料庫中獲取,這裡仿造資料
List<TestExcle> list = new ArrayList<>();
list.add(...);
...
for (TestExcle item : list){
// roles 為當前使用者登入的許可權列表,各個系統都不一樣,但都能獲得
// 如果是學生 ST 則隱藏 easyPoiUtil.hihdColumn("age",true);
if (roles.contains('ST')) {
EasyPoiUtil<ProductOrder> easyPoiUtil = new EasyPoiUtil<>();
easyPoiUtil.t = item;
try {
easyPoiUtil.hihdColumn("age",true);
} catch (Exception e) {
log.info("列隱藏轉換失敗:{}",e.getMessage());
e.printStackTrace();
}
}
// 如果是教師 TC 則顯示 easyPoiUtil.hihdColumn("age",false);
if (roles.contains('TC')) {
EasyPoiUtil<ProductOrder> easyPoiUtil = new EasyPoiUtil<>();
easyPoiUtil.t = item;
try {
easyPoiUtil.hihdColumn("age",false);
} catch (Exception e) {
log.info("列隱藏轉換失敗:{}",e.getMessage());
e.printStackTrace();
}
}
}
複製程式碼
匯出之後,對應的角色就可以看到對應的列。如果有多個列表的話就多次呼叫即可
easyPoiUtil.hihdColumn("age",true);
easyPoiUtil.hihdColumn("school",true);
複製程式碼
大大的完結!
日常記錄開發小技巧