【转】理解HTTP幂等性

原文地址:http://www.cnblogs.com/weidagang2046/archive/2011/06/04/2063696.html

这篇文章原文写的非常好,推荐在原文中浏览

原文如下:

Todd.log – a place to keep my thoughts on programming 理解HTTP幂等性

基于HTTP协议的Web API是时下最为流行的一种分布式服务提供方式。无论是在大型互联网应用还是企业级架构中,我们都见到了越来越多的SOA或RESTful的Web API。为什么Web API如此流行呢?我认为很大程度上应归功于简单有效的HTTP协议。HTTP协议是一种分布式的面向资源的网络应用层协议,无论是服务器端提供Web服务,还是客户端消费Web服务都非常简单。再加上浏览器、Javascript、AJAX、JSON以及HTML5等技术和工具的发展,互联网应用架构设计表现出了从传统的PHP、JSP、ASP.NET等服务器端动态网页向Web API + RIA(富互联网应用)过渡的趋势。Web API专注于提供业务服务,RIA专注于用户界面和交互设计,从此两个领域的分工更加明晰。在这种趋势下,Web API设计将成为服务器端程序员的必修课。然而,正如简单的Java语言并不意味着高质量的Java程序,简单的HTTP协议也不意味着高质量的Web API。要想设计出高质量的Web API,还需要深入理解分布式系统及HTTP协议的特性。

幂等性定义

本文所要探讨的正是HTTP协议涉及到的一种重要性质:幂等性(Idempotence)。在HTTP/1.1规范中幂等性的定义是:

Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. 从定义上看,HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。幂等性属于语义范畴,正如编译器只能帮助检查语法错误一样,HTTP规范也没有办法通过消息格式等语法手段来定义它,这可能是它不太受到重视的原因之一。但实际上,幂等性是分布式系统设计中十分重要的概念,而HTTP的分布式本质也决定了它在HTTP中具有重要地位。

分布式事务 vs 幂等设计

为什么需要幂等性呢?我们先从一个例子说起,假设有一个从账户取钱的远程API(可以是HTTP的,也可以不是),我们暂时用类函数的方式记为:

bool withdraw(account_id, amount) withdraw的语义是从account_id对应的账户中扣除amount数额的钱;如果扣除成功则返回true,账户余额减少amount;如果扣除失败则返回false,账户余额不变。值得注意的是:和本地环境相比,我们不能轻易假设分布式环境的可靠性。一种典型的情况是withdraw请求已经被服务器端正确处理,但服务器端的返回结果由于网络等原因被掉丢了,导致客户端无法得知处理结果。如果是在网页上,一些不恰当的设计可能会使用户认为上一次操作失败了,然后刷新页面,这就导致了withdraw被调用两次,账户也被多扣了一次钱。如图1所示:

non-idempotent

图1

这个问题的解决方案一是采用分布式事务,通过引入支持分布式事务的中间件来保证withdraw功能的事务性。分布式事务的优点是对于调用者很简单,复杂性都交给了中间件来管理。缺点则是一方面架构太重量级,容易被绑在特定的中间件上,不利于异构系统的集成;另一方面分布式事务虽然能保证事务的ACID性质,而但却无法提供性能和可用性的保证。

另一种更轻量级的解决方案是幂等设计。我们可以通过一些技巧把withdraw变成幂等的,比如:

int create_ticket() bool idempotent_withdraw(ticket_id, account_id, amount) create_ticket的语义是获取一个服务器端生成的唯一的处理号ticket_id,它将用于标识后续的操作。idempotent_withdraw和withdraw的区别在于关联了一个ticket_id,一个ticket_id表示的操作至多只会被处理一次,每次调用都将返回第一次调用时的处理结果。这样,idempotent_withdraw就符合幂等性了,客户端就可以放心地多次调用。

