【Java】使用BeanUtils的copyProperties含過濾屬性引數(ignoreProperties)方法的應用
阿新 • • 發佈:2018-12-24
問題
需求:
來源於更新資料的一個介面,要求可以修改類中某一些欄位的值,可以僅修改一部分,沒有修改的欄位預設為不修改。
例中使用了一個檢視層的包裝物件vo,包含了需要更新的目標底層實體po的一個擴充套件子類(假設這個物件就是poi),和一些其他的無關屬性。從前端獲取到已經改好資料的vo後,需要儲存已經更新的po。
思路
使用BeanUtils.copyProperties(source, target, ignoreProperties)
這個方法,將源的屬性,過濾掉一部分屬性名,複製到目標上
ignoreProperties的宣告型別是String… ignoreProperties
為獲取一個能得到屬性欄位名的陣列,需要用反射機制
過程
- 新建一個po物件,使用copyProperties複製poi已有值的屬性到po裡
- 設計一個方法獲取不為空的欄位名陣列,供過濾功能的呼叫
- 再使用copyProperties的過濾過載方法,將原po複製到新po
反射獲取欄位名的實現
目標是獲取不為空的欄位
/**
* 用反射機制來得到vo中itemsCustom的不為空的屬性
* @param objClass 為目標的Class物件,呼叫時為實體類的Class物件,並不是vo
* @param vo
* @return
* @throws ClassNotFoundException
*/
private String[] getProperties(Class objClass,ItemsQueryVo vo) throws ClassNotFoundException {
//得到ItemsCustom的class類
ItemsCustom obj = vo.getItemsCustom();
List<String> properties = new ArrayList<>();
//遍歷欄位
try {
//使用getDeclaredFields()方法而不是getFields()的原因是
//該方法明確的只需要匹配objClass類的欄位,
//不使用obj.getClass()的原因也是如此,因為obj的類繼承自objClass的類
for(Field field: objClass.getDeclaredFields()) {
//使其可以訪問private
field.setAccessible(true);
//如果欄位不為空
if(field.get(obj)!=null)
properties.add(field.getName());
}
}catch (Exception e) {
/*
* 如果獲取出了錯,return null的方法相當於
* 源的所有欄位都是空的,目標在外部會被完全覆蓋掉,這次更新相當於無效了
*/
return null;
}
//轉陣列
String[] propers = new String[properties.size()];
return properties.toArray(propers);
}
上段程式碼就實現了過程中的第二步
利用上述程式碼的簡單方法可以寫更多類似且更有通用性的工具