【開源之路】溫蒂、一次簡單的嘗試
干點正事吧,巴巴托斯
##V1.01 2020/11/23 溫蒂類資訊對比處理工具包,目前可以用來對比更新前後的類資訊。
因為工作中需要進行數據對比,所以經常需要在程式碼的增刪改查操作中嵌入一些對比類。我們都知道開閉原則:對修改關閉,對擴展開放。所以每次修改的時候都需要新增一個類,然後再通知用到了原始類的同事一起同步修改程式碼。如果方法涉及到的模組少,還可以比較輕鬆的解決,但是如果用到的地方比較多,那需要協調的地方也會增多。
偷懶是人類文明發展的驅動力
於是,為了解決新增數據對比方法的苦惱,也為了盡量使用少侵入的模式,在工作之餘,我也開始思考是不是把放進去的程式碼再抽出來。思考再三,決定用註解模式解決這個問題,於是乎,就有了weed這一個工具的出現。
當然,現在只是一塊不到一千行程式碼,解決不了絕大多數問題的小工具包。
目前可以公開的情報
-
1、contrastSourceFundByBean方法專門用來對比兩個類對象的資訊,類中可以包含任意類 ,但是要記得在類中類加註解。
-
2、getListupdateOnly方法專門用來對比兩個集合的資訊,集合中不可包含類,只能是純基礎對象的集合,以後會慢慢更新。
-
3、judgeArray方法用來比較兩個數組之間的資訊,數組可以是任意類。
-
4、註解默認都是可以不加的,需要加的時候是需要用到的時候。
-
5、這個項目是因為日常給後台人員提供資訊對比類的時候想到的,就寫出來應該有一點用吧?大家就不用重複造輪子了。
-
6、weed代表著我第一個十連出了溫蒂,第二個十連就出了可莉,第三個十連出了盧姥爺, 其實我挺難受的,香菱60出了可莉,可莉70、武器也70,一整套魔女的時候出了盧姥爺,哎。。。不想要火C了
設計思路
既然決定使用少侵入的模式,那麼使用註解的方法就是一個不錯的解決方式。
因為網上都有如何使用自定義註解的教程,我這裡也就不再班門弄斧,主要展示一下我大概的設計思路。
@Target(java.lang.annotation.ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckField {
/**
* 欄位最小長度
*/
int minlen() default 0;
/**
* 欄位最大長度
*/
int maxlen() default Short.MAX_VALUE;
/**
* 欄位是否需要校驗
*/
Check check() default Check.unchecks;
/**
* 欄位名(用於後期獲取)
*/
String name() default "";
/**
* 欄位類型
*/
Check type() default Check.basics;
}
校驗欄位枚舉類,這裡也主要體現的是一種思路,也是目前提供的解決方案:無論你是基礎類型,還是對象、數組,亦或是集合,目前都有辦法進行對比,也能拿到所需要的數據。
public enum Check {
/**
* 檢查
*/
checks,
/**
* 不檢查
*/
unchecks,
/**
* 對象
*/
beans,
/**
* 數組
*/
arrays,
/**
* 集合
*/
sets,
/**
* 基礎數據類型
*/
basics,
}
最後就是其中的一個方法了,看過我過去文章的同學能夠發現,這個方法是在之前的基礎上進行了改動,加大了對註解的應用。
/**
* @param oldBean 原始數據
* @param newBean 新數據
* @return 根據傳入的對象返回變化值
*/
public static String contrastSourceFundByBean(Object oldBean, Object newBean) {
StringBuilder str = new StringBuilder();
Object pojo1 = (Object) oldBean;
Object pojo2 = (Object) newBean;
if (!(pojo1.getClass()==pojo2.getClass())){
return "對象類型不一致";
}
try {
Class clazz = pojo1.getClass();
Field[] fields = pojo1.getClass().getDeclaredFields();
Class<CheckField> chkField = CheckField.class;
int i = 1;
for (Field field : fields) {
CheckField cf = field.getAnnotation(chkField);
if (field.isAnnotationPresent(chkField)) {
//獲取欄位是否填寫(不校驗,空,非空)
if (cf.check().equals(Check.unchecks)&&cf.type().equals(Check.basics)) {
continue;
}
//同意對private欄位取值
field.setAccessible(true);
Object fValue = null;
try {
fValue = field.get(pojo1);
} catch (Exception e) {
return "獲取欄位值異常!";
}
//獲取最大值
int max = cf.maxlen();
//獲取配置最小值
int min = cf.minlen();
int flength = 0;
//為空時判斷
if (fValue != null) {
try {
String strVal = fValue.toString();
flength = strVal.length();
} catch (Exception e) {
}
}
if (max < flength) {
return cf.name() + "長度不能大於" + max + "!";
}
if (min > flength) {
return cf.name() + "長度不能小於" + min + "!";
}
}
//獲取對象具體資訊
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
Method getMethod = pd.getReadMethod();
//對象間比較
Object o1 = getMethod.invoke(pojo1);
Object o2 = getMethod.invoke(pojo2);
if (o2 == null) {
continue;
} else if (o1 == null) {
if (filterCheck(cf)) {
continue;
}
String getName = cf.name();
str.append(getName).append(":新增值:").append(o2);
i++;
} else {
if (filterCheck(cf)){
String otto = contrastSourceFundByBean(o1, o2);
String getName = cf.name();
str.append("|").append(getName).append("{").append("[").append(otto).append("]").append("}");
}else if(filterChecksets(cf)){
String list =getListupdateOnly((List)o1,(List)o2);
String getName = cf.name();
str.append("|").append(getName).append("{").append("[").append(list).append("]").append("}");
}else if(filterCheckarray(cf)){
String array =judgeArray(o1,o2);
String getName = cf.name();
str.append("|").append(getName).append("{").append("[").append(array).append("]").append("}");
}else{
if (!o1.equals(o2)) {
if (filterCheck(cf)) {
continue;
}
if (i != 1) {
str.append("|");
}
String getName = cf.name();
str.append(getName).append(":舊值:").append(o1).append(",新值:").append(o2);
i++;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return str.toString();
}
/**
* 對傳入的狀態進行判斷
* @param cf
* @return
*/
private static boolean filterChecksets(CheckField cf){
return cf.type().equals(Check.sets);
}
private static boolean filterCheck(CheckField cf){
return cf.type().equals(Check.beans);
}
private static boolean filterCheckarray(CheckField cf){
return cf.type().equals(Check.arrays);
}
}
然後對方法進行一下小小的測試,輸出如下:
其餘的部分,大家去我的GitHub地址看看吧~,在給大家發一遍
weed的github地址
希望能夠一起完善weed~
我的微信