很多时候我们调用接口并不是需要接口返回的所有信息; 就像查询数据库很少使用 select * from table; 一样;
为了使现有的存储结构以及代码逻辑改动最少 想办法在最外层的接口对返回的对象进行精简
目的使为了提高接口性能:减少 RPC 传输时间、节省网络带宽、节省序列化开销
一、方案
直接创建一个对象,根据入参传入的所需字段,写一堆 if else 进行 get set;
使用序列化工具,转为类似 Map 结构,取值拼装;
使用 BeanWrapper 操作对象;
前面两种比较呆板,属于定制化开发;
二、实践
Spring BeanWrapper 方案处理非集合对象比较完美,输出对象小不少; 基本数据类型有默认值,无法去除,不过这种对大小影响不大; 完整代码:github.com
1 2 3 4 5 6 7 8 9 10 11 12 13
publicstaticvoidmain(String[] args) { Orderorder= getOrder(); OrdersmallerOrder=newOrder(); List<String> keepFields = Lists.newArrayList(); keepFields.add("orderId"); keepFields.add("address.province"); // i want get all names, not only index 1, how to do ? keepFields.add("productInfos[1].name"); copyLimitedProperties(order, smallerOrder, keepFields); Gsongson=newGson(); System.out.println("src:" + gson.toJson(order)); System.out.println("des" + gson.toJson(smallerOrder)); }
目前 Spring BeanWrapper 处理集合类型比较费劲,需要告知一个个具体的路径 比如:productInfos[1].name 如果能做到 productInfos[any].name 这种,然后取出所有 index 的属性,就比较完美 (目前解决方法:通过自定义处理,遇到 any 标识,自动补全所有 index 的 key 即可,只是不那么优雅)
缺陷原因:内部逻辑直接用 key 转换为 index ,没有 any 逻辑。
1 2 3 4 5 6
else if (value instanceof List) { index = Integer.parseInt(key); List<Object> list = (List)value; this.growCollectionIfNecessary(list, index, indexedPropertyName, ph, i + 1); value = list.get(index); }