基于幂等性的解决方案中一个完整的取钱流程被分解成了两个步骤:1.调用create_ticket()获取ticket_id;2.调用idempotent_withdraw(ticket_id, account_id, amount)。虽然create_ticket不是幂等的,但在这种设计下,它对系统状态的影响可以忽略,加上idempotent_withdraw是幂等的,所以任何一步由于网络等原因失败或超时,客户端都可以重试,直到获得结果。如图2所示:

idempotent

图2

和分布式事务相比,幂等设计的优势在于它的轻量级,容易适应异构环境,以及性能和可用性方面。在某些性能要求比较高的应用,幂等设计往往是唯一的选择。

HTTP的幂等性

HTTP协议本身是一种面向资源的应用层协议,但对HTTP协议的使用实际上存在着两种不同的方式:一种是RESTful的,它把HTTP当成应用层协议,比较忠实地遵守了HTTP协议的各种规定;另一种是SOA的,它并没有完全把HTTP当成应用层协议,而是把HTTP协议作为了传输层协议,然后在HTTP之上建立了自己的应用层协议。本文所讨论的HTTP幂等性主要针对RESTful风格的,不过正如上一节所看到的那样,幂等性并不属于特定的协议,它是分布式系统的一种特性;所以,不论是SOA还是RESTful的Web API设计都应该考虑幂等性。下面将介绍HTTP GET、DELETE、PUT、POST四种主要方法的语义和幂等性。

HTTP GET方法用于获取资源,不应有副作用,所以是幂等的。比如:GET http://www.bank.com/account/123456,不会改变资源的状态,不论调用一次还是N次都没有副作用。请注意,这里强调的是一次和N次具有相同的副作用,而不是每次GET的结果相同。GET http://www.news.com/latest-news这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的。

HTTP DELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。

比较容易混淆的是HTTP POST和PUT。POST和PUT的区别容易被简单地误认为“POST表示创建资源,PUT表示更新资源”;而实际上,二者均可用于创建资源,更为本质的差别是在幂等性方面。在HTTP规范中对POST和PUT是这样定义的:

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line …… If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. POST所对应的URI并非创建的资源本身,而是资源的接收者。比如:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。而PUT所对应的URI是要创建或更新的资源本身。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。

在介绍了几种操作的语义和幂等性之后,我们来看看如何通过Web API的形式实现前面所提到的取款功能。很简单,用POST /tickets来实现create_ticket;用PUT /accounts/account_id/ticket_id&amount=xxx来实现idempotent_withdraw。值得注意的是严格来讲amount参数不应该作为URI的一部分,真正的URI应该是/accounts/account_id/ticket_id,而amount应该放在请求的body中。这种模式可以应用于很多场合,比如:论坛网站中防止意外的重复发帖。

总结

上面简单介绍了幂等性的概念,用幂等设计取代分布式事务的方法,以及HTTP主要方法的语义和幂等性特征。其实,如果要追根溯源,幂等性是数学中的一个概念,表达的是N次变换与1次变换的结果相同,有兴趣的读者可以从Wikipedia上进一步了解。

参考

RFC 2616, Hypertext Transfer Protocol — HTTP/1.1, Method Definitions The Importance of Idempotence Stackoverflow – PUT vs POST in REST

【转】对Adobe Flex的十大误解

原文地址:http://www.blogjava.net/vip01/archive/2007/12/18/168462.html

原文内容如下:(PS:这是一篇陈旧的文章)

对Adobe Flex的十大误解
在这篇文章中开源的blazeds折射出adobe的野心 ,
看了大家的回复

感觉很多人还是不了解flex

特地找了篇文章解释一下
------------------------------------------

在Qcon上,Adobe的James Ward和InfoQ.com一起分享了他推广传播Flex应用框架过程中所遇到的对Adobe Flex的十大误解。
为了运行Flex应用程序用户需要安装新东西。

Ward向InfoQ.com独家论述了Flash采用比例和Flex编程模型:
Flex 2和Flex 3必需运行在Flash Player 9上。Flash Player 9运行时目前已经被安装在世界94%的计算机上:http://www.adobe.com/products/player_census/flashplayer/version_penetration.html

