[REST]深入浅出REST

mikel阅读(798)

作者 Stefan Tilkov 译者 苑永凯 发布于 2007年12月25日 下午10时10分

社区
Architecture,
SOA
主题
REST,
企业架构
标签
Web服务

不 知你是否意识到,围绕着什么才是实现异构的应用到应用通信的“正确”方式,一场争论正进行的如火如荼:虽然当前主流的方式明显地集中在基于SOAP、 WSDL和WS-*规范的Web Services领域,但也有少数人用细小但洪亮的声音主张说更好的方式是REST,表述性状态转移(REpresentational State Transfer)的简称。在本文中,我不会涉及争论的话题,而是尝试对REST和RESTful HTTP应用集成做实用性的介绍。以我的经验,有些话题一旦触及就会引来众多的讨论,当涉及到这方面话题的时候,我会深入详细地阐述。

REST关键原则

大部分对REST的介绍是以其正式的定义和背景作为开场的。但这儿且先按下不表,我先提出一个简单扼要的定义:REST定义了应该如何正确地使用 (这和大多数人的实际使用方式有很大不同)Web标准,例如HTTP和URI。如果你在设计应用程序时能坚持REST原则,那就预示着你将会得到一个使用 了优质Web架构(这将让你受益)的系统。总之,五条关键原则列举如下:

  • 为所有“事物”定义ID
  • 将所有事物链接在一起
  • 使用标准方法
  • 资源多重表述
  • 无状态通信

下面让我们进一步审视这些原则。

为所有“事物”定义ID

在这里我使用了“事物”来代替更正式准确的术语“资源”,因为一条如此简单的原则,不应该被淹没在术语当中。思考一下人们构建的系统,通常会找到一 系列值得被标识的关键抽象。每个事物都应该是可标识的,都应该拥有一个明显的ID——在Web中,代表ID的统一概念是:URI。URI构成了一个全局命 名空间,使用URI标识你的关键资源意味着它们获得了一个唯一、全局的ID。

对事物使用一致的命名规则(naming scheme)最主要的好处就是你不需要提出自己的规则——而是依靠某个已被定义,在全球范围中几乎完美运行,并且能被绝大多数人所理解的规则。想一下你 构建的上一个应用(假设它不是采用RESTful方式构建的)中的任意一个高级对象(high-level object),那就很有可能看到许多从使用唯一标识中受益的用例。比如,如果你的应用中包含一个对顾客的抽象,那么我可以相当肯定,用户会希望将一个指 向某个顾客的链接,能通过电子邮件发送到同事那里,或者加入到浏览器的书签中,甚至写到纸上。更透彻地讲:如果在一个类似于Amazon.com的在线商 城中,没有用唯一的ID(一个URI)标识它的每一件商品,可想而知这将是多么可怕的业务决策。

当面对这个原则时,许多人惊讶于这是否意味着需要直接向外界暴露数据库记录(或者数据库记录ID)——自从多年以来面向对象的实践告诫我们,要将持 久化的信息作为实现细节隐藏起来之后,哪怕是刚有点想法都常会使人惊恐。但是这条原则与隐藏实现细节两者之间并没有任何冲突:通常,值得被URI标识的事 物——资源——要比数据库记录抽象的多。例如,一个定单资源可以由定单项、地址以及许多其它方面(可能不希望作为单独标识的资源暴露出来)组成。标识所有 值得标识的事物,领会这个观念可以进一步引导你创造出在传统的应用程序设计中不常见的资源:一个流程或者流程步骤、一次销售、一次谈判、一份报价请求—— 这都是应该被标识的事物的示例。同样,这也会导致创建比非RESTful设计更多的持久化实体。

下面是一些你可能想到的URI的例子:

http://example.com/customers/1234
http://example.com/orders/2007/10/776654
http://example.com/products/4554
http://example.com/processes/salary-increase-234 

正如我选择了创建便于阅读的URI——这是个有用的观点,尽管不是RESTful设计所必须的——应该能十分容易地推测出URI的含义:它们明显地标识着单一“数据项”。但是再往下看:

http://example.com/orders/2007/11
http://example.com/products?color=green 

首先,这两个URI看起来与之前的稍有不同——毕竟,它们不是对一件事物的标识,而是对一类事物集合的标识(假定第一个URI标识了所有在2007年11月份提交的定单,第二个则是绿颜色产品的集合)。但是这些集合自身也是事物(资源),也应该被标识。

注意,使用唯一、全局统一的命名规则的好处,既适用于浏览器中的Web应用,也适用于机对机(machine-to-machine,m2m)通信。

来对第一个原则做下总结:使用URI标识所有值得标识的事物,特别是应用中提供的所有“高级”资源,无论这些资源代表单一数据项、数据项集合、虚拟亦或实际的对象还是计算结果等。

将所有事物链接在一起

接下来要讨论的原则有一个有点令人害怕的正式描述:“超媒体被当作应用状态引擎(Hypermedia as the engine of application state)”,有时简写为HATEOAS。(严格地说,这不是我说的。)这个描述的核心是超媒体概念,换句话说:是链接的思想。链接是我们在HTML中常见的概念,但是它的用处绝不局限于此(用于人们网络浏览)。考虑一下下面这个虚构的XML片段:


23


 

如果你观察文档中product和customer的链接,就可以很容易地想象到,应用程序(已经检索过文档)如何“跟随”链接检索更多的信息。当然,如果使用一个遵守专用命名规范的简单“id”属性作为链接,也是可行的——但是仅限于应用环境之内。使用URI表示链接的优雅之处在于,链接可以指向由不同应用、不同服务器甚至位于另一个大陆上的不同公司提供的资源——因为URI命名规范是全球标准,构成Web的所有资源都可以互联互通。

超媒体原则还有一个更重要的方面——应用“状态”。简而言之,实际上服务器端(如果你愿意,也可以叫服务提供者)为客户端(服务消费者)提供一组链 接,使客户端能通过链接将应用从一个状态改变为另一个状态。稍后我们会在另一篇文章中探究这个方面的影响;目前,只需要记住:链接是构成动态应用的非常有 效的方式。

对此原则总结如下:任何可能的情况下,使用链接指引可以被标识的事物(资源)。也正是超链接造就了现在的Web。

使用标准方法

在前两个原则的讨论中暗含着一个假设:接收URI的应用程序可以通过URI明确地一些有意义的事情。如果你在公共汽车上看到一个URI,你可以将它输入浏览器的地址栏中并回车——但是你的浏览器如何知道需要对这个URI做些什么呢?

