背景介绍:
A服务是基础服务,靠一个appid做省份的隔离,这个appid需要调用方设置请求头传入,一般情况是前端请求,用户的数据自然可以得知省份;
B服务做统计的业务,需要从A服务读取数据。这个调用完全是后端之间的服务调用,所以需要自己设置appid的请求头。同时旧的结构是没做省份隔离的,所以需要读所有省份的数据合并返回与旧的返回结果结构相同,才能兼容旧的代码。
实现
一开始想用代理模式,不过这样会需要改动原来的业务代码,又想到每个请求的结构类似,所以抽象出如下的代码:
- 把appid设置在配置文件里面
- 模版
@Slf4j
public abstract class AbstractItemsUomClientTemplate<T extends BaseVo> {
public abstract void checkParam();
public abstract T call();
public abstract String getErrorMsgTitle();
public final T execute(List<String> appIdList) {
if(CollectionUtils.isEmpty(appIdList)) {
return null;
}
checkParam();
List<T> voList = new ArrayList<>();
appIdList.stream().forEach(appId -> {
try {
XXXXXContext.setSdpAppId(appId);
T vo = call();
if (vo != null && CollectionUtils.isNotEmpty(vo.getItems())) {
voList.add(vo);
}
} catch (Exception e) {
log.error(getErrorMsgTitle(),e);
}
});
if(CollectionUtils.isEmpty(voList)) {
return null;
}
// 把每个省份的数据合并
return (T) merge(voList);
}
}
- 使用:
把请求头的部分提取出来,下次再写的时候,只需要关注业务调用,省份的隔离变得无感知了
public XXX getXXXXXByXXXX(......) {
// ...
XXX xxx = new AbstractItemsUomClientTemplate<XXX>() {
@Override
public void checkParam() {
// 校验
}
@Override
public XXX call() {
// 在这里调用A服务
}
@Override
public String getErrorMsgTitle() {
return "....";
}
}.execute(appIdConfig.getList());
return xxx;
}
总结
适用于结构类似的方法,抽象出来,方便维护和扩展