Spring Boot通过AOP的方式实现RESTful根据请求参数中的fields返回嵌套对象字段而且需要保证对象为null值时正常返回并写出使用案例
- 实现方式:
首先,在定义返回对象的类中,需要添加一个静态的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) {
// ...
}
}
- 使用案例:
假设有一个用户类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"
}
]
}
原文地址: https://www.cveoy.top/t/topic/bghn 著作权归作者所有。请勿转载和采集!