Flex 2和Flex 3的应用程序执行在Flash Player 9环境下。Flex应用程序构建在本地Flash Player API之上,如矢量图形、位图处理和网络(基于浏览器网络协议栈)。Flex框架增加了如日期选择器、数据表格、图表等可重用组件。编译Flex应用程序的结果产生一个SWF文件,它是供Flash Player使用的二进制字节码格式。SWF文件包含的是Flex框架代码和项目自定义代码的字节码。Flex编译器对字节码进行了优化,只将要用的类编译到SWF文件中。

对于桌面应用软件,Adobe的目标是推出自己名为Adobe AIR的新桌面运行时,希望能像Web运行时一样普及。Adobe AIR 1.0版本将于2008年初发布。目前,从labs.adobe.com上可得到的AIR是测试版。许多公司都已经在使用AIR构建产品软件。eBay的应用程序eBay桌面就是一个例子。
Flash Player是100%私有的。

Ward继续为InfoQ.com做出说明:
Flash Player的核心是Tamarin虚拟机,这是Mozilla旗下的一个开源项目。而SWF文件格式不是完全开放的,它是由osflash.org社区备案的。已有很多读写SWF文件的开源产品。Flash Player产品的发展方向在很大程度上受该社区及其需求所影响。Flash Player的核心语言是ECMAScript 262的一个实现,ECMAScript 262是JavaScript的规范。Flex还将CSS用于组件/应用的样式。Adobe AIR使用web标准以及开源技术如Tamarin、Webkit和SQLite作为其桌面应用的基础。
Flash是为设计者、视频准备的,而且让人讨厌。

2007年7月Ward在博客文章“我是如何克服对Flash的恐惧”中指出:
毋庸置疑的,Flash的能力被滥用了。弹出窗口、跳过介绍和烦人的广告横行于我们的屏幕上。我曾听人们说过不应该因为一个宗教被滥用而否定它。这一格言同样适用于技术。FLASH不能因为有些人拿它来做令人讨厌的东西而遭到摒弃。毕竟e-mail并没有因为垃圾邮件泛滥而消失。
Ward为InfoQ.com详细阐述了该主题:
传统的FLASH是用为设计者提供的基于时间轴的工具构建的。Flex是用于构建基于Flash的内容/应用的开发者工具套件。设计者和开发者通过共享两个工具之间的资源能够携手合作。Flex增加了一个全面的组件库:

http://www.adobe.com/go/flex_explorer_a pp
http://www.adobe.com/cfusion/exchange/index. cfm?event=productHome&exc=15&loc=en_us
Flex不是为企业/商业应用准备的。

在过去数周里,Ward 发布了关于Oracle在Adobe Flex之上实现大量新应用的七篇系列博客文章。这些应用软件近来公布在Oracle OpenWorld 上,其范围涉及从销售工具到数据库管理和商业智能。

除了Oracle对Flex的使用,InfoQ.com也公布了一些使用Flex开发企业应用的团体。Ward也为InfoQ.com指出了很多使用Adobe Flex开发企业级应用的例子,包括:Workday, SAP, Salesforce和Business Objects。

Flex太贵。

Ward详述了Adobe所做的一系列努力来消除公众对价格的误解:
Flex是为构建Web和桌面的丰富互联网应用所提供的、免费的开发工具包,并且马上要开源。免费SDK包含了开发者构建RIA应用所需的一切,构建出的RIA应用可在任何浏览器或操作系统上同样工作。免费Flex SDK的一部分部分是一套内容广泛的组件集,其可扩展、可更换皮肤且可访问。你可以在Flex组件资源管理器上看到很多这样的组件:http://www.adobe.com/devnet/flex/samples/code_explorer/

Flex Builder是一个可选的Eclipse插件,这让使用免费Flex SDK开发应用软件更高效。它包括如集成调试、设计视图和代码补全等功能。