它知道如何去处理URI的原因在于所有的资源都支持同样的接口,一套同样的方法(只要你乐意,也可以称为操作)集合。在HTTP中这被叫做动词 (verb),除了两个大家熟知的(GET和POST)之外,标准方法集合中还包含PUT、Delete、HEAD和OPTIONS。这些方法的含义连同 行为许诺都一起定义在HTTP规范之中。如果你是一名OO开发人员,就可以想象到RESTful HTTP方案中的所有资源都继承自类似于这样的一个类(采用类Java、C#的伪语法描述,请注意关键的方法):

class Resource {
Resource(URI u);
Response get();
Response post(Request r);
Response put(Request r);
Response delete();
} 

由于所有资源使用了同样的接口,你可以依此使用GET方法检索一个表述(representation)——也 就是对资源的描述。因为规范中定义了GET的语义,所以可以肯定当你调用它的时候不需要对后果负责——这就是为什么可以“安全”地调用此方法。GET方法 支持非常高效、成熟的缓存,所以在很多情况下,你甚至不需要向服务器发送请求。还可以肯定的是,GET方法具有幂等性[译 注:指多个相同请求返回相同的结果]——如果你发送了一个GET请求没有得到结果,你可能不知道原因是请求未能到达目的地,还是响应在反馈的途中丢失了。 幂等性保证了你可以简单地再发送一次请求解决问题。幂等性同样适用于PUT(基本的含义是“更新资源数据,如果资源不存在的话,则根据此URI创建一个新 的资源”)和Delete(你完全可以一遍又一遍地操作它,直到得出结论——删除不存在的东西没有任何问题)方法。POST方法,通常表示“创建一个新资 源”,也能被用于调用任过程,因而它既不安全也不具有幂等性。

如果你采用RESTful的方式暴露应用功能(如果你乐意,也可以称为服务功能),那这条原则和它的约束同样也适用于你。如果你已经习惯于另外的设计方式,则很难去接受这条原则——毕竟,你很可能认为你的应用包含了超出这些操作表达范围的逻辑。请允许我花费一些时间来让你相信不存在这样的情况。

来看下面这个简单的采购方案例子:

Sample Scenario

可以看到,例子中定义了两个服务程序(没有包含任何实现细节)。这些服务程序的接口都是为了完成任务(正是我们讨论的 orderManagement和CustomerManagement服务)而定制的。如果客户端程序试图使用这些服务,那它必须针对这些特定接口进行 编码——不可能在这些接口定义之前,使用客户程序去有目的地和接口协作。这些接口定义了服务程序的应用协议(application protocol)。

在RESTful HTTP方式中,你将通过组成HTTP应用协议的通用接口访问服务程序。你可能会想出像这样的方式:

Sample Scenario, done RESTfully

可以看到,服务程序中的特定操作被映射成为标准的HTTP方法——为了消除歧义,我创建了一组全新的资源。“这是骗人的把戏”,我听见你叫嚷着。 不,这不是欺骗。标识一个顾客的URI上的GET方法正好相当于getCustomerDetails操作。有人用三角形形象化地说明了这一点:

Knobs one can turn

把三个顶点想象为你可以调节的按钮。可以看到在第一种方法中,你拥有许多操作,许多种类的数据以及固定数量的“实例”(本质上和你拥有的服务程序数 量一致)。在第二种方法中,你拥有固定数量的操作,许多种类的数据和许多调用固定方法的对象。它的意义在于,证明了通过这两种方式,你基本上可以表示任何 你喜欢的事情。

为什么使用标准方法如此重要?从根本上说,它使你的应用成为Web的一部分——应用程序为Web变成Internet上最成功的应用所做的贡献,与 它添加到Web中的资源数量成比例。采用RESTful方式,一个应用可能会向Web中添加数以百万计的客户URI;如果采用CORBA技术并维持应用的 原有设计方式,那它的贡献大抵只是一个“端点(endpoint)”——就好比一个非常小的门,仅仅允许有钥匙的人进入其中的资源域。

统一接口也使得所有理解HTTP应用协议的组件能与你的应用交互。通用客户程序(generic client)就是从中受益的组件的例子,例如curl、wget、代理、缓存、HTTP服务器、网关还有Google、Yahoo!、MSN等等。

总结如下:为使客户端程序能与你的资源相互协作,资源应该正确地实现默认的应用协议(HTTP),也就是使用标准的GET、PUT、POST和Delete方法。

资源多重表述

到目前为止我们一直忽略了一个稍微复杂的问题:客户程序如何知道该怎样处理检索到的数据,比如作为GET或者POST请求的结果?原因是,HTTP 采取的方式是允许数据处理和操作调用之间关系分离的。换句话说,如果客户程序知道如何处理一种特定的数据格式,那就可以与所有提供这种表述格式的资源交 互。让我们再用一个例子来阐明这个观点。利用HTTP内容协商(content negotiation),客户程序可以请求一种特定格式的表述:

GET /customers/1234 HTTP/1.1
Host: example.com
Accept: application/vnd.mycompany.customer+xml  

请求的结果可能是一些由公司专有的XML格式表述的客户信息。假设客户程序发送另外一个不同的请求,就如下面这样:

GET /customers/1234 HTTP/1.1
Host: example.com
Accept: text/x-vcard 

结果则可能是VCard格式的客户地址。(在这里我没有展示响应的内容,在其HTTP Content-type头中应该包含着关于数据类型的元数据。)这说明为什么理想的情况下,资源表述应该采用标准格式——如果客户程序对HTTP应用协 议和一组数据格式都有所“了解”,那么它就可以用一种有意义的方式与世界上任意一个RESTful HTTP应用交互。 不幸的是,我们不可能拿到所有东西的标准格式,但是,或许我们可以想到在公司或者一些合作伙伴中使用标准格式来营造一个小环境。当然以上情况不仅适用于从 服务器端到客户端的数据,反之既然——倘若从客户端传来的数据符合应用协议,那么服务器端就可以使用特定的格式处理数据,而不去关心客户端的类型。

在实践中,资源多重表述还有着其它重要的好处:如果你为你的资源提供HTML和XML两种表述方式,那这些资源不仅可以被你的应用所用,还可以被任意标准Web浏览器所用——也就是说,你的应用信息可以被所有会使用Web的人获取到。

资源多重表述还有另外一种使用方式:你可以将应用的Web UI纳入到Web API中——毕竟,API的设计通常是由UI可以提供的功能驱动的,而UI也是通过API执行动作的。将这两个任务合二为一带来了令人惊讶的好处,这使得 使用者和调用程序都能得到更好的Web接口。

总结:针对不同的需求提供资源多重表述。

无状态通信

无状态通信是我要讲到的最后一个原则。首先,需要着重强调的是,虽然REST包含无状态性(statelessness)的观念,但这并不是说暴露功能的应用不能有状态——
事 实上,在大部分情况下这会导致整个做法没有任何用处。REST要求状态要么被放入资源状态中,要么保存在客户端上。或者换句话说,服务器端不能保持除了单 次请求之外的,任何与其通信的客户端的通信状态。这样做的最直接的理由就是可伸缩性—— 如果服务器需要保持客户端状态,那么大量的客户端交互会严重影响服务器的内存可用空间(footprint)。(注意,要做到无状态通信往往需要需要一些 重新设计——不能简单地将一些session状态绑缚在URI上,然后就宣称这个应用是RESTful。)

但除此以外,其它方面可能显得更为重要:无状态约束使服务器的变化对客户端是不可见的,因为在两次连续的请求中,客户端并不依赖于同一台服务器。一 个客户端从某台服务器上收到一份包含链接的文档,当它要做一些处理时,这台服务器宕掉了,可能是硬盘坏掉而被拿去修理,可能是软件需要升级重启——如果这 个客户端访问了从这台服务器接收的链接,它不会察觉到后台的服务器已经改变了。

理论上的REST

我承认:以上我所说的REST不是真正的REST,而且我可能有点过多地热衷于简单化。但因为我想有一个与众不同的开场,所以没有在一开始就介绍其正式的定义和背景。现在就让我们稍微简要地介绍一下这方面的内容。

首先,先前我并没有明确地区分HTTP、RESTful HTTP和REST。要理解这些不同方面之间的关系,我们要先来看看REST的历史。

Roy T. Fielding在他的博士学位论文(实际上你应该访问这个链接——至少对于一篇学术论文来说,它是相当易读的。此论文已被翻译成中文) 中定义了术语REST。Roy曾是许多基本Web协议的主要设计者,其中包括HTTP和URIs,并且他在论文中对这些协议提出了很多想法。(这篇论文被 誉为“REST圣经”,这是恰当的——毕竟,是作者发明了这个术语,所以在定义上,他写的任何内容都被认为是权威的。)在论文中,Roy首先定义一种方法 论来谈论架构风格——高级、抽象的模式,来表达架构方法背后的核心理念。每一个架构风格由一系列的约束(constraints)定义形成。架构风格的例子包括“没有风格”(根本没有任何约束)、管道和过滤器(pipe and filter)、客户端/服务器、分布式对象以及——你猜到它了——REST。

如果对你来说这些听起来都太抽象了,那就对了——REST在本质上是一个可以被许多不同技术实现的高层次的风格,而且可以被实例化——通过为它的抽 象特性赋上不同的值。比如,REST中包含资源和统一接口的概念——也就是说,所有资源都应该对这些相同的方法作出反应。但是REST并没有说明是哪些方 法,或者有多少方法。

REST风格的一个“化身”便是HTTP(以及一套相关的一套标准,比如URI),或者稍微抽象一些:Web架构自身。接着上面的例子,HTTP使 用HTTP动词作为REST统一接口的“实例”。由于Fielding是在Web已经(或者至少是大部分)“完善”了之后才定义的REST风格,有人可能 会争论两者是不是100%的匹配。但是无论如何,整体上来说Web、HTTP和URI仅仅是REST风格的一个主要实现。不过,由于Roy Fielding即是REST论文的作者,又对Web架构设计有过深远的影响,两者相似也在情理之中。

最后,我在前面一次又一次地使用着术语“RESTful HTTP”,原因很简单:许多使用HTTP的应用因为一些理由并没有遵循REST原则,有人会说使用HTTP而不遵循REST原则就等同于滥用HTTP。 当然这听起来有点狂热——事实上违反REST约束的原因通常是,仅仅因为每个约束带来的设计权衡可能不适合于一些特殊情况。但通常,违背REST约束的原 因可归咎于对其好处认知的缺乏。来看一个明显的反面案例:使用HTTP GET调用类似于删除对象的操作,这违反了REST的安全约束和一般性常识(客户程序不应为此负责,服务器端开发人员大概不是有意而为之)。但在随后的文 章中,我会提及更多这样或那样的对HTTP的滥用。

总结

本文试图对REST(Web架构)背后的概念提供快速的介绍。RESTful HTTP暴露功能的方式与RPC、分布式对象以及Web Services是不相同的;要真正理解这些不同是需要一些心态的转变。不管你构建的应用是仅仅想暴露Web UI还是想把API变成Web的一份子,了解下REST的原则还是有好处的。

Stefan Tilkov是InfoQ SOA社区的首席编辑,并且是位于德国和瑞士的innoQ公司的共同创始人、首席顾问和REST狂热分子首领。

查看英文原文A Brief Introduction to REST

[REST]什么是REST

mikel阅读(764)

什么是REST?
  REST是Roy Fielding在他的博士论文中提出的词汇,是对网络系统构架的一个描述。REST是表现性状态传输首字母缩写(Representational State Transfer)。
Roy Feilding这么解释表现性状态传输的意义:

引用 “表现性状态传输试图描述一个设计优良的Web是如何运转的:用户在web网络(虚拟状态机)里通过点击链接处理应用(状态传输),结果就是传输并渲染下一个页面给用户(应用程序的下一个状态的表现性)。“

REST的目的
  REST的目的是寻找让Web如此成功的特性。然后再使用这些特性指导Web变革。
REST是一个结构设计,而不是一个标准
   REST不是一个标准,你永远也不会看到W3C发布REST白皮书。你也不会看到微软或者IBM销售REST开发工具。为什么?REST它仅仅是一个结 构设计而不是一个标准。你不能控制这个设计,你仅能够理解并且应用在你的Web服务中。(类似的C/S结构也是一种结构设计,而不是一个C/S标准)。
虽然REST不是一个标准,但它确实使用标准:
HTTP
URL
XML/HTML/GIF/JPEG等等(状态表现)
text/xml, text/html, image/gif, image/jpeg等等(MIME类型)
经典的REST系统
  Web就是REST系统,有很多你使用了很多年的服务就是基于REST的Web服务,例如:订书服务、搜索服务、在线电子字典。
  REST是关于Web的一张“大蓝图”,它不负责处理具体的执行细节(例如:使用Java还是CGI来实现一个Web服务)。所以让我们用REST“大蓝图”的观点来设计一个Web服务。
REST Web服务的特征
C/S结构:一个完全基于交互的设计
无状态:每个发送给服务器的信息必须包含服务器处理所需的所有信息,不能通过在服务器保存相关信息而获益。
缓存:为了提供网络的效率,响应必须标志出是否可以缓存。
统一的接口:所有的资源都可以通过一个通用的接口访问(例如:HTTP GET、POST、PUT、Delete)。
命名的资源:组成系统的资源使用URL来命名。
互联资源表现性:资源的表现性通过URL实现互联,因此客户可以一个状态接着一个状态处理。
组件层:可以在客户和资源间插入用于提高效率,增强安全的的中间件,象代理服务、缓存服务、网关等。
REST Web服务设计原则
1.以REST网络建立Web服务的关键(例如Web)是确定想作为服务展现的所有概念化的实体。
2.为每个资源提供URL。资源应该是名词,不是动词
3.根据客户处理资源的方式分类,可以分为客户仅接收资源的表现性,客户能够修改(增加)资源。对于前者,提供HTTP GET方法访问。对于后者,提供HTTP POST、PUT和(或)Delete。

我们在 Web 应用中处理来自客户端的请求时,通常只考虑 GET 和 POST 这两种 HTTP 请求方法。实际上,HTTP 还有 HEAD、PUT、Delete 等请求方法。而在 REST 架构中,用不同的 HTTP 请求方法来处理对资源的 CRUD(创建、读取、更新和删除)操作:

  • POST: 创建
  • GET: 读取
  • PUT: 更新
  • Delete: 删除

经过这样的一番扩展,我们对一个资源的 CRUD 操作就可以通过同一个 URI 完成了:

http://www.example.com/photo/logo(读取)
仍然保持为 [GET] http://www.example.com/photo/logo

http://www.example.com/photo/logo/create(创建)
改为 [POST] http://www.example.com/photo/logo

http://www.example.com/photo/logo/update(更新)
改为 [PUT] http://www.example.com/photo/logo

http://www.example.com/photo/logo/delete(删除)
改为 [Delete] http://www.example.com/photo/logo

从而进一步规范了资源标识的使用。

通过 REST 架构,Web 应用程序可以用一致的接口(URI)暴露资源给外部世界,并提供对资源的操作服务。这对于以资源为中心的 Web 应用来说非常重要。例如照片共享网站、用户社区等。

 

 

4.所有通过HTTP GET访问的资源应该是无副作用的,也就是说,这些资源仅仅向客户返回一个资源的表现性,客户调用他们不应该对它们产生影响。
5.没有孤立的人,同样,没有孤立的表现性。换言之,在资源的表现性中提供链接,让客户能更深入的获取更多的信息,或者相关信息。
6.逐步的提供数据,不应该在一个文档里提供所有的内容,可以为更详细的信息提供链接。
7.使用模式(DTD、W3C Schema、RelaxNG或者Schematron)指定响应数据的格式。如果服务需要POST或PUT,也同样使用一个模式规定这些响应。
8.通过WSDL文档或者HTML页面描述如何调用你的服务。

(转载)

[REST]REST构架风格介绍之一:状态表述转移

mikel阅读(843)

转载:http://www.cnblogs.com/weidagang2046/archive/2009/05/08/1452322.html

REST(Representational State Transfer)HTTP协议的作者Roy Fielding博士在其博士论文中提出的一种互联网应用构架风格。与以远程对象为核心的ORB和以服务为核心的SOA相比,以资源为核心的REST让我们从崭新的视角审视互联网应用。REST互联网应用量身定做的简洁模型和其高扩展性,为互联网应用构架设计和异构系统集成设计带来了一股清新的空气。

本文希望与大家分享REST风格构架设计的体会,错误不足之处欢迎批评指正。

语言生态环境

计算机发展至今,产生了许许多多不同的语言,每种语言都定义了自己独特的生态环 境。在这个生态环境内,所有程序共享相同的类型系统、运行时环境、并发模型等。虽然所有程序的本质是相同的:从问题领域到机器领域的映射,但无法回避的是 不同生态环境的程序很难跨越彼此的边界。同样是int,在AB语言通常截然不同(CLRJVM能部分解决类型共享问题),更不用说A语言具有但B语言不具有的某些语言特性(CLRJVM没法解决)

当系统可以在单一的生态环境中自给自足时,跨越生态环境的问题并不存在;但在多数互联网应用中,系统的各个部分通常既是生产者又是消费者,必须要打破生态环境的界限才能相互协作。比如,A公司的Service A,需要对外提供服务,而Service A又依赖于B公司的Service BC公司的Service C;由于无法保证不同公司都采用同样的语言,因此各服务的接口必须保证语言无关性。在我所了解的范围内,有3种跨域生态环境的方式:

1.      ORB(Object Request Broker)

CORBA为代表,其核心概念是远程对象(remote object)。熟悉.Net Remoting的朋友应该能体会其风格(需要说明的是.Net Remoting只跨越微软的生态环境)。不同生态环境的程序可以像调用本地对象一样调用远程对象代理的方法,ORB会负责连接到远程的对象,并处理数据的序列化与反序列化。

2.      SOA

其核心概念是服务(Service)。比如:我们要提供整数加法Web服务,我们会很自然地想到通过类似下面的url来表达服务接口:

http://www.example.com/add?a=1&b=2

并通过xml结构表达结果:

<sum>3</sum>

3.      REST

其核心概念是资源(Resource)。在REST的世界中,没有服务的概念,同样是上面的例子,在REST的世界中,http://www.example.com/add?a=1&b=2是一个xml网页资源的id,而非服务的接口。所以,REST让我们从资源的角度来审视互联网应用并指导我们的设计,这是它与ORB和SOA最本质的区别。下面我们将更详细的介绍,REST以资源为核心的模型和相应的设计风格。

状态表述转移

REST的世界中,互联网就是一个巨大的状态机:每个网页是其一个状态(资源);url则是状态的表述。互联网应用是地从一个状态迁移到下一个状态的状态转移过程。这个状态表述转移过程正是互联网形成初期通过超链接在静态网页间浏览跳转的page->link->page->link…模式。REST风格应用可以实现交互,但它却天然地具有服务器无状态的特征。PS:更准确地说,除资源本身是状态以外,服务器不需要保存会话状态,本文提到的无状态服务均指无会话状态服务。在状态迁移的过程中,服务器不需要记录任何Session,所有的状态都通过url的形式记录在了客户端。

举个例子:一个心理测试的应用,需要用户做2次选择题,每次可选AB两种答案,2次选择完毕之后将告知用户属于何种心理类型。

如果按SOA的服务思维,很容易想到在服务器端保存Session,每次选择以后修改Session。但如果按REST的状态转移思维方式,我们会得出这样设计:

每一个页面表示一个状态(存在于客户端),页面包含了到下一个页面的超链接,当用户选a和选b时分别转移到相应的状态。这样,所有的会话状态其实都是通过url的形式保存在了客户端,服务器端实现了无状态模式。需要说明的是,虽然上图有7个状态,但并非一定需要在服务器预先生成7个静态页面,它们完全可以是动态页面,这不影响状态转移的概念模型以及服务器无状态的特征。

有构架设计经验的朋友应该很清楚,与有状态服务设计相比,无状态服务容易实现系统性能的横向扩展。通过增加硬件,部署多个无状态服务,并进行load balance不会受到制约;而有状态服务模式,Session的存储、共享都会带来性能瓶颈,且无法通过增加硬件消除。

Google搜索就是一个典型的无状态服务。试想一下,当你搜索“周杰伦”以后,Google提示你有数百万的结果,并每10条一页分成若干 页,Google会把结果保存进服务器Session吗,然后当你翻页的时候,再从Session中取吗?显然这样庞大的Session,即使是 Google也无法承受。看看Google的url就清楚了:

第一页:http://www.google.cn/search?q=%E5%91%A8%E6%9D%B0%E4%BC%A6&hl=zh-CN&newwindow=1&start=0&sa=N 

第二页:http://www.google.cn/search?q=%E5%91%A8%E6%9D%B0%E4%BC%A6&hl=zh-CN&newwindow=1&start=10&sa=N

当你点击第二页的链接时,无非是从一个状态跳到了下一个状态而已。对于Google而言,其实是一条新的查询,而两次查询很可能是由不同的服务器在处理,而用户却感觉Google记住了会话。

最后,需要说明的是,REST风格包含了无状态服务的特征,但并非具有无状态服务特征的都是REST。SOA同样可以是无状态的,REST的核心还是资源,下一节将会继续就这个话题进行探讨,谢谢关注!

[MVC]ASP.NET MVC Performance Tips(1):RenderPartial

mikel阅读(919)

转载:http://www.cnblogs.com/Terrylee/archive/2009/05/08/ASPNET-MVC-Performance-Tips-Part1.html

背景

ASP.NET MVC中,HtmlHelper的扩展方法RenderPartial为我们使用UserControl带来了极大的方便,当我们指定一个 UserControl时,RenderPartial会在当前View文件夹下查找相应的UserControl,如果没有找到则会到Shared文件 夹下查找。然后在使用RenderPartial方法有一些性能方面的考虑,值得我们去关注。

设想有这样一个场景,一篇文章有很多个评论,在页面中我们需要呈现出一个评论列表,自然我们会定义一个评论的UserControl,如下代码所示:

Code 1:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Comment>" %>
<%@ Import Namespace="TerryLee.MvcPerformance01.Models" %>
<p>
ID: <%=Model.ID %> <br />
Author: <%=Model.Author %> <br />
Description: <%= Model.Description %>
</p>
<hr />

在页面中呈现评论列表,代码非常简单,仅仅是遍历所有的评论而已:

Code 2:

<div>
<%
     foreach (var comment in Model.Comments)
{
Html.RenderPartial("CommentsItem", comment);
}
%>
</div>

运行后效果如下,可以看到正确的输出了评论:

aspnetmvc_performance_tips_001 

性能优化1

然而当我们同时输出200条评论的时候, 却要花费大量的时间,用Stopwatch来测量一下会发现,输出200条评论花费的时间基本在210ms左右,也就是说平均每条评论的输出花费了 1ms。我们不妨看一下ASP.NET MVC的源代码,在WebFormViewEngine中当查找UserControl时,遵循如下查找模式:

Code 3:

public WebFormViewEngine() {
MasterLocationFormats = new[] {
"~/Views/{1}/{0}.master",
"~/Views/Shared/{0}.master"
};
ViewLocationFormats = new[] {
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx"
};
PartialViewLocationFormats = ViewLocationFormats;
}

所以如果我们在RenderPartial方法中,指定了UserControl的完全路径,是不是可以避免这个查找过程呢?修改Code 2代码如下所示:

Code 4:

<div>
<%
       foreach (var comment in Model.Comments)
{
Html.RenderPartial("~/Views/Shared/CommentsItem.ascx", comment);
}
%>
</div>

现在再测试一下会发现呈现200条评论的时间平均值保持在10ms左右,比前面的方式提升了近200ms。然而我们是否真的找到了解决问题的方 法?ASP.NET MVC难道不对查找的View路径进行缓存?带着这样的疑问,我们在ASP.NET MVC源代码VirtualPathProviderViewEngine的构造函数中,找到这样一段代码:

Code 5:

protected VirtualPathProviderViewEngine() {
if (HttpContext.Current == null || HttpContext.Current.IsDebuggingEnabled) {
ViewLocationCache = DefaultViewLocationCache.Null;
}
else {
ViewLocationCache = new DefaultViewLocationCache();
}
}

这里的判断说明如果启用了Debug模式,将会使用NullViewLocationCache,即不进行缓存,否则会使用DefaultViewLocationCache对View路径进行缓存。所以上面的测试结果都是基于Debug模式:

Code 6:

<compilation debug="true">

如果关闭了Debug模式,测试结果又该如何呢?使用下面代码关闭Debug模式:

Code 7:

<compilation debug="false">

再次进行测试,会发现使用Code 2代码呈现200条评论时,花费的时间平均值也是在10ms左右。所以在使用RenderPartial方法时,大可不必为了提升性能而指定 UserControl的完全路径,ASP.NET MVC已经为我们做好了这一切,我们要做的仅仅是在发布到生产环境时,别忘了关闭Debug模式!在本示例中,开启Debug和关闭Debug模式在一次调用时的性能差距如下图所示:

aspnetmvc_performance_tips_002 

性能优化2

现在回过头来看前面的代码,其实并没有做什么性能优化,仅仅时给大家提个醒而已。在Code 2中,我们的遍历代码放在了主页面中,即在每一次迭代中调用RenderPartial方法,尽管ASP.NET MVC在RenderPartial时,对于UserControl路径做了缓存,但是200次的调用仍然有不小的开销。如果我们的遍历代码放在 UserControl中,而在主页面中只进行一次调用RenderPartial方法,结果又将如何呢?修改UserControl为下代码所示:

Code 8:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IList<Comment>>" %>
<%@ Import Namespace="TerryLee.MvcPerformance01.Models" %>
<%
    foreach(Comment comment in Model)
{
%>
<p>
ID: <%= comment.ID%> <br />
Author: <%= comment.Author%> <br />
Description: <%= comment.Description%>
</p>
<%} %>
<hr />

这样在主页面中,只进行一次RenderPartial调用,如下代码所示:

<div>
<%
     Html.RenderPartial("CommentsItem", Model.Comments);
%>
</div>

此时再次测试,可以看到呈现200条评论所花费的时间不足1ms!为了直观期间,我们仍然使用图形表示如下:

aspnetmvc_performance_tips_003 

从上图中可以看到,通过在UserControl中进行遍历,减少RenderPartial方法调用,带来的性能提升还是非常可观的。

总结

本文主要讨论在ASP.NET MVC中使用RenderPartial方法时的一些性能问题,记住两点:一是在ASP.NET MVC应用程序发布到生产服务器时,别忘了关闭Debug模式(对于ASP.NET WebForm应用程序也是一样);二时尽可能的减少调用RenderPartial方法的次数,如通过在UserControl中进行遍历等方法。希望 对大家有用。

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[Flash]Flash实现文件上传

mikel阅读(869)

 

********************************************************************
*                                                 版权声明
*
* 本文以Creative Commons的知识共享署名-非商业性使用-相同方式共享发布,请严格遵循该授权协议。
* 本文首发于博客园, 此声明为本文章中不可或缺的一部分。
* 作者网名:    浪子
* 作者EMAILdayichen (at)163.com
* 作者BLOG:  Http://Www.Cnblogs.Com/Walkingboy
*
********************************************************************

[Flash FileUpload]用flash.net.FileReference实现无刷新文件上传

-Written by http://walkingboy.cnblogs.com/ (07-02-07)

摘要:

还在用UpdatePanel嘛?是否还为文件上传苦恼?

还在用Callback嘛?是否对文件上传无计可施?

还在用Ajax上传组件嘛?是否为其不稳定性而头疼不已?

兄弟忘了这些吧,让我们拾起古老的Flash,跟我一道将积蓄已久的无奈、郁闷踩于脚下……

一、楔子

一直都无法忘怀那段痴迷Flash的大学时代,从认识动画,到ActionScript,再到苦练鼠绘,所有付出的时间和睡眠都代表了我对 Flash的情有独钟,曾经一直都在幻想毕业后可以从事Flash编程工作。可能自己的先天美感不足或者运气不佳,最终还是远离了自己一直钟爱的 Flash。

时隔多年,Flash有了长足的发展,Flex更是呈现一片喜人的景象。

但是个人认为,如果Flash定位为富客户端,而不掺合服务端的推广,我相信现在的很多js类库将失去他们的市场。

喂,谁的臭袜子,稍微理解下我沉浸往事,不能自拔的心情嘛:)

