【开源之路】温蒂、一次简单的尝试

1,024 阅读4分钟

干点正事吧,巴巴托斯

##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~