最近也采取了不少办法来调整Flex Builder的价格。Flex Builder现正免费提供给学生及教职人员。不带图表组件的vanilla版本Flex Builder,其价格已降至249美元,以此更好地平衡Flex Builder的价格等级。

还有许多构建Flex应用后端基础结构的可选项。为了利用高性能AMF数据传输协议,有如LiveCycle数据服务这样的官方Adobe产品,以及如Granite数据服务这样的众多开源项目。使用AMF消除了以下不必要的步骤:从数据转换为文本(SOAP, RESTful 等),传送,然后再由文本转换回数据。AMF还允许在线传送中保存类型信息。
关于AMF 和其他基于文本序列化技术的比较,请看James Ward的RIA基准应用系统普查:http://www.jamesward.org/census.
Flex的应用程序需要专用服务器。

Ward再次为InfoQ.com讲述:
Flex应用程序可以运行在任何Web服务器,应用服务器和数据库服务器之上。Flex应用程序更像是客户端-服务器应用程序。由于逻辑是运行在Flash Player客户端内,你需要某种方式来与服务器交互。你可以有很多不同的选择将Flex连接到你的基础结构。不需要任何专用库,你可以将你的后端数据和服务暴露为RESTful、XML或SOAP,并且很容易在你的Flex应用中消费这些数据。如果选择使用AMF二进制序列化协议,你可能需要添加一些额外的库到你的web应用软件。AMF只是另外一种序列化技术,就如XML或JSON 一样,所以它可以作为你用于和后端SOA沟通的多样方式中的一种。
Flex很难学。

InfoQ.com社区的Leftie Friele,就InfoQ.com文章”谁在使用Flex?” 发表了评论,详述了他的公司在学习Flex上的经验:
我们初创公司Ezmo在开创以来就在使用Flex,我们非常愉快的使用该框架。

不需要任何Flex/Flash的预备知识,我们可以在少于两周之内构建出我们的应用程序。Java和Flex之间的整合更是超级简单,开始使用Flex就像是公园漫步。

说到工具支持, Flex Builder也是相当不错。如果你熟悉Eclipse环境,你能顺利起飞,不会碰到任何问题。唯一缺憾是缺少更好的持续集成工具和更好的Maven插件来构建Flex应用。
对于Flex新手们,Ward给了一段截屏录像,展示了一个Flex应用的构建过程,以帮助你起步。此外,还有许多关于使用Flex和Java的其他文章在 Adobe Developer Connection上 。

使用Flex,我需要重建我的整个应用。

今年1月,Bruce Eckel发表了一篇题目为”混合Java” 的文章。文章中他认为Java团体应该继续使用Java好的方面,但是也应该采用其他技术来替代Java薄弱的方面。文中主要焦点是使用Adobe Flex作为用户界面来取代传统的Java选项(Swing、JSF等……)

Ward详细阐述了这一概念:
既然Flex应用程序只是应用程序的UI端,而后端通常都是一样的。如果你的后端是依照SOA模式构建的,那么通常很容易将这些服务暴露给一个新的Flex UI。这将保持你现有的商业逻辑不变,无论它使用的是EJB、Spring服务还是POJO。
Flex打破了常规的浏览习惯,象后退按钮。

Ward的博文讨论了后退按钮:
Flex已经内建了对后退按钮的支持且非常容易定制,因此这已不再是问题。Flex也提供了一个简单的办法来处理“#”url(或命名的锚点),url随应用状态的变化而变化。另一个Web 1.0的整合问题业已解决。
Ward为InfoQ.com补充了更多的细节:
Flex 3给应用提供了一个简单的方式在命名的锚点中储存状态参数,当该URL被请求时可以根据这些参数正确地恢复状态。有关这一特点的更多信息可以参见Flex 3特性介绍:深连接专题介绍文档。

