一、场景
存在如下对象
class User{
int ID;
String name;
Integer age;
Double money;
}
对于 /userInfo
这样的get接口,有时候我们并不需要返回所有的用户属性,所以添加fields参数,类型为String数组。
满足如下几点规则:
二、规则
- 当
fields
为空,或不传,则返回所有属性 - 当
fields=[name,age]
等与属性一一对应的参数时,返回对应的属性 - 响应群,定义
profile = {name,age}
,则当fields = [profile]
时,返回name
和age
属性 - 去重,即便
fields=[profile,name,name]
,也只返回name
和age
属性 - 异常:
fields
获取了不存在的属性,比如weight
,则返回错误
三、核心流程
- 动态返回VO的字段
使用jackson的ObjectMapper、@JsonFilter,这里有坑:就算不过滤,也需要定义一下JsonFilter:SimpleBeanPropertyFilter.serializeAll() - 响应群的展开与去重
抽象成了Class FieldsFilter,后续只需要继承该类,并定义_querySettingAllowFieldSet,_rawFieldsGroupRoutes - 大小写insensitive
rawFieldsGroupRoutes.keySet().stream().anyMatch(field::equalsIgnoreCase)
四、流程
定义:
FP = 用户传来的fileds数组。判断为空,即为null或length == 0
FS = 所有符合条件的field参数的集合
五、核心代码
一、对fields参数进行预处理(1.2.3)
1. FieldsFilter
public class FieldsFilter {
Map<String, Set<String>> rawFieldsGroupRoutes;
HashSet<String> allRawFields;
public FieldsFilter(Map<String, Set<String>> rawFieldsGroupRoutes, HashSet querySettingAllowFieldSet) {
this.rawFieldsGroupRoutes = rawFieldsGroupRoutes;
this.allRawFields = querySettingAllowFieldSet;
}
public boolean isValid(String[] rawFields) {
return allRawFields.containsAll(Arrays.asList(rawFields));
}
/**
* 将参数的响应群展开,并且过滤掉重复项
*
* @param rawFields
* @return
*/
public FieldFilterResult doFilter(String[] rawFields) {
FieldFilterResult fieldFilterResult = new FieldFilterResult();
HashSet<String> allTargetFields = new HashSet<>();
HashSet<String> targetIncludeFieldGroup = new HashSet<>();
for (String field : rawFields) {
// 忽略大小写
if (rawFieldsGroupRoutes.keySet().stream().anyMatch(field::equalsIgnoreCase)) {
allTargetFields.addAll(rawFieldsGroupRoutes.get(field));
targetIncludeFieldGroup.add(field);
} else {
// 这里也要找到他的group
for (Map.Entry<String, Set<String>> entry : rawFieldsGroupRoutes.entrySet()) {
if (entry.getValue().stream().anyMatch(field::equalsIgnoreCase)) {
targetIncludeFieldGroup.add(entry.getKey());
}
}
allTargetFields.add(field);
}
}
fieldFilterResult.setAllTargetFields(allTargetFields);
fieldFilterResult.setTargetIncludeFieldGroup(targetIncludeFieldGroup);
return fieldFilterResult;
}
}
2. SettingFieldsFilter
public class SettingFieldsFilter extends FieldsFilter {
final static private HashSet _querySettingAllowFieldSet = new HashSet(Arrays.asList("notif", "preference", "learning", "profile", "triggerCondition", "triggerTime", "outfit", "showCountDown", "showFinishedCard", "openAutoPronunciation", "pronType", "dailyTargetNum", "currentWordBookCode", "avatarUrl", "nickName"));
final static private Map<String, Set<String>> _rawFieldsGroupRoutes = Map.of("notif", Set.of("triggerCondition", "triggerTime"), "preference", Set.of("outfit", "showCountDown", "showFinishedCard", "openAutoPronunciation", "pronType"), "learning", Set.of("dailyTargetNum", "currentWordBookCode"), "profile", Set.of("nickName", "avatarUrl"));
private final static SettingFieldsFilter Instance = new SettingFieldsFilter(_rawFieldsGroupRoutes, _querySettingAllowFieldSet);
public static SettingFieldsFilter getInstance() {
return Instance;
}
private SettingFieldsFilter(Map<String, Set<String>> _rawFieldsGroupRoutes, HashSet _querySettingAllowFieldSet) {
super(_rawFieldsGroupRoutes, _querySettingAllowFieldSet);
}
}
3. FieldFilterResult
@Data
public class FieldFilterResult {
HashSet<String> allTargetFields;
HashSet<String> TargetIncludeFieldGroup;
}
二、 去掉无用的VO属性
4. JsonUtil
@Slf4j
public class JsonUtil {
@SneakyThrows
public static JSONObject defaultFilter(String filterName, Object sourceObject) {
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter(filterName, SimpleBeanPropertyFilter.serializeAll());
String s = new ObjectMapper().setFilterProvider(filterProvider).writeValueAsString(sourceObject);
// 转成jsonObject,方便封装统一返回格式
JSONObject jsonObject = JSONObject.parseObject(s);
return jsonObject;
}
/**java
* 动态只留下bean的某些属性
*
* @param filterName Bean的注解@JsonFilter("filterName")
* @param sourceObject Bean的实例
* @param exceptPropertyArray 需要保留的属性
* @return
* @throws JsonProcessingException
*/
@SneakyThrows
public static JSONObject jsonFilter(String filterName, Object sourceObject, String... exceptPropertyArray) {
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter(filterName,
SimpleBeanPropertyFilter.filterOutAllExcept(exceptPropertyArray));
String s = new ObjectMapper().setFilterProvider(filterProvider).writeValueAsString(sourceObject);
JSONObject jsonObject = JSONObject.parseObject(s);
return jsonObject;
}
public static JSONObject jsonFilter(String filterName, Object sourceObject, Set<String> exceptPropertySet) {
return JsonUtil.jsonFilter(filterName, sourceObject, exceptPropertySet.toArray(new String[exceptPropertySet.size()]));
}
}
六、附录
PUT修改setting