这个能力面向的场景:有些业务使用的是一个复杂的大接口,返回的VO中字段很多,但是不同调用方需要的字段可能是不一样的,
可能大多数字段在其他场景下并不需要。
解法一 拆分接口
这种解法过于理想,你把接口拆分开,还需要上游和你打配合,除非项目整体在搞大优化,不然和上游的沟通,排期,对接会花费很多精力。另外拆分后的接口需要返回不同的VO,也比较坑爹。
解法二 创建很多实体类
还有一种解法就是创建很多实体类,根据不同的场景将查询结果转换为不同的VO,这种解法太死板,如果上游忽然需要另一个字段,你还要吭哧吭哧来改对应VO,修改一个赋值,然后再来一次发布,十分沉重。
解法三 使用序列化过滤器
这种接法要求你要有一个配置中心,实在不行放在yaml文件里也可,这样灵活度受限,但还是比上一种好(但一般有这种需求的团队应该也是有配置中心的),只要在配置中心声明不同场景下的配置,在序列化过滤器中指定当前属性是否需要被write。
这种方式还要求在对应的VO上指定序列化过滤器。
@Configuration
public class CommonWebMvcConfigurer implements WebMvcConfigurer {
// 获取配置的bean
@Autowired
private ApolloProperties apolloProperties;
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
ObjectMapper objectMapper = new ObjectMapper();
//忽略无法识别字段
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//忽略空值
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
FilterProvider filterProvider = new SimpleFilterProvider().addFilter("myFilter",
new MyPropertyFilter(apolloProperties));
objectMapper.setFilterProvider(filterProvider);
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(objectMapper);
converters.add(converter);
}
public static class MyPropertyFilter extends SimpleBeanPropertyFilter {
private ApolloProperties apolloProperties;
public MyPropertyFilter(ApolloProperties apolloProperties) {
this.apolloProperties = apolloProperties;
}
@Override
protected boolean include(PropertyWriter writer) {
String propertyName = writer.getFullName().getSimpleName();
// 获取配置 当前请求对应的配置 ["id", "name"]
Set<String> useProperty = apolloProperties.getConfig();
return useProperty.contains(propertyName);
}
}
@Data
@JsonFilter("myFilter")
public static class SimpleBeanVO {
private String id;
private String name;
private String price;
}
}
解法四 直接返回Map
配置还是这个配置,VO结果遍历一遍,仅对单个VO,遍历属性,如果属性在配置中,就放进map返回给前端,这个方法也可以,但是你遍历属性要用到反射吧,反射现在的性能比之前高了很多,但是注意上面的场景,本来字段就多,你性能就算高了很多,这个花销还是存在的,而且你返回map也要走序列化器,那把这个工作放在序列化器里是不是比较合理。