可访问性对Flex应用来说一直是非常重要。因为Flash Player与Jaws及其他可访问性技术一起工作的,因此为基于Flash的应用程序增加可访问性的能力已经具备了。Flex框架将可访问性纳入核心框架。有许多不同方面的可访问性,这取决于你的应用程序需要支持什么样的损伤和残疾。你可以在开发者指南中找到更多有关Flex可访问性特性的信息。
Flex能做到的,Ajax也能做到。

Ward解释说:
Flex RIA和Ajax不是非此即彼的关系。像Google Finance网站就展示了如何同时使用Flex和Ajax。Ajax非常适合以内容为中心的应用,而Flex则适合于互动,媒体和数据为中心的应用。如果你的应用介于这两者之间,那么你可以用Flex Ajax Bridge来结合这两种技术。在 Flex 3里,Flex Ajax Bridge已经直接集成到SDK中。如果使用的Flex 2,你将需要单独下载Flex Ajax Bridge。
此外,InfoQ.com社区的Michael Marth讲述了他的小组为什么选择Flex:
我们即将推出的网上约会站点viibee.com使用的就是Flex 2

理由是:付出相同的努力,Flex使我们能够创建的用户体验远远超过我们用Javascript/Ajax所能做到的。

【转】FlashBuilder插件

转自:http://bbs.9ria.com/thread-150898-1-1.html

以下是转载内容:

所谓磨刀不误砍柴工,这些插件可以让你的ActionScript编程事半功倍哦!有些是自己在open-oepn的插件列表一个个找的,有些是在网络上搜集的,以后有了新的插件,也会陆续更新。
如果不清楚怎么安装插件的同学,可以看我的另外一篇《FlashBuilder插件安装的3种方法》
FlashBuilder常用精选

1.Easy Explorer:打开在eclipse中选定文件所在的目录。
这是一个非常不错的插件,有了它,你就可以随时跳到你指定文件的目录了。
地址:http://sourceforge.net/projects/easystruts/

2.全屏插件
Eclipse Fullscreen 是一个让 Eclipse 开发工具可以全屏方式运行的插件,全屏状态下将隐去菜单栏和状态栏。
在线安装地址:http://scharf.gr/eclipse/fullscreen/update/

3.SVN插件
可以直接在FlashBuilder里面直接更新和提交代码到svn,非常方便
在线安装地址:http://subclipse.tigris.org/update_1.7.x

4.vi插件
vimPlugin是eclipse下的vim插件,很好用
1、下载viPlugin下载地址:http://www.viplugin.com/viplugin/
2、解压文件夹,将里面的plugin、feature放到eclipse下的对应plugin、feature文件夹下
3、破解方法:在提示的路径(一般为eclipse或workspace路径)新建一个名为viPlugin.license的文件,内容为Xq@a*4
4、重启eclipse,这是在eclipse中可以看到vi的图标

5.范例查询插件
具体使用方法:当你编写as代码时,需要查询某个类怎么使用,可以使用Ctrl+B调出blueprint,然后在输入框中键入要查询的内容
网址:http://labs.adobe.com/technologies/blueprint
安装教程:http://labs.adobe.com/wiki/index.php/Blueprint:Installation_Instructions

