1. 实现方式:

首先,在定义返回对象的类中,需要添加一个静态的Map类型的字段,用于存储需要返回的字段名和对应的getter方法。

public class User {
    private Long id;
    private String name;
    private List<Address> addresses;

    public static Map<String, Function<User, Object>> fieldMap = new HashMap<>();

    static {
        fieldMap.put("id", User::getId);
        fieldMap.put("name", User::getName);
        fieldMap.put("addresses", User::getAddresses);
    }

    // getter/setter methods
}

然后,定义一个切面类,用于处理请求参数中的fields字段,并根据该字段返回需要的数据。

@Aspect
@Component
public class FieldsAspect {

    @Around("@annotation(fields)")
    public Object processFields(ProceedingJoinPoint joinPoint, Fields fields) throws Throwable {
        Object result = joinPoint.proceed();
        if (fields == null || fields.value().length == 0) {
            return result;
        }
        if (result == null) {
            return null;
        }
        if (result instanceof List) {
            List<Map<String, Object>> resultList = new ArrayList<>();
            for (Object obj : (List) result) {
                resultList.add(getFields(obj, fields.value()));
            }
            return resultList;
        } else {
            return getFields(result, fields.value());
        }
    }

    private Map<String, Object> getFields(Object obj, String[] fields) {
        Map<String, Object> resultMap = new HashMap<>();
        for (String field : fields) {
            Function<Object, Object> getter = getFieldGetter(obj, field);
            if (getter != null) {
                resultMap.put(field, getter.apply(obj));
            }
        }
        return resultMap;
    }

    private Function<Object, Object> getFieldGetter(Object obj, String fieldName) {
        Class<?> clazz = obj.getClass();
        Method method = null;
        try {
            method = clazz.getMethod("get" + StringUtils.capitalize(fieldName));
        } catch (NoSuchMethodException e) {
            return null;
        }
        return (o) -> {
            try {
                return method.invoke(o);
            } catch (IllegalAccessException | InvocationTargetException e) {
                return null;
            }
        };
    }
}

最后,在需要使用该功能的地方,可以通过在方法上加上@Fields注解,指定需要返回的字段。

@RestController
public class UserController {

    @GetMapping("/users")
    @Fields("id,name")
    public List<User> getUsers() {
        // ...
    }

    @GetMapping("/users/{id}")
    @Fields("id,name,addresses")
    public User getUserById(@PathVariable Long id) {
        // ...
    }
}
  1. 使用案例:

假设有一个用户类User,其中包含了用户的基本信息和地址信息,如下所示:

public class User {
    private Long id;
    private String name;
    private List<Address> addresses;

    // getter/setter methods
}

为了实现根据请求参数中的fields返回嵌套对象字段的功能,需要先在User类中定义一个静态的Map类型的字段,用于存储需要返回的字段名和对应的getter方法。

public static Map<String, Function<User, Object>> fieldMap = new HashMap<>();

static {
    fieldMap.put("id", User::getId);
    fieldMap.put("name", User::getName);
    fieldMap.put("addresses", User::getAddresses);
}

然后,在需要使用该功能的方法上,可以通过在方法上加上@Fields注解,指定需要返回的字段。

@RestController
public class UserController {

    @GetMapping("/users")
    @Fields("id,name")
    public List<User> getUsers() {
        // ...
    }

    @GetMapping("/users/{id}")
    @Fields("id,name,addresses")
    public User getUserById(@PathVariable Long id) {
        // ...
    }
}

最后,在请求该接口时,只需要在请求参数中加上fields字段即可返回指定的字段,如下所示:

GET /users?fields=id,name HTTP/1.1
Host: localhost:8080
HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "id": 1,
        "name": "Tom"
    },
    {
        "id": 2,
        "name": "Jerry"
    }
]
GET /users/1?fields=id,name,addresses HTTP/1.1
Host: localhost:8080
HTTP/1.1 200 OK
Content-Type: application/json

{
    "id": 1,
    "name": "Tom",
    "addresses": [
        {
            "province": "Guangdong",
            "city": "Shenzhen",
            "street": "Nanshan District"
        }
    ]
}
Spring Boot通过AOP的方式实现RESTful根据请求参数中的fields返回嵌套对象字段而且需要保证对象为null值时正常返回并写出使用案例

原文地址: https://www.cveoy.top/t/topic/bghn 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录