使用 ServiceStack 构建跨平台 Web 服务(转)
出处:http://www.cnblogs.com/shanyou/p/3348347.html
本文主要来自MSDN杂志《Building Cross-Platform Web Services with ServiceStack》,Windows Communication Foundation (WCF) 是一个相当优秀的服务框架,当我们讨论跨平台的服务的时候,虽然WCF对WebService的支持还行,在面对一些高级应用的不太好,微软重新发展了ASP.NET WebAPI框架,关于这两个框架的讨论可以看我另外一篇文章《WCF和ASP.NET Web API在应用上的选择》 。在讨论跨平台的Web服务上,ASP.NET Web API是一个重要选项,在本文中,我将展示如何利用 ServiceStack (开放源代码.NET 和Mono REST 服务框架) 来完成这一任务,不用离开 Visual Studio 或 Microsoft.NET/Mono,除了 ServiceStack 之外还有个Nancy的框架,具体可以看《.NET的微型Web框架 Nancy》。
一个典型的 Web 服务结构如下:
- 服务层是您定义您的Web 服务接口的地方。 这也是,客户端和你的 Web 服务进行交互的一层。
- 业务层通常是业务逻辑
- 数据层是为了封装数据访问和操纵在业务层提供抽象的数据模型。
- Web服务通常有远程过程调用(RPC)和RESTful (HTTP)两类,现在占据主导地位的Web服务是RESTful (HTTP),具体内容可以参看文章《REST在企业中获得成功了么?》,贴一张文章里的图片:
2年前REST就已经成为Web API部署方式的主流了,而且一直保持这种发展势头,现在基本上都是REST服务,SOAP在企业内网还存在。
远程过程调用 (RPC) ,每个请求旨在类似于函数调用:
public interface IService
{
string DoSomething(int input);
}
RPC 方法对服务的修改非常不友好。 例如前面的代码段,如果要求从客户端来执行更高版本的 Web 服务的 DoSomething 方法的两个输入参数 — 或需要返回字符串值之外的另一个字段 —— 给老客户重大更改是不可避免的。 当然,您始终可以创建平行的 DoSomething_v2 方法,要带两个输入的参数,但久而久之会搞乱您的 Web 服务接口和消费者,服务变得越来越丑,用WCF实现的Web服务就是属于这种情况,下面我们介绍ServiceStack。
ServiceStack是.Net和Mono的开源框架,相对WCF,MVC及Web API而言它是开发Web服务与Web应用的有力替代品,它越来越普及。 用 ServiceStack 生成的 web 服务可以运行在 Windows 环境中,.NET 代码或Mono支持 Linux 环境中。 Mono支持的操作系统包括:
- Linux
- Mac OS X, iOS
- Sun Solaris
- BSD
- Microsoft Windows
- Nintendo Wii
- Sony PlayStation 3
ServiceStack是一系列事物的综合体:
- 包含高性能Razor Engine的Web应用框架
- 支持例如HTML,XML,JSON,SOAP等多种格式的基于消息的Web服务框架
- 包含内建IOC的容器
- 若干内建库文件,诸如:Text serializer,Redis Client,ORM以及caching providers
- 除了ASP.NET Hosting和Mono Hosting之外,还包含self-hosting选项
ServiceStack 强制远程 Web 服务最佳实践、 基于公约 DTO 标准为其 Web 服务接口,ServiceStack 还提供预置的响应状态对象,可用于撰写 DTO,鼓励更加直接和简单的错误处理方案,显然和WCF是明显不同的路线。
本文假定您有一些熟悉 WCF 和.NET 框架。 为了更好地展示WCF 概念可以如何转化为 ServiceStack 的概念,首先会在WCF中实现服务层。我会告诉你如何通过将WCF Web 服务移植到等效的使用 ServiceStack 转换为跨平台的 Web 服务。
WCF 使用数据合同建立的客户端和服务器之间的通信手段。 ServiceStack和WCF相同。 WCF 需要何数据对象和数据成员打上标记; 否则,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>
/// 检索当前队列中的所有门票的完整清单
/// </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();
}
}
把它转换为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 规定每个唯一的请求是对象所标识唯一的请求,这意味着你不能重用 DTO 跨多个服务实现与 ServiceStack 的请求。ServiceStack 支持不同的操作,如有 Get 和 Post。 您的选择在这里仅影响的 HTTP 请求。 指定任何 Web 服务请求是指可以通过 HTTP GET 和 HTTP POST 调用操作。 这种强制措施,简化了 rest 风格的 Web 服务实现。要将您的 ServiceStack Web 服务变成 rest 风格的 Web 服务,只需添加 URL [Route(...)]向您的 Web 服务请求声明属性。
//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,创建一个空的ASP.NET应用,使用 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 继承实现端点。
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 应用程序启动时,您的服务合同列出作为元数据操作,如图所示:
相关文章:
SignalR, Filters and ServiceStack
采访ServiceStack的项目领导Demis Bellot——第1部分
采访ServiceStack的项目领导Demis Bellot——第2部分
使用 ServiceStack 构建跨平台 Web 服务(转)的更多相关文章
- 使用 ServiceStack 构建跨平台 Web 服务
本文主要来自MSDN杂志<Building Cross-Platform Web Services with ServiceStack>,Windows Communication Fou ...
- 使用RpcLite构建SOA/Web服务
使用RpcLite构建SOA/Web服务 SOA框架系列 1. 使用RpcLite构建SOA/Web服务 提到Web服务最先想到的就是WebService此外常用的还有WCF.ServiceStack ...
- 基于IIS构建Pyathon Web服务
本文简单叙述了在Windows下,如何利用IIS构建Python Web服务. 其主要步骤如下: 1.在IIS下构建一个站点,如图: 2.配置Python文件的处理程序,如图: 3.最后,在对应站点根 ...
- Guzzle – 构建 RESTful Web 服务的 PHP HTTP 框架
Guzzle 减轻了发送 HTTP 请求和创建 Web 服务客户端的痛苦.它包含建立一个强大的网络服务客户端的工具,包括:服务描述定义的输入和输出的 API,资源迭代器遍历分页资源,尽可能有效地发送大 ...
- WCF:为 SharePoint 2010 Business Connectivity Services 构建 WCF Web 服务(第 1 部分,共 4 部分)
转:http://msdn.microsoft.com/zh-cn/library/gg318615.aspx 摘要:通过此系列文章(共四部分)了解如何在 Microsoft SharePoint F ...
- 使用 Spring 3 MVC HttpMessageConverter 功能构建 RESTful web 服务
原文地址:http://www.ibm.com/developerworks/cn/web/wa-restful/ 简介: Spring,构建 Java™ 平台和 Enterprise Edition ...
- 如何快速搭建一个基于ServiceStack框架的web服务
ServiceStack是一个高性能的.NET Web Service 平台,能够简化开发高性能的REST (支持JSON,XML,JSV,HTML,MsgPack,ProtoBuf,CSV等消息格式 ...
- SpringBoot实战(十)之使用Spring Boot Actuator构建RESTful Web服务
一.导入依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http ...
- 基于jersey和Apache Tomcat构建Restful Web服务(二)
基于jersey和Apache Tomcat构建Restful Web服务(二) 上篇博客介绍了REST以及Jersey并使用其搭建了一个简单的“Hello World”,那么本次呢,再来点有趣的东西 ...
随机推荐
- 20165226 实验三 敏捷开发与XP实践
实验三 敏捷开发与XP实践 实验目的 一.安装alibaba 插件,解决代码中的规范问题.在IDEA中使用工具(Code->Reformate Code)格式化代码,研究一下Code菜单,比较功 ...
- limesurvey的问卷类型
- lamp与lnmp的选择
lnmp和lamp业务上的不同 由于二者仅仅是区别在于web的选择,nginx更高效,占用资源更少,详情区别查看LNMP环境应用实践 lnmp和lamp安装上的不同 生产环境中,可能会遇到lamp架构 ...
- jquery发送数组
假设keywordid_list是一个javascript数组,将它发送到keywordbatchsetting.php. $.ajax({ url:"keywordbatchsetting ...
- TIMEQUEST学习之黑金动力(四)
现在知道时序约束主要是FPGA to ic,或者ic to FPGA. 上图可以表示FPGA to IC, IC to FPGA. fpga2ic:fpga2ext 是 fpga 致 ic 信号的走线 ...
- Python的urllib和urllib2模块
Python的urllib和urllib2模块都做与请求URL相关的操作,但他们提供不同的功能.他们两个最显着的差异如下: urllib2可以接受一个Request对象,并以此可以来设置一个URL的h ...
- Eclipse免reload设置
在使用eclipse开发web项目的时候,有的时候需要通过运行看结果,但是如果项目很大,你改一句代码,也许就要重启一次,或者eclipse自动帮你reload,这样严重的影响开发的效率,这里只要修改一 ...
- springboot-shiro chapter02——springboot webmvc jsp
简介:这一节主要涉及spring boot 支持jsp, 由于对spring boot不太熟悉,走了一些弯路. 环境:IDEA15+JDK1.8+Maven3+ 代码: https://git.osc ...
- 如何清除svn的账号缓存信息(solaris)
如果我们不小心输入svn账号错误的话,后面就一直提示认证失败,不能checkout代码. 这个是因为svn把你输入的账号进行了缓存. 如果我们想重新输入新的账号,必须要清除缓存 svn存储账号的目录在 ...
- T-SQL 之 执行顺序
1.sql查询语句的处理步骤,代码清单 --查询组合字段 (5)select (5-2) distinct(5-3) top(<top_specification>)(5-1)<se ...