6.代码格式化FlexPrettyPrintCommand
可以自动对齐等对代码进行格式化
在线安装地址:[url=url:http://flexformatter.googlecode. … ntCommandUpdateSite]

7.SourceMate
SouceMate是Flash Builder下的一个收费插件,但在我看来,它完全值得你花点小钱去买。它的功能有很多:可以进行元数据验证(如果你的框架里有使用元数据),可以生成ASDocs和ANT构建脚本,可以搜索FIXME和TODO标签下的语句等等。但其真正的亮点在于重构、模块化和代码生成功能。其中的Extract方法我使用的最多。我很幸运地在一个报告会上得到了一份免费的版本,现如今它对我已经不可或缺
地址:http://www.elementriver.com/sourcemate

8.Flash Builder Task Plugin
支持用注释的方式添加任务标记
用法:
//TODO: 添加任务主标题
// todo – 任务详细描述
//FIXME: 待修复的bug主标题
//FIXme: 待修复的bug详细描述
非常好用哦,这样可以和队友共享一些任务标记啦。
下载地址:http://www.richinternet.de/blog/download/flexbuilderTask_1.0.0.zip

一些精选的比较偏门的插件,个人看着喜欢就安装吧

1.一个可以控制Eclipse字体大小的Eclipse插件
http://code.google.com/p/eclipse-fonts/
快捷键-
CTRL+= : 增大字体
CTRL+- : 减小字体
在线安装地址:http://eclipse-fonts.googlecode.com/svn/trunk/FontsUpdate/

2.EditBox:http://editbox.sourceforge.net/
EditBox是一个能够对选中的代码块进行加亮的Eclipse插件。通过改变代码块的背景或对代码块加边框来实现加亮。

3.Multi Clipboard
http://www.bastian-bergerhoff.com/eclipse/features/web/MultiClipboard/toc.html
Multi Clipboard为Eclipse源代码编辑器提供一个可以把多次复制的内容保存起来的剪贴板,它不会像正常剪贴板一样只是保存最后一次复制的内容。 你可以设置该插件当Eclipse关闭时会把Multi Clipboard中的内容保存一个文件中,当Eclipse再次打开时会重新加载保存到文件中的内容。你还可以通过设置该插件把Multi Clipboard中的内容变成可编辑。

4.EditorList 方便的列出所有打开的Editor
http://editorlist.sourceforge.net/

5.Eclipse Platform Extensions
一组Eclipse插件提供了以下功能:
1.提供把文件名或完整的限定名(Qualified name)复制到剪贴板;?
2.提供垃圾收集功能;
3.用命令提示符(Command Prompt)或资源管理或导航器方式打开所选文件或项目所在的位置。
4.提供重启Eclipse平台的菜单; 支持的Eclipse版包括3.0,3.1,3.2;
在线安装:http://opensource.trajano.net/

6.Vrapper(又一个VI插件)
Vrapper是一个Eclipse插件,它对Eclipse文本编辑器进行了封装提供了类似于Vim的编辑功能。让你可以使用像dd yy $ gg jkli这些常用的高效操作指令。安装完Vrapper 之后, 工具栏会出现一个Vim 的图标, 点击一下就可以进入Vim 模式了。可以在Eclipse 的正常编辑模式和Vim 模式之间随意切换。
地址:http://vrapper.sourceforge.net/home/

7.JGit是Git版本控制一个的客户端Eclipse插件。
地址:http://www.eclipse.org/egit/

8.ActionScript Code Coverage Plug-in
ActionScript代码覆盖插件,这个插件可以让你知道你的代码里有那些方法没有被调用到,也就是说那里写了多余的代码:)
地址:http://www.adobe.com/devnet/flash-builder/articles/ascode-coverage.html

最后是几个我没测试成功或者版本过期的插件,有兴趣的同学可以继续研究(之前新闻区发过的)
FlexPMD
FlexPMD是一个代码检测工具,可以检测到一些Flex和Actionscript代码中并不规范、但Flex编译器又无法发现的小细节。使用它有助于提高代码质量,当我写完一段新代码时,我第一件要做的事情就是用FlexPMD过一遍。
你可能不会全盘认可它作出的提示,但你也可以进行设置,使之适应你自己的代码风格。使用该工具的前提是:你必须了解如何编写规范的Flex代码,以及Flex框架的少量相关知识。
FlexPMD还可以显示出代码中被复制和粘贴过的区域,以帮助你确定哪些部分需要重构。在你需要了解一个项目含有多少粘贴来的代码时,该功能显得非常实用。
FlexPMD也可以在Ant、OSX Automator以及Maven等环境下使用,还可以集成到一个如Hudson这样的持续可集成系统的一部分。
FlexPMDhttp://sourceforge.net/adobe/flexpmd/wiki/FlexPMD%20Eclipse%20plugin/

