Spring Boot通过AOP的方式实现RESTful根据请求参数中的fields返回嵌套对象字段而且需要保证对象为null值时正常返回并写出使用案例 其中fields是请求参数
中的一个字符串,格式为用逗号分隔的字段名。
首先,我们需要定义一个注解@Fields,用于标注哪些方法需要进行字段过滤。注解中包含一个属性value,表示需要返回的字段名。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Fields {
String value();
}
然后,我们定义一个切面类,用于拦截带有@Fields注解的方法,并根据请求参数中的fields参数进行字段过滤。
@Aspect
@Component
public class FieldsAspect {
@Autowired
private ObjectMapper objectMapper;
@Around("@annotation(fields)")
public Object filterFields(ProceedingJoinPoint joinPoint, Fields fields) throws Throwable {
Object result = joinPoint.proceed();
if (result == null) {
return null;
}
String fieldsParam = ServletRequestUtils.getStringParameter(
RequestContextHolder.getRequestAttributes().getRequest(), "fields", "");
if (StringUtils.isEmpty(fieldsParam)) {
return result;
}
Set<String> fieldsSet = new HashSet<>(Arrays.asList(fieldsParam.split(",")));
if (fieldsSet.isEmpty()) {
return result;
}
if (result instanceof Collection) {
List<Map<String, Object>> resultList = new ArrayList<>();
for (Object obj : (Collection) result) {
Map<String, Object> resultMap = objectMapper.convertValue(obj, Map.class);
filterFields(resultMap, fieldsSet);
resultList.add(resultMap);
}
return resultList;
} else {
Map<String, Object> resultMap = objectMapper.convertValue(result, Map.class);
filterFields(resultMap, fieldsSet);
return resultMap;
}
}
private void filterFields(Map<String, Object> map, Set<String> fieldsSet) {
Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> entry = iterator.next();
if (entry.getValue() instanceof Map) {
filterFields((Map<String, Object>) entry.getValue(), fieldsSet);
} else if (entry.getValue() instanceof Collection) {
List<Map<String, Object>> resultList = new ArrayList<>();
for (Object obj : (Collection) entry.getValue()) {
Map<String, Object> resultMap = objectMapper.convertValue(obj, Map.class);
filterFields(resultMap, fieldsSet);
resultList.add(resultMap);
}
entry.setValue(resultList);
} else if (!fieldsSet.contains(entry.getKey())) {
iterator.remove();
}
}
}
}
在切面类中,我们使用了Spring Boot自带的ObjectMapper类,将对象转换为Map,方便进行字段过滤。filterFields方法用于递归遍历Map中的所有字段,并根据fields参数进行过滤。
最后,我们在需要进行字段过滤的方法上添加@Fields注解即可。
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users")
@Fields("id,username,profile(id,name)")
public List<User> getUsers() {
return userService.getUsers();
}
}
在上面的例子中,我们希望返回用户的id、username和profile中的id和name字段。如果profile为null,则正常返回null值。如果请求参数中没有fields参数,则返回所有字段。如果fields参数为空,则也返回所有字段。
使用时,我们可以通过GET请求访问/users接口,并在请求参数中添加fields参数,如:/users?fields=id,username,profile(id,name)。
$ curl -X GET http://localhost:8080/users?fields=id,username,profile(id,name)
[ {
"id" : 1,
"username" : "user1",
"profile" : {
"id" : 1,
"name" : "profile1"
}
}, {
"id" : 2,
"username" : "user2",
"profile" : {
"id" : 2,
"name" : "profile2"
}
} ]
原文地址: https://www.cveoy.top/t/topic/bgh6 著作权归作者所有。请勿转载和采集!