使用 ServiceStack 构建跨平台 Web 服务
本文主要來(lái)自MSDN雜志《Building Cross-Platform Web Services with ServiceStack》,Windows Communication Foundation (WCF) 是一個(gè)相當(dāng)優(yōu)秀的服務(wù)框架,當(dāng)我們討論跨平臺(tái)的服務(wù)的時(shí)候,雖然WCF對(duì)WebService的支持還行,在面對(duì)一些高級(jí)應(yīng)用的不太好,微軟重新發(fā)展了ASP.NET WebAPI框架,關(guān)于這兩個(gè)框架的討論可以看我另外一篇文章《WCF和ASP.NET Web API在應(yīng)用上的選擇》 。在討論跨平臺(tái)的Web服務(wù)上,ASP.NET Web API是一個(gè)重要選項(xiàng),在本文中,我將展示如何利用 ServiceStack (開(kāi)放源代碼.NET 和Mono REST 服務(wù)框架) 來(lái)完成這一任務(wù),不用離開(kāi) Visual Studio 或 Microsoft.NET/Mono,除了 ServiceStack 之外還有個(gè)Nancy的框架,具體可以看《.NET的微型Web框架 Nancy》。
一個(gè)典型的 Web 服務(wù)結(jié)構(gòu)如下:
- 服務(wù)層是您定義您的Web 服務(wù)接口的地方。 這也是,客戶(hù)端和你的 Web 服務(wù)進(jìn)行交互的一層。
- 業(yè)務(wù)層通常是業(yè)務(wù)邏輯
- 數(shù)據(jù)層是為了封裝數(shù)據(jù)訪問(wèn)和操縱在業(yè)務(wù)層提供抽象的數(shù)據(jù)模型。
- Web服務(wù)通常有遠(yuǎn)程過(guò)程調(diào)用(RPC)和RESTful (HTTP)兩類(lèi),現(xiàn)在占據(jù)主導(dǎo)地位的Web服務(wù)是RESTful (HTTP),具體內(nèi)容可以參看文章《REST在企業(yè)中獲得成功了么?》,貼一張文章里的圖片:
2年前REST就已經(jīng)成為Web API部署方式的主流了,而且一直保持這種發(fā)展勢(shì)頭,現(xiàn)在基本上都是REST服務(wù),SOAP在企業(yè)內(nèi)網(wǎng)還存在。
遠(yuǎn)程過(guò)程調(diào)用 (RPC) ,每個(gè)請(qǐng)求旨在類(lèi)似于函數(shù)調(diào)用:
public interface IService
{
????? string DoSomething(int input);
}
RPC 方法對(duì)服務(wù)的修改非常不友好。 例如前面的代碼段,如果要求從客戶(hù)端來(lái)執(zhí)行更高版本的 Web 服務(wù)的 DoSomething 方法的兩個(gè)輸入?yún)?shù) — 或需要返回字符串值之外的另一個(gè)字段 —— 給老客戶(hù)重大更改是不可避免的。 當(dāng)然,您始終可以創(chuàng)建平行的 DoSomething_v2 方法,要帶兩個(gè)輸入的參數(shù),但久而久之會(huì)搞亂您的 Web 服務(wù)接口和消費(fèi)者,服務(wù)變得越來(lái)越丑,用WCF實(shí)現(xiàn)的Web服務(wù)就是屬于這種情況,下面我們介紹ServiceStack。
ServiceStack是.Net和Mono的開(kāi)源框架,相對(duì)WCF,MVC及Web API而言它是開(kāi)發(fā)Web服務(wù)與Web應(yīng)用的有力替代品,它越來(lái)越普及。 用 ServiceStack 生成的 web 服務(wù)可以運(yùn)行在 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)建庫(kù)文件,諸如:Text serializer,Redis Client,ORM以及caching providers
- 除了ASP.NET Hosting和Mono Hosting之外,還包含self-hosting選項(xiàng)
ServiceStack 強(qiáng)制遠(yuǎn)程 Web 服務(wù)最佳實(shí)踐、 基于公約 DTO 標(biāo)準(zhǔn)為其 Web 服務(wù)接口,ServiceStack 還提供預(yù)置的響應(yīng)狀態(tài)對(duì)象,可用于撰寫(xiě) DTO,鼓勵(lì)更加直接和簡(jiǎn)單的錯(cuò)誤處理方案,顯然和WCF是明顯不同的路線。
本文假定您有一些熟悉 WCF 和.NET 框架。 為了更好地展示W(wǎng)CF 概念可以如何轉(zhuǎn)化為 ServiceStack 的概念,首先會(huì)在WCF中實(shí)現(xiàn)服務(wù)層。我會(huì)告訴你如何通過(guò)將WCF Web 服務(wù)移植到等效的使用 ServiceStack 轉(zhuǎn)換為跨平臺(tái)的 Web 服務(wù)。
WCF 使用數(shù)據(jù)合同建立的客戶(hù)端和服務(wù)器之間的通信手段。 ServiceStack和WCF相同。 WCF 需要何數(shù)據(jù)對(duì)象和數(shù)據(jù)成員打上標(biāo)記; 否則,WCF 簡(jiǎn)單地忽略它們。 這是 ServiceStack 和 WCF 與的不同的地方。 ServiceStack 支持所有POCO 的對(duì)象作為契約:
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)前隊(duì)列中的所有門(mén)票的完整清單
??????? /// </summary>
??????? /// <returns></returns>
??????? [OperationContract]
??????? List<Ticket> GetAllTicketsInQueue();
??????? /// <summary>
??????? /// 新增新門(mén)票
??????? /// </summary>
??????? /// <param name="ticket"></param>
??????? [OperationContract]
??????? void QueueTicket(Ticket ticket);
??????? /// <summary>
??????? /// 從隊(duì)列拉出一張票
??????? /// </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ī)定每個(gè)唯一的請(qǐng)求是對(duì)象所標(biāo)識(shí)唯一的請(qǐng)求,這意味著你不能重用 DTO 跨多個(gè)服務(wù)實(shí)現(xiàn)與 ServiceStack 的請(qǐng)求。ServiceStack 支持不同的操作,如有 Get 和 Post。 您的選擇在這里僅影響的 HTTP 請(qǐng)求。 指定任何 Web 服務(wù)請(qǐng)求是指可以通過(guò) HTTP GET 和 HTTP POST 調(diào)用操作。 這種強(qiáng)制措施,簡(jiǎn)化了 rest 風(fēng)格的 Web 服務(wù)實(shí)現(xiàn)。要將您的 ServiceStack Web 服務(wù)變成 rest 風(fēng)格的 Web 服務(wù),只需添加 URL [Route(...)]向您的 Web 服務(wù)請(qǐng)求聲明屬性。
??? //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)建一個(gè)空的ASP.NET應(yīng)用,使用 NuGet 包管理器控制臺(tái)將 ServiceStack 引用添加到 ServiceStack.Host.AspNet中所示
Web.config 會(huì)增加下面的配置
<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 繼承-實(shí)現(xiàn)端點(diǎ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)用程序啟動(dòng)時(shí),您的服務(wù)合同列出作為元數(shù)據(jù)操作,如圖所示:
相關(guān)文章:
SignalR, Filters and ServiceStack
采訪ServiceStack的項(xiàng)目領(lǐng)導(dǎo)Demis Bellot——第1部分
采訪ServiceStack的項(xiàng)目領(lǐng)導(dǎo)Demis Bellot——第2部分????????????
轉(zhuǎn)載于:https://www.cnblogs.com/shanyou/p/3348347.html
總結(jié)
以上是生活随笔為你收集整理的使用 ServiceStack 构建跨平台 Web 服务的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: cpc客户端上传文件服务器拒收,cpc客
- 下一篇: poj 3469(网络流模版)