ServiceStack 提倡一种类似于 SOA 的基于消息的设计,这种设计是最优的,并为远程服务提供了许多自然的好处。
我最初的想法看起来像
- POST {CloseItemNumber} /item/1/close
- 发布 {ItemNumber} /item/1?replace=true
- 发布 {ItemNumber} /item/1
- POST {ItemNumber} /item/1 即相同的 DTO/服务不同的值。
在哪里ItemNumber
和CloseItemNumber
是单独的请求 DTO 和服务。
设计服务 API
我更喜欢围绕“资源/名词”来构建我的服务,并将我的服务 API 设计为对它们应用操作的操作。
如果该操作需要比存储资源 DTO 更多的信息,我将创建一个带有附加元数据的单独服务。
即以下是我如何将亚马逊的“RPC”服务转换为更加 REST-ful:
https://ec2.amazonaws.com/?Action=AttachVolume
&VolumeId=vol-4d826724
&InstanceId=i-6058a509
&Device=/dev/sdh
&AUTHPARAMS
进入我更喜欢写它的方式:
POST https://ec2.amazonaws.com/volumes/vol-4d826724/attach
FormData: InstanceId=i-6058a509&Device=/dev/sdh&AUTHPARAMS
仍然会使用显式的AttachVolume Request DTO。
我用来展示 WCF RPC 和 ServiceStack 粗粒度基于消息的方法之间的差异的另一个示例是:https ://gist.github.com/1386381
RPC-chatty 和基于消息的 API 之间的区别:
这是 WCF 鼓励的典型 API:
public interface IService
{
Customer GetCustomerById(int id);
Customer[] GetCustomerByIds(int[] id);
Customer GetCustomerByUserName(string userName);
Customer[] GetCustomerByUserNames(string[] userNames);
Customer GetCustomerByEmail(string email);
Customer[] GetCustomerByEmails(string[] emails);
}
这是我们在 ServiceStack 中鼓励的基于消息的等效 API:
public class Customers {
int[] Ids;
string[] UserNames;
string[] Emails;
}
public class CustomersResponse {
Customer[] Results;
}
注意:如果您希望相同的服务同时支持 SOAP 和基于 REST 的 API,则需要稍微不同地构建服务,以克服 SOAP 通过 HTTP POST 隧道传输所有操作的限制。