java通过反射和注解,将一个对象转换成另一个对象

1,680 阅读2分钟

本文章介绍java通过反射和注解,将一个对象转换成另一个对象,从而屏蔽掉一下敏感字段和字段名

枚举对象:

@Getter
public enum InoroutEnum {
    IN,//表示数据只进不出
    OUT,//表示数据只出不进
    IN_OUT//表示数据可进可出
}

注解对象:

@Target({ElementType.TYPE,ElementType.FIELD,ElementType.PARAMETER,ElementType.CONSTRUCTOR,ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    InoroutEnum value() default InoroutEnum.IN_OUT;//默认数据可进可出
    String fieldName() default "";
}

对象A:对外对象,即使该对象泄露,也不会造成真实字段名字泄露

@Data
public class UserOutput implements Serializable {
    private String id;
    private String account;
    private String password;
    private Date createTime;
    private Date updateTime;
}

对象B:对内对象

@Data
@MyAnnotation
public class User implements Serializable {
    @MyAnnotation(fieldName = "id")
    private String aaId;
    @MyAnnotation(fieldName = "account")
    private String aaAccount;
    @MyAnnotation(value = InoroutEnum.IN,fieldName = "aaPassword")
    private String aaPassword;
    @MyAnnotation(value = InoroutEnum.OUT,fieldName = "createTime")
    private Date aaCreateTime;
    @MyAnnotation(value = InoroutEnum.OUT,fieldName = "updateTime")
    private Date aaUpdateTime;
}

转换方法:

public class EntityUtils {

    public static <T1, T2> T2 copyDataOnAnnotation(T1 sourceObj, Class<T2> clazz) {
        //获取源数据的类
        Class<?> clazz1 = sourceObj.getClass();
        //创建一个目标数据对象
        T2 targetObj = EntityUtils.getInstance(clazz);
        //获取两个类字段集合
        Field[] fields1 = clazz1.getDeclaredFields();
        Field[] fields2 = clazz.getDeclaredFields();

        MyAnnotation an = clazz1.getAnnotation(MyAnnotation.class);
        if(an != null){
            toOut(sourceObj,targetObj,fields1,fields2);
        }else {
            toIn(sourceObj,targetObj,fields1,fields2);
        }

        return targetObj;
    }

    private static <T1, T2> void toIn(T1 sourceObj, T2 targetObj, Field[] fields1, Field[] fields2){
        for (Field f2 : fields2) {
            MyAnnotation an = f2.getAnnotation(MyAnnotation.class);
            if(an != null && (an.value().equals(InoroutEnum.IN)||an.value().equals(InoroutEnum.IN_OUT))){
                String fieldName = an.fieldName();
                for (Field f1 : fields1) {
                    if (fieldName.equalsIgnoreCase(f1.getName())) {
                        //复制字段
                        copyFieldValueWithOutName(sourceObj, targetObj, f1, f2);
                    }
                }
            }
        }
    }

    private static <T1, T2> void toOut(T1 sourceObj, T2 targetObj, Field[] fields1, Field[] fields2){
        for (Field f1 : fields1) {
            MyAnnotation an = f1.getAnnotation(MyAnnotation.class);
            if(an != null && (an.value().equals(InoroutEnum.OUT)||an.value().equals(InoroutEnum.IN_OUT))){
                String fieldName = an.fieldName();
                for (Field f2 : fields2) {
                    if (fieldName.equalsIgnoreCase(f2.getName())) {
                        //复制字段
                        copyFieldValueWithOutName(sourceObj, targetObj, f1, f2);
                        break;
                    }
                }
            }
        }
    }
    
    private static <T1, T2> void copyFieldValueWithOutName(T1 sourceObj, T2 targetObj, Field field1, Field field2) {
        try {
            if (equalFieldsType(field1, field2)) {
                //获取源数据字段的值
                field1.setAccessible(true);
                Object value = field1.get(sourceObj);
                if(value != null){
                    //给目标数据字段赋值
                    field2.setAccessible(true);
                    //数据字段类型为字符串是去两端空格,也可以对数据进行一些自定义的修改
                    if(value instanceof String){
                        String str = ((String)value).trim();
                        if(str.length()>0){
                            field2.set(targetObj, str);
                        }
                    }else {
                        field2.set(targetObj, value);
                    }
                    //访问权限还原
                    field2.setAccessible(false);
                }
                field1.setAccessible(false);
            }
        } catch (IllegalAccessException e) {
            //访问权限还原
            field2.setAccessible(false);
            field1.setAccessible(false);
        }
    }
    
}

此时就可以通过

User user = EntityUtils.copyDataOnAnnotation(userOutput,User.class);

UserOutput userOutput = EntityUtils.copyDataOnAnnotation(user,UserOutput.class);

在两个对象之间相互转换