二、上传难题

以前用UpdatePanel的时候,涉及到上传都只能在做一个小页面用Postback来做;

现在用Callback,还是只能使用新页面在Postback;

尝试过好几个Ajax 上传组件,最终败倒在其不稳定下。

昨天偶在codeproject查找资料,看到Flash 上传文件的介绍,才突然想起这个被自己遗忘在角落里的咚咚。

察看了下Flash 的API,发现FileReference和FileReferenceList对文件的上传支持已经相当的好了。 

事件摘要
事件        说明
 
onCancel = function(fileRef:FileReference) {}
当用户取消文件浏览对话框时调用。
 
onComplete = function(fileRef:FileReference) {}
当上载或下载操作成功完成时调用。
 
onHTTPError = function(fileRef:FileReference, httpError:Number) {}
当上载由于 HTTP 错误而失败时调用。
 
onIOError = function(fileRef:FileReference) {}
当发生输入/输出错误时调用。
 
onOpen = function(fileRef:FileReference) {}
当上载或下载操作开始时调用。
 
onProgress = function(fileRef:FileReference, bytesLoaded:Number, bytesTotal:Number) {}
在文件上载或下载操作期间定期调用。
 
onSecurityError = function(fileRef:FileReference, errorString:String) {}
当上载或下载由于安全错误而失败时调用。
 
