在Spring Boot中的AOP和反射的方式实现RESTful动态过滤嵌套对象字段且无论是否为null值只根据请求参数需要都要返回并给出请求案例包含url
实现过程:
- 创建一个注解@DynamicFilter,用于标识需要进行动态过滤的方法或类。
- 使用AOP拦截被@DynamicFilter注解标识的方法或类,获取请求参数中的过滤字段,并使用反射对对象进行过滤,返回过滤后的结果。
- 对于嵌套对象,使用递归的方式进行过滤。
代码实现:
- 创建注解@DynamicFilter
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface DynamicFilter {
}
- 使用AOP拦截被@DynamicFilter注解标识的方法或类,并进行动态过滤
@Component
@Aspect
public class DynamicFilterAspect {
@Autowired
private HttpServletRequest request;
@Around("@annotation(com.example.demo.annotation.DynamicFilter) || @within(com.example.demo.annotation.DynamicFilter)")
public Object dynamicFilter(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = joinPoint.proceed();
// 获取请求参数中的过滤字段
String fields = request.getParameter("fields");
if (StringUtils.isBlank(fields)) {
return result;
}
// 对结果进行过滤
String[] fieldArray = fields.split(",");
List<String> fieldList = Arrays.asList(fieldArray);
if (fieldList.size() > 0) {
if (result instanceof List) {
List<Object> resultList = new ArrayList<>();
for (Object obj : (List) result) {
Object filtered = filterObject(obj, fieldList);
resultList.add(filtered);
}
return resultList;
} else {
return filterObject(result, fieldList);
}
}
return result;
}
private Object filterObject(Object obj, List<String> fieldList) {
try {
// 使用反射获取对象的所有属性
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String fieldName = field.getName();
// 如果属性是对象,则对其进行递归过滤
if (field.getType().getClassLoader() != null) {
Object nestedObj = field.get(obj);
if (nestedObj != null) {
Object filteredNestedObj = filterObject(nestedObj, fieldList);
field.set(obj, filteredNestedObj);
}
} else {
// 对属性进行过滤
if (!fieldList.contains(fieldName)) {
field.set(obj, null);
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return obj;
}
}
- 在Controller中使用@DynamicFilter注解标识需要进行动态过滤的方法
@RestController
@RequestMapping("/users")
@DynamicFilter
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
@GetMapping
public List<User> getUsers() {
return userService.getUsers();
}
}
- 发送请求
请求案例:
获取用户列表,只返回id和name字段
GET http://localhost:8080/users?fields=id,name
返回结果:
[
{
"id": 1,
"name": "Alice"
},
{
"id": 2,
"name": "Bob"
}
]
获取用户详情,返回id、name和address字段,同时address只返回province和city字段
GET http://localhost:8080/users/1?fields=id,name,address.province,address.city
返回结果:
{
"id": 1,
"name": "Alice",
"address": {
"province": "Beijing",
"city": "Haidian"
}
}
原文地址: https://www.cveoy.top/t/topic/bgH9 著作权归作者所有。请勿转载和采集!