使用 ServiceStack 构建跨平台 Web 服务
本文主要來自MSDN雜志《Building Cross-Platform Web Services with ServiceStack》,Windows Communication Foundation (WCF) 是一個相當(dāng)優(yōu)秀的服務(wù)框架,當(dāng)我們討論跨平臺的服務(wù)的時候,雖然WCF對WebService的支持還行,在面對一些高級應(yīng)用的不太好,微軟重新發(fā)展了ASP.NET WebAPI框架,關(guān)于這兩個框架的討論可以看我另外一篇文章《WCF和ASP.NET Web API在應(yīng)用上的選擇》 。在討論跨平臺的Web服務(wù)上,ASP.NET Web API是一個重要選項,在本文中,我將展示如何利用 ServiceStack (開放源代碼.NET 和Mono REST 服務(wù)框架) 來完成這一任務(wù),不用離開 Visual Studio 或 Microsoft.NET/Mono,除了 ServiceStack 之外還有個Nancy的框架,具體可以看《.NET的微型Web框架 Nancy》。
一個典型的 Web 服務(wù)結(jié)構(gòu)如下:
- 服務(wù)層是您定義您的Web 服務(wù)接口的地方。 這也是,客戶端和你的 Web 服務(wù)進行交互的一層。
- 業(yè)務(wù)層通常是業(yè)務(wù)邏輯
- 數(shù)據(jù)層是為了封裝數(shù)據(jù)訪問和操縱在業(yè)務(wù)層提供抽象的數(shù)據(jù)模型。
- Web服務(wù)通常有遠程過程調(diào)用(RPC)和RESTful (HTTP)兩類,現(xiàn)在占據(jù)主導(dǎo)地位的Web服務(wù)是RESTful (HTTP),具體內(nèi)容可以參看文章《REST在企業(yè)中獲得成功了么?》,貼一張文章里的圖片:
2年前REST就已經(jīng)成為Web API部署方式的主流了,而且一直保持這種發(fā)展勢頭,現(xiàn)在基本上都是REST服務(wù),SOAP在企業(yè)內(nèi)網(wǎng)還存在。
遠程過程調(diào)用 (RPC) ,每個請求旨在類似于函數(shù)調(diào)用:
public interface IService
{
????? string DoSomething(int input);
}
RPC 方法對服務(wù)的修改非常不友好。 例如前面的代碼段,如果要求從客戶端來執(zhí)行更高版本的 Web 服務(wù)的 DoSomething 方法的兩個輸入?yún)?shù) — 或需要返回字符串值之外的另一個字段 —— 給老客戶重大更改是不可避免的。 當(dāng)然,您始終可以創(chuàng)建平行的 DoSomething_v2 方法,要帶兩個輸入的參數(shù),但久而久之會搞亂您的 Web 服務(wù)接口和消費者,服務(wù)變得越來越丑,用WCF實現(xiàn)的Web服務(wù)就是屬于這種情況,下面我們介紹ServiceStack。
ServiceStack是.Net和Mono的開源框架,相對WCF,MVC及Web API而言它是開發(fā)Web服務(wù)與Web應(yīng)用的有力替代品,它越來越普及。 用 ServiceStack 生成的 web 服務(wù)可以運行在 Windows 環(huán)境中,.NET 代碼或Mono支持 Linux 環(huán)境中。 Mono支持的操作系統(tǒng)包括:
- Linux
- Mac OS X, iOS
- Sun Solaris
- BSD
- Microsoft Windows
- Nintendo Wii
- Sony PlayStation 3
ServiceStack是一系列事物的綜合體:
- 包含高性能Razor Engine的Web應(yīng)用框架
- 支持例如HTML,XML,JSON,SOAP等多種格式的基于消息的Web服務(wù)框架
- 包含內(nèi)建IOC的容器
- 若干內(nèi)建庫文件,諸如:Text serializer,Redis Client,ORM以及caching providers
- 除了ASP.NET Hosting和Mono Hosting之外,還包含self-hosting選項
ServiceStack 強制遠程 Web 服務(wù)最佳實踐、 基于公約 DTO 標準為其 Web 服務(wù)接口,ServiceStack 還提供預(yù)置的響應(yīng)狀態(tài)對象,可用于撰寫 DTO,鼓勵更加直接和簡單的錯誤處理方案,顯然和WCF是明顯不同的路線。
本文假定您有一些熟悉 WCF 和.NET 框架。 為了更好地展示W(wǎng)CF 概念可以如何轉(zhuǎn)化為 ServiceStack 的概念,首先會在WCF中實現(xiàn)服務(wù)層。我會告訴你如何通過將WCF Web 服務(wù)移植到等效的使用 ServiceStack 轉(zhuǎn)換為跨平臺的 Web 服務(wù)。
WCF 使用數(shù)據(jù)合同建立的客戶端和服務(wù)器之間的通信手段。 ServiceStack和WCF相同。 WCF 需要何數(shù)據(jù)對象和數(shù)據(jù)成員打上標記; 否則,WCF 簡單地忽略它們。 這是 ServiceStack 和 WCF 與的不同的地方。 ServiceStack 支持所有POCO 的對象作為契約:
WCF的契約:
?? [DataContract] 
??? public class Ticket 
??? { 
??????? [DataMember] 
??????? public int TicketId { get; set; } 
??????? [DataMember] 
??????? public int TableNumber { get; set; } 
??????? [DataMember] 
??????? public int ServerId { get; set; } 
??????? [DataMember] 
??????? public List<Order> Orders { get; set; } 
??????? [DataMember] 
??????? public DateTime Timestamp { get; set; } 
??? } 
??? [ServiceContract] 
??? public interface ITicketService 
??? { 
??????? /// <summary> 
??????? /// 檢索當(dāng)前隊列中的所有門票的完整清單 
??????? /// </summary> 
??????? /// <returns></returns> 
??????? [OperationContract] 
??????? List<Ticket> GetAllTicketsInQueue();
??????? /// <summary> 
??????? /// 新增新門票 
??????? /// </summary> 
??????? /// <param name="ticket"></param> 
??????? [OperationContract] 
??????? void QueueTicket(Ticket ticket);
??????? /// <summary> 
??????? /// 從隊列拉出一張票 
??????? /// </summary> 
??????? /// <returns></returns> 
??????? [OperationContract] 
??????? Ticket PullTicket(); 
??? } 
}
把它轉(zhuǎn)換為ServiceStack的契約:
public class Ticket 
{ 
?????? public int TicketId { get; set; } 
??????? public int TableNumber { get; set; } 
??????? public int ServerId { get; set; } 
??????? public List<Order> Orders { get; set; } 
??????? public DateTime Timestamp { get; set; }
}
public class GetAllTicketsInQueueRequest 
{ 
}
public class QueueTicketRequest 
{ 
??? public Ticket Ticket { get; set; } 
}
public class PullTicketRequest 
{ 
}
public interface ISCTicketService 
{ 
??? List<Ticket> Any(GetAllTicketsInQueueRequest request);
??? void Any(QueueTicketRequest request);
??? Ticket Any(PullTicketRequest request); 
}
ServiceStack 規(guī)定每個唯一的請求是對象所標識唯一的請求,這意味著你不能重用 DTO 跨多個服務(wù)實現(xiàn)與 ServiceStack 的請求。ServiceStack 支持不同的操作,如有 Get 和 Post。 您的選擇在這里僅影響的 HTTP 請求。 指定任何 Web 服務(wù)請求是指可以通過 HTTP GET 和 HTTP POST 調(diào)用操作。 這種強制措施,簡化了 rest 風(fēng)格的 Web 服務(wù)實現(xiàn)。要將您的 ServiceStack Web 服務(wù)變成 rest 風(fēng)格的 Web 服務(wù),只需添加 URL [Route(...)]向您的 Web 服務(wù)請求聲明屬性。
??? //Request DTO 
??? public class Hello 
??? { 
??????? public string Name { get; set; } 
??? }
??? //Response DTO 
??? public class HelloResponse 
??? { 
??????? public string Result { get; set; } 
??????? public ResponseStatus ResponseStatus { get; set; } //Where Exceptions get auto-serialized 
??? }
??? //Can be called via any endpoint or format, see: http://servicestack.net/ServiceStack.Hello/ 
??? public class HelloService : Service 
??? { 
??????? public object Any(Hello request) 
??????? { 
??????????? return new HelloResponse { Result = "Hello, " + request.Name }; 
??????? } 
??? }
??? //REST Resource DTO 
??? [Route("/todos")] 
??? [Route("/todos/{Ids}")] 
??? public class Todos : IReturn<List<Todo>> 
??? { 
??????? public long[] Ids { get; set; } 
??????? public Todos(params long[] ids) 
??????? { 
??????????? this.Ids = ids; 
??????? } 
??? }
??? [Route("/todos", "POST")] 
??? [Route("/todos/{Id}", "PUT")] 
??? public class Todo : IReturn<Todo> 
??? { 
??????? public long Id { get; set; } 
??????? public string Content { get; set; } 
??????? public int Order { get; set; } 
??????? public bool Done { get; set; } 
??? }
??? public class TodosService : Service 
??? { 
??????? public TodoRepository Repository { get; set; }? //Injected by IOC
??????? public object Get(Todos request) 
??????? { 
??????????? return request.Ids.IsEmpty() 
??????????????? ? Repository.GetAll() 
??????????????? : Repository.GetByIds(request.Ids); 
??????? }
??????? public object Post(Todo todo) 
??????? { 
??????????? return Repository.Store(todo); 
??????? }
??????? public object Put(Todo todo) 
??????? { 
??????????? return Repository.Store(todo); 
??????? }
??????? public void Delete(Todos request) 
??????? { 
??????????? Repository.DeleteByIds(request.Ids); 
??????? } 
??? }??? 
以ASP.NET Hosting承載ServiceStack,創(chuàng)建一個空的ASP.NET應(yīng)用,使用 NuGet 包管理器控制臺將 ServiceStack 引用添加到 ServiceStack.Host.AspNet中所示
Web.config 會增加下面的配置
<configuration> 
? <system.web> 
??? <compilation debug="true" targetFramework="4.0" /> 
? ? <httpHandlers> 
????? <add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" /> 
??? </httpHandlers> 
? </system.web> 
? <system.webServer> 
??? <modules runAllManagedModulesForAllRequests="true" /> 
??? <validation validateIntegratedModeConfiguration="false" /> 
? ? <handlers> 
????? <add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" /> 
??? </handlers> 
? </system.webServer> 
</configuration>
你需要從 ServiceStack.WebHost.End 繼承-實現(xiàn)端點。
public class AppHost? : AppHostBase 
??? {??????? 
??????? public AppHost() //Tell ServiceStack the name and where to find your web services 
??????????? : base("StarterTemplate ASP.NET Host", typeof(HelloService).Assembly) { }
??????? public override void Configure(Funq.Container container) 
??????? { 
??????????? //Set JSON web services to return idiomatic JSON camelCase properties 
??????????? ServiceStack.Text.JsConfig.EmitCamelCaseNames = true; 
??????? 
??????????? //Configure User Defined REST Paths 
??????????? Routes 
????????????? .Add<Hello>("/hello") 
????????????? .Add<Hello>("/hello/{Name*}");
??????????? //Uncomment to change the default ServiceStack configuration 
??????????? //SetConfig(new EndpointHostConfig { 
??????????? //});
??????????? //Enable Authentication 
??????????? //ConfigureAuth(container);
??????????? //Register all your dependencies 
??????????? container.Register(new TodoRepository());??????????? 
??????? }
??????? /* Uncomment to enable ServiceStack Authentication and CustomUserSession 
??????? private void ConfigureAuth(Funq.Container container) 
??????? { 
??????????? var appSettings = new AppSettings();
??????????? //Default route: /auth/{provider} 
??????????? Plugins.Add(new AuthFeature(() => new CustomUserSession(), 
??????????????? new IAuthProvider[] { 
??????????????????? new CredentialsAuthProvider(appSettings), 
??????????????????? new FacebookAuthProvider(appSettings), 
??????????????????? new TwitterAuthProvider(appSettings), 
??????????????????? new BasicAuthProvider(appSettings), 
??????????????? })); 
??????????? //Default route: /register 
??????????? Plugins.Add(new RegistrationFeature()); 
??????????? //Requires ConnectionString configured in Web.Config 
??????????? var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString; 
??????????? container.Register<IDbConnectionFactory>(c => 
??????????????? new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));
??????????? container.Register<IUserAuthRepository>(c => 
??????????????? new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));
??????????? var authRepo = (OrmLiteAuthRepository)container.Resolve<IUserAuthRepository>(); 
??????????? authRepo.CreateMissingTables(); 
??????? } 
??????? */
??????? public static void Start() 
??????? { 
??????????? new AppHost().Init(); 
??????? } 
??? }
ServiceStack Web 應(yīng)用程序啟動時,您的服務(wù)合同列出作為元數(shù)據(jù)操作,如圖所示:
相關(guān)文章:
SignalR, Filters and ServiceStack
采訪ServiceStack的項目領(lǐng)導(dǎo)Demis Bellot——第1部分
采訪ServiceStack的項目領(lǐng)導(dǎo)Demis Bellot——第2部分????????????
轉(zhuǎn)載于:https://www.cnblogs.com/shanyou/p/3348347.html
總結(jié)
以上是生活随笔為你收集整理的使用 ServiceStack 构建跨平台 Web 服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: cpc客户端上传文件服务器拒收,cpc客
- 下一篇: poj 3469(网络流模版)
