自定义注解+反射提取对象到map中
一、问题:有时候我们与第三方接口对接传参时,需要将对象里的字段和值以map形式传给别人,此时可以借助其他的工具类,但是我个人用起来不太灵活,还会把多余的字段传给别人,因此我们自己动手搞一套
二、思路:
1.别人的字段定义和我们定义的名称可能不一样,字段名称需要能够自定义;
2.要能够忽略对象里面的字段;
3.要能支持对字段做简单的非空校验;
4.复杂的pojo需要递归,这里只考虑简单的pojo对象。
三、步骤:
1.定义字段的注解
/**
* 字段转化适配
*
* @author xuzhangxing
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldMask {
// 指定新的字段名,如果不指定就取原字段名
String value() default "";
// 是否忽视这个字段
boolean ignore() default false;
// 字段为空时是否仍然需要放入map中,默认是不放入
boolean nullIgnore() default false;
// 是否必传,如果设置true 值为null时会抛出异常
boolean required() default false;
}
2.通过反射转成map
import java.lang.reflect.Field;
import java.util.*;
/**
* 字段转map 且能够自定义字段名称或者直接忽视该字段
*
* @author xuzhangxing
*/
public final class ParamMapUtil {
public static List<Field> getAllFields(Class<?> cls) {
final List<Field> allFields = new ArrayList<>();
Class<?> currentClass = cls;
while (currentClass != null) {
final Field[] declaredFields = currentClass.getDeclaredFields();
Collections.addAll(allFields, declaredFields);
currentClass = currentClass.getSuperclass();
}
return allFields;
}
public static Map<String, Object> generateMap(Object target) {
Map<String, Object> result = new HashMap<>();
if (target == null) {
return result;
}
List<Field> allFields = getAllFields(target.getClass());
for (Field field : allFields) {
Object fieldObj;
field.setAccessible(Boolean.TRUE);
try {
fieldObj = field.get(target);
} catch (IllegalAccessException e) {
throw new RuntimeException("ParamMapUtil 获取field 值异常-->" + e.getMessage());
} finally {
field.setAccessible(Boolean.FALSE);
}
FieldMask[] fieldMasks = field.getAnnotationsByType(FieldMask.class);
if (fieldMasks.length > 0) {
FieldMask fieldMask = fieldMasks[0];
if (fieldMask.ignore()) {
continue;
}
// 如果需要非空校验且该字段为空时,抛出异常
if (fieldMask.required() && fieldObj == null) {
throw new RuntimeException("参数" + field.getName() + "必填");
}
// 字段为空时,是否还放入map中
if (fieldObj == null && fieldMask.nullIgnore()) {
continue;
}
// 是否重命名了
String fieldName = fieldMask.value();
if (fieldName == null || fieldName.length() < 1) {
result.put(field.getName(), fieldObj);
} else {
result.put(fieldName, fieldObj);
}
} else {
// 默认所有字段都加进去,需要忽略字段时,标注FieldMask注解且ignore设置成true
result.put(field.getName(), fieldObj);
}
}
return result;
}
}
三、测试
1 pojo
/** * @author xuzhangxing */ public class UserDTO { @FieldMask("Name") private String name; @FieldMask(required = true) private String age; @FieldMask(nullIgnore = true) private String height; private String email; @FieldMask(ignore = true) private String password; // ...geter setter }
2. 方法调用:
public static void main(String[] args) { UserDTO userDTO = new UserDTO(); userDTO.setName("xzx"); userDTO.setAge("12"); userDTO.setEmail("123@qq.com"); userDTO.setPassword("123456"); Map<String, Object> generateMap = ParamMapUtil.generateMap(userDTO); System.out.println(generateMap); }
3.结果:
{age=12, email=123@qq.com, Name=xzx}
四、总结
1、map中的字段可以通过注解控制字段是否重命名,字段是否直接忽略,字段为空是否抛出异常,字段为空是否不放入map
2、注意如果不标注注解,默认是放入map中