自定义注解+反射提取对象到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中

posted on 2022-03-23 22:47  _掌心  阅读(438)  评论(0编辑  收藏  举报