【開源之路】溫蒂、一次簡單的嘗試

干點正事吧,巴巴托斯

##V1.01 2020/11/23 溫蒂類資訊對比處理工具包,目前可以用來對比更新前後的類資訊。


weed的github地址

因為工作中需要進行數據對比,所以經常需要在程式碼的增刪改查操作中嵌入一些對比類。我們都知道開閉原則:對修改關閉,對擴展開放。所以每次修改的時候都需要新增一個類,然後再通知用到了原始類的同事一起同步修改程式碼。如果方法涉及到的模組少,還可以比較輕鬆的解決,但是如果用到的地方比較多,那需要協調的地方也會增多。

偷懶是人類文明發展的驅動力

於是,為了解決新增數據對比方法的苦惱,也為了盡量使用少侵入的模式,在工作之餘,我也開始思考是不是把放進去的程式碼再抽出來。思考再三,決定用註解模式解決這個問題,於是乎,就有了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~

我的微信

在這裡插入圖片描述