onSelect = function(fileRef:FileReference) {}
当用户从文件浏览对话框选择要上载或下载的文件时调用。
 
 

基本上上传文件所需要的功能都有了。

三、SWF FileUpload

很久没有写ActionStcript,变得好生疏了,熟悉了一个下午才算缓过气来了。定下了这个上传组件的需求:

接受Handler:支持内嵌的HttpHandler处理和自定义的Aspx处理(提供传递参数)

进度条显示:计算总数和已上传数

提供结束JS事件:上传结束触发指定的js方法,并将文件名作为参数

花了一个晚上才写好这个swf,调用相当的简单 

     内嵌HttpHandler,不做任何处理的调用
         <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0"
                width="250" height="80" id="SWFFileUpload" align="middle">
                <param name="allowScriptAccess" value="sameDomain" />
                <param name="movie" value="SWFFileUpload.swf" />
                <param name="quality" value="high" />    
                <param name="FlashVars" value="CompletedFunction=OnCompleted">        
                <embed src="SWFFileUpload.swf" name="fileUpload1" align="middle" allowscriptaccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
            </object>

 使用内置的HttpHandler,需要在WebConfig配置HttpHandler信息: 

<httpHandlers>
    <add verb="*" path="SWFFileUpload.axd" type="SWFFileUpload.SWFFileUpload" validate="false"/>
