我们有 2 个独立的产品,需要通过 Web 服务相互通信。
支持 API 版本控制的最佳实践是什么?
I have 本文 http://www.ibm.com/developerworks/webservices/library/ws-version/从 2004 年开始,声称没有实际标准,只有最佳实践。还有更好的解决方案吗?如何解决 WS 版本控制问题?
问题描述
System A
Client
class SystemAClient{
SystemBServiceStub systemB;
public void consumeFromB(){
SystemBObject bObject = systemB.getSomethingFromB(new SomethingFromBRequest("someKey"));
}
}
Service
class SystemAService{
public SystemAObject getSomethingFromA(SomethingFromARequest req){
return new SystemAObjectFactory.getObject(req);
}
}
可转让对象
版本1
class SystemAObject{
Integer id;
String name;
... // getters and setters etc;
}
版本2
class SystemAObject{
Long id;
String name;
String description;
... // getters and setters etc;
}
请求对象
版本1
class SomethingFromARequest {
Integer requestedId;
... // getters and setters etc;
}
版本2
class SomethingFromARequest {
Long requestedId;
... // getters and setters etc;
}
System B
Client
class SystemBClient{
SystemAServiceStub systemA;
public void consumeFromA(){
SystemAObject aObject = systemA.getSomethingFromA(new SomethingFromARequest(1));
aObject.getDescription() // fail point
// do something with it...
}
}
Service
class SystemBService{
public SystemBObject getSomethingFromB(SomethingFromBRequest req){
return new SystemBObjectFactory.getObject(req);
}
}
可转让对象
版本1
class SystemBObject{
String key;
Integer year;
Integer month;
Integer day;
... // getters and setters etc;
}
版本2
class SystemBObject{
String key;
BDate date;
... // getters and setters etc;
}
class BDate{
Integer year;
Integer month;
Integer day;
... // getters and setters etc;
}
请求对象
版本1
class SomethingFromBRequest {
String key;
... // getters and setters etc;
}
版本2
class SomethingFromBRequest {
String key;
BDate afterDate;
BDate beforeDate;
... // getters and setters etc;
}
失败场景
If a System A client of 版本1打电话给System B service of 版本2它可能会失败:
- 缺少方法
SystemBObject
(getYear()
, getMonth()
, getDay()
)
- 未知类型
BDate
If a System A client of 版本2打电话给System B service of 版本1它可能会失败:
- 未知类型
BDate
on the SomethingFromBRequest
(A客户端使用B版本1无法识别的较新的B请求对象)
- 如果系统 A 客户端足够聪明,可以使用请求对象的版本 1,则它可能会因缺少方法而失败
SystemBObject
目的 (getDate()
)
If a System B client of 版本1打电话给System A service of 版本2它可能会失败:
- 类型不匹配或溢出
SystemAObject
(回Long
但预计Integer
)
If a System B client of 版本2打电话给System A service of 版本1它可能会失败:
- 类型不匹配或溢出
SystemARequest
(要求Long
代替Integer
)
- 如果请求以某种方式通过,则会出现转换问题(存根是
Long
但该服务返回一个Integer
不一定兼容所有 WS 实现)
可能的解决方案
- 推进版本时使用数字:例如
SystemAObject1
, SystemBRequest2
等等,但这缺少一个用于匹配源/目标版本的 API
- 在签名中,传递 XML 而不是对象(哎呀,在 XML 中传递转义的 XML、双重序列化、反序列化/解析、解解析)
- 其他:例如Document/literal/WS-I 有补救措施吗?