本文章介绍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);
在两个对象之间相互转换