</httpHandlers>

 

 然后文件会默认被上传到root/UploadFiles/底下,文件名与客户端文件名同,同名则覆盖 

        指定HttpHandler,指定参数    
        <br />
             <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0"
                width="250" height="80" id="Object1" align="middle">
                <param name="allowScriptAccess" value="sameDomain" />
                <param name="movie" value="SWFFileUpload.swf" />
                <param name="quality" value="high" />
                <param name="wmode" value="transparent">
                <%--flash组件的参数传递:
                    UploadPage:自定义的ASPX文件接受Handler
                    Args:传递到UploadPage的参数,最终以QueryString的形式传递,以;分割
                    CompletedFunction:上传结束后调用的js方法
                    FileExtension:上传文件类型过滤,以;分割
                    --%>
                <param name="FlashVars" value="UploadPage=CustomerHandler.aspx&Args=name=cdy;blog=walkingboy.cnblogs.com&CompletedFunction=OnCompleted&FileExtension=*.jpg;*.txt">
                <embed src="SWFFileUpload.swf" name="fileUpload2" align="middle"
                    allowscriptaccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
            </object>

         如果文件大的话,需要在webconfig配置(Macromedia官方声称可以支持100M的上传) 

<httpRuntime maxRequestLength="1550000"/>

 

四、扩展&Demo