FlexCover
FlexCover是一个针对Flex、AIR的代码覆盖率测试工具,其最新版本更方便使用,因为你只需要用FlexCover SDK覆盖掉你正在使用的Flex SDK再重新进行编译就可以了。在你进行单元测试时,它会同时提供代码覆盖率和分枝覆盖率。这非常有助于你了解需要进行哪种测试,以及是否已经做了足够的测试。
即便你的项目没有单元测试(为你感到羞耻)。FlexCover也能对你的代码中的无效部分作出较好的提示。
地址:http://code.google.com/p/flexcover/

【转】Flex 4与自定义布局

原文地址:http://blog.csdn.net/lihe111/article/details/4325571

如果您还不熟悉Flex 4的最新功能,那么有些内容肯定是您想要了解的。Flex 4/Spark组件架构的新功能之一是可以定制一个容器的布局而不必改变容器本身。您需要做的就是定义一个自定义布局。

Flex 4/Spark架构中的容器并不控制它们自己的布局。相反,每种容器具有一个布局属性,用于确定如何在屏幕上设置子元素的布局。可以使用一个单独的Group容器,并赋予其一个垂直布局、水平布局或平铺布局,这取决于您将如何创建它。代码很简单,如下所示:



         

不过真正的好处在于您不必局限于框架中定义的默认布局。您可以轻松定制BaseLayout类来实现自己定制的布局逻辑。下面是一个简单的例子,显示了如何实现一个在原点周围顺时针放置组件的布局。只要单击左下方的按钮就可以将更多按钮添加到布局。

下面是主应用程序文件的代码。可以看到,代码相当简单。这就是一个DataGroup,有点像一个重复程序(repeater),它包含一组按钮。这个容器的布局基于一个自定义布局实现。在creationComplete中,填充DataGroup的数据提供程序,从而在布局中创建按钮实例。




 
  
    
 
  
    
  
 
  
   
    
      
    
 
  
 
  
 

可以看到,DataGroup实例的布局受CircularLayout类控制(该类如下所示)。该类只是循环遍历datagroup对象的子对象并将它们按顺时针方向放在一个圆圈内。我查看了VerticalLayout类的源代码,弄清了它的工作方式,并由此开始构建自己的布局实现。


package
{
   import mx.core.ILayoutElement;
  
   import spark.layouts.supportClasses.LayoutBase;
  
   public class CircularLayout extends LayoutBase
   {
      override public function updateDisplayList(w:Number, h:Number):void
      {
           super.updateDisplayList(w, h);
            
           if (!target)
             return;
                
           var layoutElement:ILayoutElement;
           var count:uint = target.numElements;
            
           var angle : Number = 360/count;
           var radius : Number = Math.min( target.width/2, target.height/2 ) - 25;
            
           var w2 : Number = target.width/2;
           var h2 : Number = target.height/2;
            
           for (var i:int = 0; i < count; i++)
           {
              layoutElement = target.getElementAt(i);
                   
              if (!layoutElement || !layoutElement.includeInLayout)
                continue;
           
              var radAngle : Number = (angle * i) * (Math.PI / 180) ;
           
              var _x : Number = Math.sin( radAngle );
              var _y : Number = - Math.cos( radAngle );
           
              layoutElement.setLayoutBoundsPosition( w2 + (_x * radius) - 25, h2 + (_y * radius) - 10 );
            }
       }
    }
}

这个示例中使用的项目渲染器实际上是最基本的。它是一个只包含一个按钮的ItemRenderer实例,简单明了并且很容易看到产生的结果。



 
  
    
    
  
 
  
    
  
 
  
 

这个例子使用从以下网址得到的4.0.0.7052每日构建(nighly build)版本进行创建:
http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4

英文原文:http://www.insideria.com/2009/05/flex-4-custom-layouts.html

饿的时候,要一心想着如何填饱肚子

饱的时候,记得多想想如何吃得更好。