ServiceStack简单使⽤
提到构建WebService服务,⼤家肯定第⼀个想到的是使⽤WCF,因为简单快捷嘛。⾸先要说明的是,本⼈对WCF不太了解,但是想快速建⽴⼀个WebService,于是看到了MSDN上的这⼀篇⽂章,所以这⾥简要介绍⼀下如何使⽤ServiceStack快速建⽴⼀个WebService服务。
当然,在开始之前,⾸先要说明⼀下ServiceStack是个什么东西。在国内⽤ServiceStack的似乎很少,⼤部分都是WCF或者ASP.NET WebAPI,唯⼀接触ServiceStack的可能是在C# 中调⽤Redis的时候,有个,之前还写过⼀篇的拙⽂。这个ServiceStack.Redis其实就是ServiceStack的⼀个组件,专门⽤来跟Redis进⾏交互的。
⼀关于WebService
在谈论ServiceStack之前,先看看构成⼀个WebService的基本框架:
服务层就是定义WebService接⼝的地⽅,这⼀层也是客户端使⽤WebService唯⼀需要与之交互的⼀层。
业务层通常包含有⼤量的业务逻辑。他也是实现接⼝层定义的接⼝的地⽅,也是保持服务层的轻量以及关注服务端客户端的契约以及通讯的地⽅。
数据层通常就是封装数据访问⽅法并给业务层提供抽象数据模型。
现在我们来看Service这⼀层。⼀些WebService使⽤远程过程调⽤的⽅法来实现(RPC),⽐如会定义如下函数调⽤:
public interface IService
{
string DoSomething(int input);
}
这种RPC的⽅式使得服务不能很好的应对变化。⽐如,在上⾯的代码中,如果后续版本的接⼝需要接受两个参数来执⾏DoSomething⽅法,或者说除了返回⼀个string外还需要返回其他信息。如果在原接⼝上修改的话,就会使得⽼版本的客户端⽆法使⽤。当然,我们可以创建⼀个平⾏的DoSomething_v2来接受两个参数。但是随着时间的迁移,我们的接⼝中会充斥着越来越多这样的定义,不管是新⽤户还是⽼⽤户都会感到困惑。
⾯对这种情况,可以使⽤数据传输对象(DTO) 来定义前⾯的接⼝中的相关参数。上⾯的RPC⽅式转换为对应的DTO模型如下:
public class DoSomethingRequest
{
public int Input { get; set; }
}
public class DoSomethingResponse
{
public string Result { get; set; }
}
public interface IService
{
DoSomethingResponse DoSomething(DoSomethingRequest request);
}
每个服务接受⼀个DTO请求参数,返回⼀个DTO响应。在请求和相应的DTO对象中添加字段,不会破坏旧的客户端。
在WCF中RPC和DTO风格的WebService均⽀持,但是在ServiceStack中仅⽀持DTO风格。ServiceStack为了减少繁琐和注重接⼝设计从⽽仅拥抱的DTO风格的远程 WebService接⼝。这是了解 ServiceStack的关键,也是ServiceStack框架的设计原则。
了解了ServiceStack的设计理念后,来看看ServiceStack是什么。
⼆ ServiceStack是什么
ServiceStack是⼀个开源的⼗分流⾏的WebService框架,引⽤其的介绍:
“Service Stack is a high-performance .NET web services platform that simplifies the development of high-performance REST (JSON, XML, JSV, HTML, MsgPack, ProtoBuf, CSV) and WCF SOAP .”
“ServiceStack是⼀个⾼性能的.NET Web Service 平台,他能够简化开发⾼性能的REST (⽀持
JSON,XML,JSV,HTML,MsgPack,ProtoBuf,CSV等消息格式)以及WCF SOAP风格的WebService”。
在其上也有⼀篇名为的介绍。建议您直接看,这⾥从⾥⾯截取了⼏张图:
可以看到ServiceStack除了在其底层是⼀个精简的WebService框架之外,在其上还有与之相关的⼀些组件,⽐如号称.NET 上最快的JSON 序列化⼯具,.NET中流⾏的Redis访问模块,轻量级快速Orm框架OrmLite等诸多功能。
可以看到这些组件基本提供了⼀个WebService框架必需的⼀些功能。
在内部实现上ServiceStack建⽴在原⽣的ASP.NET IHttpHandler之上,他能够允许在.NET Framework和Mono之上。
下⾯来看如何使⽤ServiceStack建⽴⼀个WebService:
三使⽤ServiceStack
要创建服务,⾸先要定义接⼝。这⾥以⼀个售票系统为例来说明如何使⽤ServiceStack来创建服务:
创建服务接⼝层
⾸先新建⼀个TicketSystem.ServiceContract的类库,我们定义DTO对象。必需要有⼀个Ticket实体类:
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; }
}
在WCF中需要在实体类和字段上⾯添加DataContract和DataMember来表⽰序列化时需要的字段,如果没有添加这些标签,在序列化的时候就会忽略。
⽽在ServiceStack中,这些标记都不需要,ServiceStack会序列化所有的Plain Old CLR Objects(POCOs),并且这些对象对客户端都可见。
然后开始定义Service中需要⽤到的对外提供服务的接⼝:
public interface ITicketService
{
List<Ticket> Any(GetAllTicketsInQueueRequest request);
void Any(QueueTicketRequest request);
Ticket Any(PullTicketRequest request);
}
在ITickertService中,我们定义了三个操作,第⼀次看到这样的操作可能有些奇怪,因为⽅法名称都⼀样。这是ServiceStack和WCF不⼀样的地⽅。在WCF中以上接⼝可能是这样的:
[ServiceContract]
public interface ITicketService调用webservice服务
{
[OperationContract]
List<Ticket> GetAllTicketsInQueue(GetAllTicketsInQueueRequest request);
[OperationContract]
void QueueTicket(QueueTicketRequest request);
[OperationContract]
Ticket PullTicket(PullTicketRequest request);
}
WCF中接⼝需要使⽤ServiceContract来表明,其中的⽅法需要使⽤OperationContract来标记。⽅法的名称就是服务的名称。ServiceStack中的服务⽅法名为Any,Get以及Post,这也是ServiceStack⽀持的请求类型,Any表⽰服务可以通过HTTP Get和HTTP Post两种⽅式调⽤。这强化和简化了RESTFull风格的WebService的实现。只需要在这些⽅法上添加爱[Route(…)]属性即可。在ServiceStack中,⽅法和⽅法之间的区别是通过服务的参数及请求对象Request DTO来区分的,⽽不是像WCF中通过⽅法名称来区分。这就表⽰⼀个请求DTO对象不能在ServiceStack的多个Service中复⽤。
创建服务端
有了服务接⼝层之后,需要编写服务端以实现这些逻辑,也就是前⾯定义的ITicketService接⼝。⾸先创建名为ServiceStackServer的空的ASP.NET 应⽤程序,然后新建TicketService类,是该类实现ITicketService接⼝并继承⾃Service类。Service类是ServiceStack中的,可以通过NuGet来安装和引⽤ServiceStack相关类库:
实现后TicketService类如下:
public class TicketService : Service, ITicketService
{
private static readonly TicketSystem.TicketProcessor.TicketProcessor
_ticketProcessor = new TicketSystem.TicketProcessor.TicketProcessor();
public List<Ticket> Any(GetAllTicketsInQueueRequest request)
{
return _ticketProcessor.GetTicketsInQueue()
.Select(TicketTranslator.TranslateTicket).ToList();
}
public void Any(QueueTicketRequest request)
{
_ticketProcessor.QueueTicket(
TicketTranslator.TranslateTicket(request.Ticket));
}
public Ticket Any(PullTicketRequest request)
{
TicketSystem.TicketProcessor.Ticket nextTicket =
_ticketProcessor.PullTicket();
if (nextTicket != null)
{
return TicketTranslator.TranslateTicket(nextTicket);
}
return null;
}
}
这⾥⾯我们定义了⼀个私有了TicketProcessor 变量,接⼝中的所有⽅法都通过该类实现,在接⼝对象到该⽅法的调⽤中,我们对实体进⾏了转换。该对象在其他程序集中定义,这样能保证服务端代码简洁。
有了服务端之后,需要把服务端Host起来对外提供服务,ServiceStack提供了通过IIS,Self-Host等多
种形式。因为我们之前创建的ASP.NET程序,所以,只需要再添加⼀个Global.asax⽂件,然后在启动的事件Application_Start中初始化即可。
protected void Application_Start(object sender, EventArgs e)
{
//Initialize your web service on startup.
new TicketServiceHost().Init();
}
public class TicketServiceHost : AppHostBase
{
//Register your web service with ServiceStack.
public TicketServiceHost()
: base("Ticket Service", typeof(TicketService).Assembly)
{ }
public override void Configure(Funq.Container container)
{
//Register any dependencies your services use here.
}
}
只需要实现ApphostBase基类,提供服务显⽰名称,以及实现了Service接⼝的服务所在的程序集即可。
当然也可以通过控制台应⽤程序来Host我们的WebService,这时TicketServiceHost需要实现AppSelfHostBase,实现如下:
public class TicketServiceHost : AppSelfHostBase
{
/// <summary>
/// Default constructor.
/// Base constructor requires a name and assembly to locate web service classes.
/// </summary>
public TicketServiceHost()
: base("WebApplication1", typeof(TicketService).Assembly)
{
}
/// <summary>
/// Application specific configuration
/// This method should initialize any IoC resources utilized by your web service classes.
/
// </summary>
/// <param name="container"></param>
public override void Configure(Container container)
{
//Config examples
//this.AddPlugin(new PostmanFeature());
//this.AddPlugin(new CorsFeature());
}
}
然后在Main函数中,启动即可:
static void Main(string[] args)
{
var listeningOn = args.Length == 0 ? "*:1337/" : args[0];
var appHost = new TicketServiceHost()
.Init()
.Start(listeningOn);
Console.WriteLine("AppHost Created at {0}, listening on {1}",
DateTime.Now, listeningOn);
Console.ReadKey();
}
现在,我们运⾏前⾯创建的ASP.NET或者运⾏Console托管的TicketServiceHost,在浏览器中访问即可看到我们定义好的服务:
服务客户端
服务端创建和托管好之后,服务使⽤者就可以直接编写HttpWebRequest对象对这些服务通过Get或者Post⽅式进⾏直接访问了。
除此之外,ServiceStack也内置了⼀些便捷访问的客户端,这些对象位于ServiceStack.ServiceClient.Web命名空间中。所有的内置的客户端都实现了ServiceStack.Service.IServiceClient 放,这些⽀持REST的客户端都实现了ServiceStack.Service.IRestClient.这些客户端对象包括:
JsonServiceClient
JsvServiceClient
XmlServiceClient
MsgPackServiceClient
ProtoBufServiceClient
Soap11ServiceClient
Soap12ServiceClient
从名称可以看出,这⼏种不同之处在于⽀持的序列化和反序列化格式不同。因为他们实现的是⼀系列相同的接⼝,所以他们的⽤法相同,也可以相互替换。
这⾥我们不演⽰如何通过HttpWebRequest像请求普通的⽹页那样请求我们之前托管好的WebService,现在假设我们有⼀个Console程序需要使⽤WebService程序。只需要新建⼀个ServiceStack的Service,然后将Host的地址传⼊即可。这些⽅法在内部会为我们将代码转化为传统的使⽤HttpWebRequest的⽅式请求,⽬前这些⽅法还都是同步的。
⽐如,如果我们想使⽤WCF中使⽤的Soap11来请求,只需如下代码:
static void Main(string[] args)
{
Console.Title = "ServiceStack Console Client";
using (var client = new Soap11ServiceClient("localhost:1337"))
{
List<Ticket> queuedTickets = client.Send<List<Ticket>>(
new GetAllTicketsInQueueRequest()) ;
if (queuedTickets != null)
{
foreach (Ticket ticket in queuedTickets)
{
PrintTicket(ticket);
}
}
}
Console.ReadKey();
}
这⾥的Soap11ServiceClient 对象可以换成ServiceStack⽀持的其他数据序列化格式。
四结语
本⽂介绍了开源的⽐较流⾏的WebService框架ServiceStack,并通过⼀个简单的例⼦展现了如何使⽤ServiceStack创建出⼀个WebService。
它能够⽐较⽅便快捷的搭建⾼效的具有RESTFull风格的WebService应⽤程序。其框架的设计思路也⾮常值得学习,通过类似“约定⼤于配置”的⽅式,减少了WCF中创建WebService需要的各种标记,强制⽤户使⽤DTO的⽅式来建⽴服务接⼝。ServiceStack也提供了名为ServiceStackVS的VisualStudio插件能够帮助您⽅便的创建ServiceStack模板。
WCF可以实现ServiceStack所有的功能。但是ServiceStack为您快速创建⼀个⾼效WebService提供了另外⼀种选择,他可以运⾏于不同的平台。ServiceStack也是开源社区⽐较活跃的⼀个WebService框架,通过研究其代码也可以借鉴其思路,提⾼⾃⼰的编码和架构⽔平。⽐如可以修改Client以⽀持异步⽅法调⽤等等,可以⾃⼰动⼿添加⾃⼰想要的功能。
希望本⽂对您了解ServiceStack有所帮助。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论