目前我只做了单文件的上传,可以利用FileReferenceList将其扩展为多文件上传。

如果你的IE打了最新的补丁,你可能发现出现“单击以激活并使用此控件”的问题,可以考虑封装一个js类,来动态Writer swf object,就可以搞定这个问题。 

function FileUpload(){
return{
     Show:function(){
    //TODO:
     },
     Hide:function(){
    //TODO:
     }
}
}();

DEMO代码下载:SWFFileUpload.WetTest.rar
有些朋友使用过程中出现问题,没办法得到真正的错误信息,现将flash的源代码fla上传,有问题的朋友自己测试下吧: SwfFileUpload.fla updated by langzi at 07.11.21 
 Update 07.12.19 原来上传的swffileupload.fla丢失了,重新上传。

[AR] ARToolKit 非官方安装指南(转载)

mikel阅读(1385)

安装并配置ARToolKit

  • 安装介绍
  • 编译toolkit
    • Windows
    • Linux/SGI Irix
    • Mac OS X
  • 运行例子和工具

安装介绍

ARToolKit的核心部分是一组可供应用程序调用的函数库。出于这个理 由,ARToolKit以源代码的方式发布。所以,你需要对它进行编译使之工作于你的平台。因此,你需要一个开发环境。开源开发环境(如GCC)可工作于 任何平台,你可以选择使用它来进行编译。当然,ARToolKit也支持在Microsoft Visual Studio中进行编译。

尽管ARToolKit为各种平台提供了类似的功能,安装方法却不尽相同。本文档的这个部分就是介绍如何在不同平台上安装并配置ARToolKit。

要安装并使用ARToolKit,你的机器、操作系统和平台必须满足基本要求。你的硬件必须 能获取视频流,并且CPU性能要足够好,以便同时进行图像的处理和显示。在软件方面需要满足一些(软件包的)依赖关系,否则会导致编译错误。主要的依赖关 系都是跨平台的(如OpenGL和GLUT),其他的依赖关系需要根据你自己的操作系统来满足(如DirectShow,V4L,QuickTime)

下面的部分将具体列出各操作系统中的依赖关系。

 

编译ToolKit

在Windows中编译

安装前的准备:

 需满足的软件包  安装指导
 开发环境  Microsoft Visual Studio 6和Microsoft Visual Studio .NET 2003都可以。也可以使用开源开发环境(例如Cygwin, http://www.cygwin.com/
DSVideoLib-0.0.8b-win32

在Win系统中,DSVideoLib是用来和摄像头驱动进行通信的包。ARToolKit 2.71需要使用DSVideoLib-0.0.8b或更新的版本。DSVideoLib的源代码和二进制包在ARToolKit downloads page on sourceforge可以下载到。

GLUT

确定GLUT运行包和SDK包都正确安装了。如果没有安装,可以在http://www.xmission.com/~nate/glut.html下载GLUT的二进制包。

在你的系统目录下(如c:\windows\system32)察看是否有glut32.dll,如果有,说明GLUT运行包已经被安装了。

在VC++的安装目录下(Include\gl\glut.h和Lib\glut32.lib)察看glut.h与glut32.lib是否存在。如果存在,说明GLUT SDK已经被安装了。

DirectX Runtime

Windows XP下是默认安装DirectX运行期包的。如果没有,请在microsoft网站下在安装DirectX 9.0b或更新版本的运行期包。

视频采集设备

安装摄像头和相关驱动。确保你的摄像头有VFW驱动或WDM驱动。确认方法是运行amcap.exe(这个程序在DirectX SDK中,Samples\C++\DirectShow\Bin目录下)。从Devices中可以察看到设备的状态(见下图)。

(可选项,用于VRML渲染) OpenVRML-0.14.3-win32

OpenVRML的源代码和二进制包可以在ARToolKit downloads page on sourceforge下载

编译ARToolKit:

按照以下步骤编译ARToolKit. Build:

1。将ARToolKit.zip解压到任一的目录下。为叙述方便,后面用{ARToolKit}代替该目录。

2。把DSVideoLib.zip也解压到{ARToolKit}。确保解压后的文件在名为“DSVL”的目录下。

3。把{ARToolKit}\DSVL\bin下的DSVL.dll和DSVLd.dll拷贝到{ARToolKit}\bin下。

4。把GLUT DLL拷贝到\Windows\System32\目录下,把GLUT SDK的.h和.lib文件放到VStudio的相应目录下(参考前表)

5。运行脚本{ARToolKit}\Configure.win32.bat,自动建立include/AR/config.h。

6。打开ARToolKit.sln(如果开发环境是VS.NET)或者ARToolkit.dsw(VS6的情况)。

7。编译toolkit.。

VRML渲染库和例子根据需要进行编译(libARvrml 和 simpleVRML)。步骤如下:

1。把OpenVRML.zip解压到{ARToolKit}。

2。把js32.dll从{ARToolKit}\OpenVRML\bin中拷贝到{ARToolKit}\bin。

3。在 VS配置管理器(configuration manager)中激活libARvrml和simpleVRML项目,然后编译。

 

运行例子和工具

当前的ARToolKit发布版本并没有要求把ARToolKit安装在特定的位置。在你编译自己的应用程序的时候,应该保证能找到ARToolKit。如果把ARToolKit编译为静态库,它将会被连接到所有你编译的程序中去。

为了使用ARToolKit,你需要有做一些“标志物”:例子程序使用的标志物放在 patterns目录下。你可以用把它打印出来。这些标志对你以后的开发也是有用的。ARToolKit需要一个不易形变的标志物,所以简单的做法是把标 志物粘在硬卡片上。然后,使用/bin目录下的graphicsTest来测试ARToolKit的图形部分是否正常工作。如果工作正常的话,应该显示一 个旋转的茶壶。

这个测试用来测试你的摄像头对ARToolKit的的图形模块的支持。图形模块使用了OpenGL。最小的允许幀率是15fps。低于这个数值会明显的限制ARToolKit渲染模块的正常工作(参考FAQ)。除此之外,还需要测试视频熟如是否正常、视频是否能显示。在/bin目录下的videoTest可以完成上述测试。如果没有错误的话,应该出现一个视频窗口,显示出摄像头采集的内容。这个测试用来测试你的摄像头对ARToolKit视频模块和图形模块的支持。

如果没有显示,可能是你的摄像头没有正确配置导致其不能正常工作(参考FAQ

第一个例子

  • 介绍
  • 运行ARToolKit
  • simpleTest的输出

介绍
当ARToolKit正常安装后,在/bin目录下有一个叫simpleTest(或simple,根据版本的不同名字有不同)的 程序可以展示ARToolKit的功能。不过你还需要把hiroPatt.pdf中的标志物打印出来。为了获得更好的效果,推荐把它粘在一个平的硬卡片 上。

在任何情况下,这个程序的输出都是一样的。所以本章的最后一个部分给出了程序在不同平台上的输出。

运行ARToolKit

运行方法,目前只有两种:一种是直接单/双击;一种是在控制台里运行。后一种要更好,因为从命令行启动会给出ARToolKit的错误和标准输出流信息(对ARToolKit来说很有用)。每个平台都提供了一个对话框用来在运行主AR循环之前设置视频。

Windows
双击simple.exe,会打开一个控制台窗口,当摄像头被检测出来后,会显示如下所示的对话框。也可以从“开始->程序->附件->命令行窗口”(winxp中文版)里运行simple.exe。

 

 

在这个对话框中,你可以设置视频输出的尺寸和格式。需要注意的是,最好使用与ARToolKit定位相同的格式,这样会会一些(RGB)。某些摄像头还允许你改变帧率。默认情况下,该对话框的设置与你先前视频输入的设置相同。此设置可能会引起一些问题(参考FAQ)。
Linux

如果你安装了gnome或KDE桌面环境,也可以直接双击运行simpleTest(不过这样运行看不到错误和输出流信息)。也可以在终端中运行它。如果你安装的是V4L,会显示如下的对话框。

在这个对话框中,你可以设置视频输出的尺寸和格式。需要注意的是,最好使用与ARToolKit定位相同的格式,这样会会一些(RGB)。某些摄像头还允许你改变帧率。默认情况下,该对话框的设置与你先前视频输入的设置相同。此设置可能会引起一些问题(参考FAQ).

MacOS

On MacOS X double click on the simple icon in the bin directory from your mac explorer. A console window will open and when the camera is detected the follow dialog will open. Otherwise start the Terminal program, go the bin directory and run simple.

The default Mac video dialog is really advanced so you can change a lot of elements, like video input, format or setup the video parameters (saturation, brightness). Furthermore, a preview window is displayed that help for the configuration. You need to notice that better the format is similar to ARToolKit tracking format, faster is the acquisition (RGB more efficient).
SGI

On SGI you need to use a terminal, go to the bin directory, and run simple.

simpleTest的输出

如果成功了,会显示一个视频窗口(如果遇到什么问题,可以参考FAQmailing list)。当你把摄像头对准标志物的时候(内部印有“hiro”的黑框),在视频窗口里,会看到有一个蓝色的方块出现在标志物上。 下图是运行的截图。当移动标志物的时候,虚拟图像(蓝色方块)会随标志物一起移动。

为了让虚拟物体显示在标志物上,必须能在视频中看到完整的黑框 和黑框中的图形。如果看不到虚拟物体,或者它时隐时现,可能是照明的问题。这个问题可以通过修改图像处理历程的阈值来解决。键入“t”,会提示你输入新的 阈值。阈值的取值范围为0~255,默认值是100。键入“d”会显示在主窗口下显示阈值图像(如下图)。在阈值图像中,会用红框把可能的定位区域标出 来。这样将便于你检查光照和阈值的设置是否合适。
键入“esc”退出程序并打印幀率信息。

[AR]完整版Flash Augmented Reality(增强现实)

mikel阅读(975)

Flash Augmented Reality

by shine on Jan.12, 2009, under ActionScript, 交互技术研究


Papervision – Augmented Reality (extended) from Boffswana on Vimeo.
大家对于VR都很熟悉,今天来讲讲AR···

AR全称为Augmented Reality(增强现实), 也被称之为混合现实。它通过电脑技术,将虚拟的信息应用到真实世界,真实的环境和虚拟的物体实时地叠加到了同一个画面或空间同时存在。增强现实提供了在一 般情况下,不同于人类可以感知的信息。它不仅展现了真实世界的信息,而且将虚拟的信息同时显示出来,两种信息相互补充、叠加。在视觉化的增强现实中,用户 利用头盔显示器,把真实世界与电脑图形多重合成在一起,便可以看到真实的世界围绕着它。

增强现实借助计算机图形技术和可视化技术产生现实环境中不存在的虚拟对象,并通过传感技术将虚 拟对象准确“放置”在真实环境中,借助显示设备将虚拟对象与真实环境融为一体,并呈现给使用者一个感官效果真实的新环境。因此增强现实系统具有虚实结合、 实时交互、三维注册的新特点。

该技术在众多领域都有令人啧啧称奇的表现和体验感,而今天介绍的这个案例则是由AS3+WEBCAM完成的。

原地址:http://www.boffswana.com/news/

体验步骤:

1.下载并打印 这个PDF

2.确认您的摄像头已正确链接主机。

3.打开这个FLASH,等待加载完成,点击START开始体验。

将打印好的PDF放在摄像头前,如果步骤一切顺利的话您可以获得和文章开头视频中一样的效果。

点击此处下载源码

简单的来说就是通过摄像头实时分析视讯数据,解析中画面中的mark(就是制订好的那个二维码),比较分析得出二维码的方向,斜率,大小等数据,然 后通过视觉表现将该数据体现出来(视频中的怪兽就是用PV3D做的,你可以用其他的任何表现形式)。通过视频和FLASH DEMO,我们可以看到实时效率,多mark识别还尚待解决,目前还难以将此技术应用到FLASH项目的实际开发中。不过这种新型的人机交互形式还是让人 大呼过瘾。

你可以点击以下地址,了解一下该技术的应用领域

http://www.youtube.com/results?search_query=Augmented+Reality&search_type=&aq=f

http://www.designboom.com/weblog/cat/8/view/4912/augmented-reality-geisha.html

上面这跨快时代的宅男产品现提供破解版的下载地址

http://qiyeji.1stfreehosting.com/simple/index.php?t88.html

本人已经下载并且亲手制作以上道具,实际体验了一下,相当有意思。

实时运行的画面,我的显示器,我的桌面,我的钱包,我的小扑(当成摄像头垫子的那个)

这是我亲手制作的道具

[FlARToolKit]使用Flash实现增强现实

mikel阅读(854)

使用Flash实现增强现实

作者 Jon Rose译者 张龙

最近随着FLARToolKit的发布,增强现实(augmented reality)成为Flash社区的一个时髦词,它能将真实世界的对象与计算机生成的对象混合在一起。

Bartek Drozdz在其博客上科普了增强现实这个概念:

增强现实使用模式识别在视频上渲染3D图形。模式(又叫做标记)是一个矩形,你用其在相机前打印和定位。来自相机的流经过分析后由标记生成其捕获世界的坐标系统,接下来将该坐标系统发送到3D引擎,由后者在视频图像上渲染对象。

Duane Nickull在其博客上高度评价了FLARToolKit:

FLARToolKit是ARToolKit的AS3版本。ARToolKit是个可以创建增强现实的C程序库,然而兼容于Adobe Flash/Flex/AIR的FLARToolKit并不仅仅只是对之前C版本的移植。FLARToolKit是从Java版本移植过来的,其名称叫做NyARToolKit(经过nyatla的艰苦努力之后,现在NyARToolKit的执行速度要比原始的C版本快)。

构建基于浏览器应用的能力(包括增强现实)可以提高开发者对软件的认识。为了让开发者尽快上手,Adobe布道者Lee Brimelow发布了一个视频教程,其中包括GE的智能网格增强现实应用的示例。该示例在真实应用中使用了增强现实的叫声因子(wow factor),是绝佳的学习资源。

请阅读维基百科关于增强现实的说明来进一步了解其背景信息。 查看英文原文:Augmented Reality with Flash

[SWF]一个名字叫“Spark project”的超级强大的AS3库

mikel阅读(852)

这是一个超级大的项目工程,叫“Spark project”。在里面,你会找到不少实用的AS3类库,例如 swfassist ,一个解析SWF文件的库,支持Flash player 9,可以用as动态生成swf文件;又例如BMPDecoder、ICODecoder、PSDParser,从名字可以看出分别是用来解析bmp文件、 ico文件以及psd文件(没错,就是PhotoShop的源文件格式 PSD !);也有 AS3D 库,用来处理 3D 的;还有 SQLControls ,可以在AIR里方便操作SQLite数据库;还有很多很多…… 总体来说,包含以下这些相关:

  • 图形/颜色处理
  • 显示对象处理
  • 3D
  • 图像处理
  • 音频处理
  • 通信处理
  • 数学运算
  • 物理现象
  • 游戏算法
  • 时间日期处理
  • Flash Player/系统
  • 调试/测试
  • 二进制文件处理(bmp、ico、psd等等)
  • 其它…

        该项目是日本人做的,幸好有英文版本的页面。要学会用应该也需要一段时间了,想要研究他们的源代码,想必不是一件快乐事 🙂

项目首页http://www.libspark.org/
一堆AS3类库的英文版页面http://www.libspark.org/wiki/WikiStart/en