MonthMay 2011

升级Android SDK Tools, revision 11时遇到问题的解决方案

安装环境和升级版本

OS:Window 7 pro

JRE Version:1.6.0_25-b06

Android SDK Platform-tools:revision 4

Android SDK Tools:revision 8

要升级为Android SDK Tools,revision 11

遇到的问题:

-= warning! =-

A folder failed to be renamed or moved. On Windows this typically means that a program Is using that Folder (for example Windows Explorer or your anti-virus software.)

Please momentarily deactivate your anti-virus software.

Please also close any running programs that may be accessing the directory ‘D:CodeAndroidandroid-sdk_r07-windowsandroid-sdk-windowstools’.

When ready, press YES to try again.

解决方法:

尝试了

1,管理员模式运行,失败

2,关了什么Adb.exe,杀毒软件,各种浏览器,皆失败

3,去Eclipse Android SDK Manager更新,失败

万般无语之后只有Google之,发现原来是个老Bug了,各种版本都是这样的,在Android Google Code是排4000多的Issues……

最后还是参考了StackOverflow上CommonsWare的回答http://stackoverflow.com/questions/4360894/android-trouble-updating-to-android-sdk-tools-revision-7

  1. 在SDK的文件夹里,复制 tools所有文件 到 scrap
  2. 在 scrap 里运行android.bat,启动SDK Manager
  3. 升级之
  4. 完成后删了scrap文件夹
至于提到的修改环境变量,和需要重启以后才能删scrap文件夹我都没碰到,如果碰到大伙自行了断就好了

 

 

REST学习实践 – 第一篇:解析REST

摘自《REST Service 的最佳实践,第 1 部分: 重新解析 REST Service》 – 马春娥, 软件工程师, IBM

————————————-分割线——————————————————–

三种流行 web 服务的架构

Web 服务是一种面向服务的架构的技术,通过标准的 Web 协议提供服务,目的是保证不同平台的应用服务可以互操作。根据 W3C 的定义,Web 服务(Web service)应当是一个软件系统,用以支持网络间不同机器的互动操作。网络服务通常是许多应用程序接口(API)所组成的,它们通过网络,例如国际互 联网(Internet)的远程服务器端,执行客户所提交服务的请求。流行的或者曾经流行的 Web 服务架构有三种:SOAP RPC over HTTP, XML RPC over HTTP, 和 REST over HTTP。下面分别简要介绍这三种架构。

SOAP RPC over HTTP

简单对象访问协议(SOAP,全写为 Simple Object Access Protocol)是一种标准化的通讯规范,主要用于 Web 服务(web service)中。SOAP 的出现是为了简化网页服务器(Web Server)在从 XML 数据库中提取数据时,无需花时间去格式化页面,并能够让不同应用程序之间透过 HTTP 通讯协定,以 XML 格式互相交换彼此的数据,使其与编程语言、平台和硬件无关。

用一个简单的例子来说明 SOAP 使用过程,一个 SOAP 消息可以发送到一个具有 Web Service 功能的 Web 站点,例如,一个图书价格信息的数据库,消息的参数中标明这是一个查询消息,此站点将返回一个 XML 格式的信息,其中包含了查询结果。由于数据是用一种标准化的可分析的结构来传递的,所以可以直接被第三方站点所利用。

SOAP RPC over HTTP,在 HTTP 上传送 SOAP 并不是说 SOAP 会覆盖现有的 HTTP 语义,而是 HTTP 上的 SOAP 语义会自然的映射到 HTTP 语义。在使用 HTTP 作为协议绑定的场合中, RPC 请求映射到 HTTP 请求上,而 RPC 应答映射到 HTTP 应答。然而,在 RPC 上使用 SOAP 并不仅限于 HTTP 协议绑定。SOAP 协议没有和 HTTP 有很好的结合,没有利用 HTTP 协议里面关于 request 和 response 的丰富词汇,而是鼓励应用设计人员定义任意的词汇(动词和名词),像 getUsers(),savePurchaseOrder(…),getBookPrice() 等。SOAP RPC Request 通过 HTTP POST 请求发送。清单 1 和清单 2 给出了 SOAP RPC over HTTP 的 request 和 response 的示例。请求和响应是封装在 SOAP Envelope 里面,以 HTTP request 和 response 的 body 传送。

XML RPC over HTTP

XML RPC over HTTP 和 SOAP RPC over HTTP 从结构上看很类似。这种远程过程调用使用 HTTP 作为传输协议,XML 作为传送信息的编码格式。XML-RPC 的定义尽可能的保持了简单,但同时能够传送、处理、返回复杂的数据结构。XML-RPC 是工作在 Internet 上的远程过程调用协议。一个 XML-RPC 消息就是一个请求体为 XML 的 HTTP POST 请求,被调用的方法在服务器端执行并将执行结果以 XML 格式编码后返回。清单 3 和清单 4 给出了 XML RPC over HTTP 的 request 和 response 的示例。请求和响应是封装在一个固定的格式里面,以 HTTP request 和 response 的 body 传送。

REST over HTTP

REST 风格的架构也并不强调和协议的绑定。HTTP 是 WWW 网上广泛使用的并且被证明是有效的通信协议,所以现在 RESTful 服务基本也是基于 HTTP 协议的。资源是由 URI 来指定。

资源的操作包括获取、创建、修改和删除资源,这些操作正好对应 HTTP 协议提供的 GET、POST、PUT 和 DELETE 方法。通过操作资源的 representation 来操作资源。资源的 representation 可以是 XML 也可以是 HTML,取决于读者是机器还是人,是消费 web 服务的客户软件还是 web 浏览器。当然也可以是任何其他的格式。

REST 在最大程度上充分利用了 HTTP,没有增加额外的词汇和约定。

通过前面的分析和比较,我们可以清楚地看到,REST 风格的 web 服务与 SOAP RPC 和 XML RPC 风格的 web 服务相比,http request 更简单,response 的语意更清楚。而且客户端不需要知道那么多关于应用的细节,比如 method name,method 调用的参数等等。

简言之,目前在三种主流的 Web 服务实现方案中,因为 REST 模式的 Web 服务与复杂的 SOAP 和 XML-RPC 对比来讲明显的更加简洁,越来越多的 web 服务开始采用 REST 风格设计和实现。例如,Amazon.com 提供接近 REST 风格的 Web 服务进行图书查找;雅虎提供的 Web 服务也是 REST 风格的。

REST 风格的 web 服务已被广泛的接受和使用,但是在使用的过程中,我们发现其实有很多号称 RESTful 的 web 服务并不是 Roy 定义的 REST 服务,或者违背了其中的一些约束。像 Amazon 和 Flickr 的 web 服务。接下来,我们首先结合实际经验,重新解读 REST 架构风格中的核心概念,帮助读者准确的掌握 REST 架构,最后给出一个完全符合 REST 风格架构的 web 服务定义的例子。

REST 核心概念解读

Representational State Transfer

在理解 REST 相关的核心概念之前,我们来看看“REST”本身应该怎么理解。“Representational State Transfer”是一个不完整的句子,“Representational”代表的是什么的“表示”?“State”又指的是什么的状态 ?“Transfer”的又是什么?如果我们要把它补全该如何呢?根据 Roy 的论文和我们的实践,应该是“Application States Transfer among the resource ’ s representation”。这里的“State”指的是“应用”的“状态”,这个“状态”是用“资源的表示”来代表的,用户可以在“状态”之间“跳 转”。

REST 架构风格定义的约束

REST 是一种架构的风格,它是对分布式 hypermidea 系统的架构元素的抽象,提供了一些核心的概念和指导思想。这种架构风格是“客户端 – 服务器”架构风格的一种,也就是说“客户端”发起“请求”,“服务器”处理“请求”并返回相应的结果。REST 的贡献是规定了一系列的方法论,在“请求”方面,规定“客户端”怎么发起“请求”,发的是什么样的“请求”,以什么协议发“请求”;在处理方面,规定“服 务器”怎么响应“请求”,返回什么样的“响应”,系统后续应该怎么“跳转”等等。让我们再回顾 Roy 定义的这些约束。

“无状态”(Stateless)

“客户端”和“服务器端”的交互是“无状态”的,也就是说“请求”之间是相互隔离的。“服务器端”不保存“客户端”的应用上下文 (context),每个从“客户端”来的“请求”都必须包括所有的必要的信息让“服务器端”能够完全理解“请求”并处理。“客户端”存了很多“会话”的 信息。让我们以搜索引擎为例来看看“有状态”和“无状态”的区别。

无状态的搜索引擎的交互示例

服务器把当前的状态隐含中结果中返回,客户端保存下这些隐含的状态,而不是保存在服务器端。客户端可以根据服务器端返回 来的状态构建下一个状态的请求。

“无状态”的好处是每个状态都有一个对应的 URI,这些 URI 可以 bookmark,可以使得用户方便的在浏览器中前进后退,可以在用户希望的任何时候访问任意多次。

有状态的搜索引擎的交互示例

有状态的搜索引擎的 request 和 response 的交互示例。可以看出,request 之间的时序依赖性。以“搜索 SOAP”为例,用户在看 1~10 个搜索结果并想看 11~20 个结果,客户端只需要发一个“start=10”的请求而是发“/search?q=SOAP&start=10”的请求,也就是客户端不用重复 前面的 request 的上下文。这使得 HTTP request 相对简单了很多。但是他使得 HTTP protocol 变得复杂。服务器端和客户端需要同步会话的状态,在可靠网络上,这是一个复杂的任务。

“无状态”带来了一些性能的提升。在“visibility”方面,对于监控系统而言,它不用去关心跨请求的数据对当前请求的影响,所以 “visibility”有所提升。在“reliability”方面,由于“客户端”保存了很多“会话”数据,因此减少了部分“服务器”端的故障或者网 络故障对应用的影响,因此对于用户来说,“reliability”有所提升。最值得一提的是“scalability”,由于“服务器”端能够独立的响 应每个 request,而不用依赖会话历史,因此少了很多“资源”的管理和同步,使得多个服务器可以同时服务不同的用户的请求,获得很好的自由扩展功能。

当然,事务都有两面性,“无状态”带来的不足之处包括可能的网络性能的降低,因为“服务器”会发很多重复的数据到不同的“客户端”,使得 “客户端”保存所有的会话信息;这也导致了另一个问题,就是“服务器”将失去对应用的一致行为的一部分控制权,而且还对“客户端”的实现产生依赖

“缓存”(Cacheable)

为了提高 REST 风格架构的网络性能,Roy 加入了“缓存”的约束。“缓存”不是一个新的概念,HTTP 协议提供机制,使得“客户端”可以“缓存”一些数据。在“服务器”返回的“响应”中,可以隐式或者显式的指明数据的“缓存”属性,这样,“客户端”可以在 未来使用“缓存”下来的数据,减少“客户端”和“服务器”端的交互次数,从而达到提高网络性能的目的。

统一的接口 (Uniform Interface)

这是 REST 风格的架构区别于其他架构的一个最关键的指标,就是 REST 风格的架构对于任意应用,规定了统一的接口定义。接口定义包括四个部分:

  • 1)identification of resources(标识资源);
  • 2)manipulation of resources through representations(通过资源的表示来操作资源);
  • 3)self-descriptive messages(自描述的信息);
  • 4)hypermedia as the engine of application state(超媒体作为应用状态的引擎)

下面分别对这些概念进行解析。

Identification of resources

第一部分“identification of resources”讲了 REST 架构风格的一个最核心的概念“Resource”以及 “Resource”的“identification”。“Resource”是信息系统的一种抽象,可以是任何重要的足以把本身作为一个引用 (reference)的事物。从应用的角度看,如果应用的用户需要“创建一个到它链接”,获取或者缓存它的“表示”,或者想对他做些操作,那么都可以创 建一个“Resource”。一个“Resource”可以是现实世界的事物,比如一本书,一辆车,一栋房子;也可以是一个虚拟的概念,也可以是一个算法 的结果。“identification”是“Resource”的全局唯一的标识,如果“Resource”没有 identification,那么他不能称为“Resource”。用 URI 来表示一个 Resource 的 identification。关于 URI 的最佳实践包括 URI 是自描述的,有结构的,这样可以使得“客户端”可以自己创建一些有预测性的请求。几个比较好的 Resource URI 示例:

http://www.example.com/books/123456
http://www.example.com/softwares/im/db2/9.5
http://www.example.com/blog/2010/09/10/1
http://www.example.com/bugs/by-state/new

前面解释了什么是 Resource,怎么用 URI 来标识一个 Resource,下面来看下 Resource 和 URI 的关系,他们之间是不是一一对应的呢?让我们来回答下面几个问题:1)两个 URI 能指向同一个 Resource 么?回答是肯定的。作为程序员,我们都有这样的经历,就是经常做一些 release,让我们考虑这两个 URI: http://www.example.com/releases/3.1.1 和 http://www.example.com/releases/latest,在特定的时刻,他们指向的就是同一个 resource,但是背后的概念是不一样的,一个是指向一个特定的 release 版本号,一个是指向一个随着时间演进的 resource,是两个完全不同的概念。所以一个 resource 可以有一个或者多个 URI 来标识。2)一个 URI 能指向不同的 resource 么?答案是否定的。这和 Universal Resource Identifier 的原则相违背。

Manipulation of resources through representations

接着来看看“Representation”。Representation 是 Resource 的表现形式。Resource 是信息系统的抽象,但是最终必须以人们能理解的一种形式提供出来。可以是一个 XML 文档,HTML 文档,CSV,file 等等。一个 Resource 可以有多种 Representation。那么服务器端怎么知道用户想要哪个 Representation 呢?通常来讲有两种方式:

1)在 resource 的 URI 里面指明,为不同的 Representation 提供不同的 URI。举个例子,我们有个 book 的 resource,我们提供几个不同的 URI 来表示不同的 representation。清单 7、8、9 分别是 XML、JSON、CSV 三种 representation 的 HTTP request 和 response 的示例。
清单 7. Representation 为 XML 的 request 和 response 示例

 GET /books/123456/xml HTTP/1.1
 Host: example.com 

 Reponse:
 HTTP/1.1 200 OK
 Date: Fri, 10 Sept 2010 17:15:33 GMT
 Last-Modified: Fri, 10 Sept 2010 17:15:33 GMT
 ETag: "2b3f6-a4-5b572640"
 Accept-Ranges: updated
 Content-Type: text/xml; charset="utf-8"
 <book category="CHILDREN">
     <title lang="en">Harry Potter</title>
     <author>J K. Rowling</author>
     <year>2005</year>
     <price>24.99</price>
 </book>

清单 8. Representation 为 JSON 的 request 和 response 示例

 GET /books/123456/json HTTP/1.1
 Host: example.com 

 Reponse:
 HTTP/1.1 200 OK
 Date: Fri, 10 Sept 2010 17:15:33 GMT
 Last-Modified: Fri, 10 Sept 2010 17:15:33 GMT
 ETag: "2b3f6-a4-5b572640"
 Accept-Ranges: updated
 Content-Type: text/json; charset="utf-8"

 [
"book":
 {
"title":Harry Potter,
"author":J K. Rowling,
"year":2005,
"price":24.99
 }
 ]

清单 9. Representation 为 CSV 的 request 和 response 示例

 GET /books/123456/csv HTTP/1.1
 Host: example.com 

 Reponse:
 HTTP/1.1 200 OK
 Date: Fri, 10 Sept 2010 17:15:33 GMT
 Last-Modified: Fri, 10 Sept 2010 17:15:33 GMT
 ETag: "2b3f6-a4-5b572640"
 Accept-Ranges: updated
 Content-Type: text/csv; charset="utf-8"

 title,author,year,price
 Harry Potter,J K. Rowling,2005,24.99

2) 利用 HTTP 的内容协商(content negotiation)机制。客户端可以利用“Accept”header 指明它希望的内容表示形式。还是拿 book 的例子来说,客户端发的 HTTP 请求如清单 9 所示:
清单 9. 利用 content negotiation 机制请求 representation 的 request 示例

 GET /books/123456 HTTP/1.1
 Host: example.com
 Accept: text/xml

对应的 response 和第一种方式相同,所以忽略了。

相比较这两种方式,根据我们的经验,第一种方式更好,URI 是一种好的实践,用来表示 resource 的各方面的信息,包括结果,版本,representation 形式,时间等等,它带来的好处是使客户端的工作大大降低,它很方便的可以在不同的应用之间共享。

那么怎么对 resource 进行下一步的操作(“manipulation”)呢? REST 对 Resource 的操作定义和 HTTP method 是对应起来的。HTTP 协议定义 GET、POST、PUT、DELETE 来表示对资源的获取、创建、更新和删除。“Manipulation of resources through representations”约束规定了 resource 的操作是通过 representation 来完成的,所以在 resource 的 representation 里面,需要包含对 resource 的操作怎么进行。APP(ATOM Publishing Protocol)提供了一个最佳实践,是用 <link> 的方式指明 Resource 响应的操作,下面是一个实例:

<link rel=”edit” href=”http://www.example.com/books/123456″/>

rel 定义了该 link 的 resource 和当前 resource 的关系,href 定义了 resource 的 HTTP endpoint。所以当用户想更新 id 为 123456 的 book 的价钱的时候,客户端会发一个 PUT 请求到指定的 URI。

Self-descriptive messages

REST 接口的定义强调了自描述“Self-descriptive”性。自描述性也是为了让客户端充分的理解当前的状态,下一步的状态怎么跳转。

前面讲了 resource 的 representation,只讲述了 representation 的数据的一部分。在 representation 里面,除了包含数据部分,还包括元数据,它是用来描述数据的信息,或者是一些客户端需要知道的一些领域知识。这里以 ATOM 协议为例看看怎么在 representation 里面提供自描述的信息。清单 12 是一个 ATOM 的片段。
清单 12. 一个 ATOM 形式的 resource representation

 <?xml version="1.0" encoding="UTF-8"?>
 <feed xmlns="http://www.w3.org/2005/Atom"
 xmlns:os="http://a9.com/-/spec/opensearch/1.1/"
 xmlns:catalog="http://www.ibm.com/opensearch/1.0">
  <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 </id>
 <link href="http://www.example.com/books?q=harry potter&start=0" rel="self"></link>
 <link href="http://www.example.com/books?q=harry potter&start=10" rel="next"></link>
  <updated>2009-08-11T03:00:27.062Z</updated>
  <title type="text"> harry potter 相关的图书 </title>
  <os:startIndex xmlns:os="http://a9.com/-/spec/opensearch/1.1/">0</os:startIndex>
  <os:itemsPerPage xmlns:os="http://a9.com/-/spec/opensearch/1.1/">10</os:itemsPerPage>
  <os:totalResults xmlns:os="http://a9.com/-/spec/opensearch/1.1/">10</os:totalResults> 

 <entry>
 <title type="text"> Harry Potter </title>
    <id>urn:id:23-27</id>
 <updated>2009-07-09T11:01:26.000Z</updated>
    <category term="harry potter"></category>
   <category term="best seller"></category>
  <category term="book"></category>
   <category term="Hyper Service"></category>
   <content type="application/xml" xmlns= ’ http://www.example.com/books ’ >
    <book category="CHILDREN">
     <title lang="en">Harry Potter</title>
     <author>J K. Rowling</author>
     <year>2005</year>
     <price>31.99</price>
            </book>
    </content>
    </entry>
…
 </feed>

从上面的例子可以看出,除了 <content> 里面的内容是和 book 数据相关的信息以外,剩下的信息都是描述性的信息,通常包括翻页信息:一共有多少页,前后翻页的 link 是什么;分类信息,时间信息,还有一些文本信息供用户阅读。

总之,服务器端尽可能的返回详细的信息,帮助客户端理解当前的状态,以及发起下一个请求所需要的所有信息,以达到“服务器端无状态”和客户端发起“状态跳转”的目的。

Hypermedia as the engine of application state

“Hypermedia as the engine of application state”是“统一接口”的最后一个约束,也是最重要的一个约束,不幸的是, Roy 的 REST 论文中对这个约束的解释特别少,在这里,我们根据我们的经验和理解,对这个约束进行描述。这个约束其实规定的是应用系统是通过 Hypermedia 的方式在不同的状态之间跳转。这句话听起来有点拗口,还是来看一个例子吧。

Flickr 提供了 REST API,以 flickr.groups.members.getList 为例来看看这个 REST API 的 定义,清单 13 是一个响应示例(sample response),可以看出“members”是一个 resource,它是一系列“member”的集合,也就是说,它指向其他的 resource。
清单 13. flickr.groups.members.getList 的响应示例

 <members page="1" pages="1" perpage="100" total="33">
 <member nsid="123456@N01" username="foo" iconserver="1"
 iconfarm="1" membertype="2"/>
 <member nsid="118210@N07" username="kewlchops666"
 iconserver="0" iconfarm="0" membertype="4"/>
 <member nsid="119377@N07" username="Alpha Shanan"
  iconserver="0" iconfarm="0" membertype="2"/>
 <member nsid="67783977@N00" username="fakedunstanp1"
 iconserver="1003" iconfarm="2" membertype="3"/>
 ...
 </members>

如果用户还想对“Alpha Shanan”了解更多呢?这时,客户端会构建一个 HTTP request,URI 为:

 http://api.flickr.com/services/rest/?
 method=flickr.people.getInfo?auth_key=xxxx&user_id=119377@N07

如果系统按照这种方式运行,问题在哪呢?客户端和服务器端需要有很多的共享的知识和约定,客户端需要知道获取人员信息的 API 是 method=flickr.people.getInfo 以 user_id 作为参数。这不是 Hypermedia,同时也违背了 Roy 的关于“Hypermedia as the engine of application state”的约束,所以这个不是好的 RESTful 的实现

Hypermedia 的实质是 hyperlink, 用 hyperlink 把这些相互依赖的 resource 联系起来,这些 hyperlink 是由服务器端生成并且在 representation 里面返回来的,包括了当前的状态集合和可能的下一步的状态集合。客户端不需要任何 domain specific 知识就能够实现状态的跳转。Hypermedia 类型的 sample response 如清单 14 所示。在清单 14 中可以看到,resource 和 resource 之间的联系通过 hyperlink 关联起来,并且在 resource 的 representation 里面表示。
清单 14. REST 风格的 flickr.groups.members.getList 的 sample response

 <members page="1" pages="1" perpage="100" total="33">
 <member href=" http://api.flickr.com/services/rest/?
 method=flickr.people.getInfo?auth_key=xxxx&user_id=123456@N01"
  username="foo" iconserver="1" iconfarm="1" membertype="2"/>
 <member href=" http://api.flickr.com/services/rest/?
 method=flickr.people.getInfo?auth_key=xxxx&user_id=118210@N07"
  username="kewlchops666" iconserver="0" iconfarm="0" membertype="4"/>
 <member href=" http://api.flickr.com/services/rest/?
 method=flickr.people.getInfo?auth_key=xxxx&user_id=119377@N07"
  username="Alpha Shanan" iconserver="0" iconfarm="0" membertype="2"/>
 <member href=" http://api.flickr.com/services/rest/?
 method=flickr.people.getInfo?auth_key=xxxx&user_id=67783977@N00"
  username="fakedunstanp1" iconserver="1003" iconfarm="2" membertype="3"/>
 ...
 </members>

通过前面关于“统一接口”的解析,我们清楚地知道,REST 风格的架构使得 web 服务的“客户端”和“服务器端”很好的分离开来。“客户端”不需要关心数据的存储,使得“客户端”的可移植性(portability)提高了。“服务器端”不用关心用户的接口和用户的状态,所以“服务器端”将变得更加简单,而且方便的获得更好的可伸缩性(scalability)。只要保持接口的定义不变 ,“客户端”和“服务器端”可以独立的开发和演变。

一个定义良好的 RESTful Web 服务接口

首先,用一个文档描述 web 服务的 capabilities 以及服务的 location。如清单 15 所示。


清单 15. 用 APP 协议描述的服务 capabilities 和 location

 <?xml version="1.0" encoding="UTF-8"?>
 <service xmlns="http://www.w3.org/2007/app"
  xmlns:atom="http://www.w3.org/2005/Atom">
 <workspace>
 <atom:title type="text"> InfoSphere MashupHub </atom:title> 

 <collection href="http://localhost:8080/mashuphub/atom?collection=all">
 <atom:title type="text"> All </atom:title>
 <accept> application/atom+xml; type=entry </accept>
 <categories> <categories> ALL </categories> </categories>
 </collection> 

 <collection href="http://localhost:8080/mashuphub/atom?collection=feeds">
 <atom:title type="text">Feeds</atom:title>
 <accept> application/atom+xml;type=entry </accept>
 <categories> <categories> feeds </categories> </categories>
 </collection>
…
 </workspace>
 </service>


这个服务文档指明 InfoSphere MashupHub 提供了一系列的 web 服务,包括 list 所有的资源,list 所有的 feeds 等等。并且还描述了每个 web 服务的 location 可以提供的 resource representation 的类型。这种描述文档对于 web 服务的客户端来说非常有益。这个服务描述文档本身也是一个 resource,可以用 HTTP URI 定位到。

其次,我们来看一下每个 web 服务是怎么定义的。


清单 16. RESTful web 服务接口的定义示例

 1) Resource:所有的 feeds
 2) Resource URI:
 http://localhost:8080/mashuphub/atom?collection=feeds
 3) Resource representation:
 <feed xmlns="http://www.w3.org/2005/Atom">
  <id>
  http://9.186.64.113:8080/mashuphub/atom?collection=feed </id>
  <link href="http://9.186.64.113:8080/mashuphub/atom?collection=feeds"
  rel ="self"></link>
  <updated> 2010-09-11 T 15:12:24.968Z </updated>
  <title type = "text"> feeds Collection </title>
  <author>
    <name> InfoSphere MashupHub Search Feed</name>
  </author>
 <entry>
 <author>
      <name> InfoSphere MashupHub Search Feed </name>
    </author>
    <title type="html"> MyCo Customer List </title>
    <updated> 2010-09-07 T 05:08:52.000Z </updated>
    <id> urn:id:1460 </id>
 <link href="http://9.186.64.113:8080/mashuphub/atom?collection=feeds&amp;id=1460"
 rel="self"></link>
 <link href="http://9.186.64.113:8080/mashuphub/atom?collection=feeds&amp;id=1498"
 rel="related" title = "MyCo Customer List with weather info" > </link>
    <category term="feed"> </category>
    <content type = "application/xml" >
      <catalog:feed xmlns:catalog="http://www.ibm.com/xmlns/atom/opensearch/feed/1.0/">
        <catalog:version> 1.0 </catalog:version>
        <catalog:name> MyCo Customer List </catalog:name>
        <catalog:author> admin </catalog:author>
        <catalog:permission> public </catalog:permission>
        <catalog:description> </catalog:description>
        <catalog:rating> 0.0 </catalog:rating>
        <catalog:useCount> 320 </catalog:useCount>
        <catalog:dateModified> 1283836132 </catalog:dateModified>
        <catalog:numComments> 0 </catalog:numComments>
        <catalog:tags> </catalog:tags>
    <catalog:categories> </catalog:categories>
    <catalog:downloadURL>http://9.186.64.113:8080/mashuphub/client
    /plugin/generate/entryid/1460/pluginid/3
     </catalog:downloadURL>
        <catalog:mimetype> application/atom+xml </catalog:mimetype>
      </catalog:feed>
    </content>
 </entry>
 </feed>
 4) Http method: GET
 5) 和别的 resource 的关系。
 在 representation 中用 <link>
 定义了“MyCo Customer List”和“MyCo Customer List with weather info”的关系


总结一下,一个设计良好的 RESTful web 服务应该包括一下几个定义:

  • 1) 服务描述文档,如清单 15 所示;
  • 2) 资源 (resource) 及其 identification;
  • 3) 资源的 representation 的定义
  • 4) 用 HTTP method 表示的资源的 manipulation
  • 5) 在资源的 representation 里面以 Hyperlink 表述的资源和资源之间的关系

结束语

REST 是一种架构风格,汲取了 WWW 的成功经验:无状态,以资源为中心,充分利用 HTTP 协议和 URI 协议,提供统一的接口定义,使得它作为一种设计 Web 服务的方法而变得流行。在某种意义上,通过强调 URI 和 HTTP 等早期 Internet 标准,REST 是对大型应用程序服务器时代之前的 Web 方式的回归。

本文根据 Roy 的论文,结合实际的例子,重新解析了 REST 中的核心概念。根据作者多年的创建和使用 RESTful web 服务的经验,更多的是在观念上的澄清。最后通过一个 RESTful web 服务,告诉读者一个真正意义上的 RESTful web 服务是什么样子。但愿本文的讨论会您提供了一定意义上的思想上的指导和实践上的指导。


参考资料

学习

  • Roy Fielding 论文“Architectural Styles and the Design of Network-based Software Architectures” 描述了一个框架来使用架构样式理解软件架构,并演示了如何使用样式指导基于网络的应用程序软件的架构设计。
  • 构建 RESTful Web 服务 介绍如何使用 Restlet(一个面向 Java™ 应用程序的轻量级框架)构建 RESTful 应用程序。
  • 编写 REST 服务 介绍了 REST 和 Atom 发布协议(Atom Publishing Protocol,APP)的概念,展示了其在服务中的应用。
  • ATOM: ATOM specification.
  • RSS RSS specification.
  • ATOM Publishing Protocol: APP 协议标准。
  • 深入浅出 REST 对 REST(Web 架构)背后的概念提供快速的介绍。
  • RESTful Web Services 描述了如何利用可编程应用程序的 Web 功能。
  • Implementing RESTful Web services in Java 介绍如何编写遵从 JAX-RS: Java API for RESTful Web Services (JSR-311) 规范的 RESTful web 服务。
  • RESTful Web Services 描述了如何利用可编程应用程序的 Web 功能。

讨论

关于作者

马 春娥,工作在 IBM 中国软件开发中心 Web 2.0 开发小组,开发人员,曾参与 Project Zero 和 Lotus Mashup Center 的开发。主要的关注点在 Web 2.0 领域的数据的建模,数据的处理,数据的可视化,Web2.0 领域的数据的语义,数据的关联等。

——————————————————-分割线——————————————————–

摘了这么长,还有几件事需要自己做的,记一下先:

1.对比分析几个REST API:新浪微博,TWITTER

2.对ATOM和RSS做个了结

3.对昊哥REST Service的实现了解下先


如何选择开源许可证?

如何为代码选择开源许可证,这是一个问题。

世界上的开源许可证,大概有上百种。很少有人搞得清楚它们的区别。即使在最流行的六种—-GPLBSDMITMozillaApacheLGPL—-之中做选择,也很复杂。

乌克兰程序员Paul Bagwell,画了一张分析图,说明应该怎么选择。这是我见过的最简单的讲解,只用两分钟,你就能搞清楚这六种许可证之间的最大区别。

下面是我制作的中文版,请点击查看大图:

Via:阮一峰

——————————-分割线————————————

记得Felix跟我说过一个巨操蛋的Do What Fuck You Want To Do协议的,不记得具体叫什么了…….

总结下字符编码格式

这两天小朋友碰到些编码问题,我今天顺便看了下,怕忘了就记一下吧:

ASCII:基本字符集是128个常用字符,扩展字符集是128个,共256个,用1个字节表示。
GB2312:6千多个常用汉字
GBK:1万多个汉字
GB18030:更多,不过依然是两个字节来表示汉字。
上面三种GB*可以统一称为ANSI编码,且16个bit的第一个必定是1。
BIG5:繁体字符集,用于台湾地区

Unicode:两字节表示的世界通用码,存储为文本时会有连个字节的头信息。
UTF-8:一种以8个bit为一组的Unicode的表示格式,存储为本文时有三个字节的头信息。
UTF-16:16个bit为一组

—————————————–分割线一枚—————————————

ASCII 字符集

1.名称的由来

ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是基于罗马字母表的一套电脑编码系统。

2.特点

它主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO 646。

3.包含内容

控制字符:回车键、退格、换行键等。

可显示字符:英文大小写字符、阿拉伯数字和西文符号

4.技术特征

7位(bits)表示一个字符,共128字符

5.ASCII扩展字符集

7位编码的字符集只能支持128个字符,为了表示更多的欧洲常用字符对ASCII进行了扩展,ASCII扩展字符集使用8位(bits)表示一个字符,共256字符。

ASCII扩展字符集比ASCII字符集扩充出来的符号包括表格符号、计算符号、希腊字母和特殊的拉丁符号。

GB2312 字符集

1.名称的由来

GB2312又称为GB2312-80字符集,全称为《信息交换用汉字编码字符集·基本集》,由原中国国家标准总局发布,1981年5月1日实施。

2.特点

GB2312是中国国家标准的简体中文字符集。它所收录的汉字已经覆盖99.75%的使用频率,基本满足了汉字的计算机处理需要。在中国大陆和新加坡获广泛使用。

3.包含内容

GB2312收录简化汉字及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母,共 7445 个图形字符。其中包括6763个汉字,其中一级汉字3755个,二级汉字3008个;包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。

4.技术特征

(1)分区表示:

GB2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为区位码。

各区包含的字符如下:01-09区为特殊符号;16-55区为一级汉字,按拼音排序;56-87区为二级汉字,按部首/笔画排序;10-15区及88-94区则未有编码。

(2)双字节表示

两个字节中前面的字节为第一字节,后面的字节为第二字节。习惯上称第一字节为“高字节” ,而称第二字节为“低字节”。

“高位字节”使用了0xA1-0xF7(把01-87区的区号加上0xA0),“低位字节”使用了0xA1-0xFE(把01-94加上0xA0)。

5.编码举例

以GB2312字符集的第一个汉字“啊”字为例,它的区号16,位号01,则区位码是1601,在大多数计算机程序中,高字节和低字节分别加0xA0得到程序的汉字处理编码0xB0A1。计算公式是:0xB0=0xA0+16, 0xA1=0xA0+1。

BIG5 字符集

1.名称的由来

又称大五码或五大码,1984年由台湾财团法人信息工业策进会和五间软件公司宏碁 (Acer)、神通 (MiTAC)、佳佳、零壹 (Zero One)、大众 (FIC)创立,故称大五码。

Big5码的产生,是因为当时台湾不同厂商各自推出不同的编码,如倚天码、IBM PS55、王安码等,彼此不能兼容;另一方面,台湾政府当时尚未推出官方的汉字编码,而中国大陆的GB2312编码亦未有收录繁体中文字。

2.特点

Big5字符集共收录13,053个中文字,该字符集在中国台湾使用。耐人寻味的是该字符集重复地收录了两个相同的字:“兀”(0xA461及0xC94A)、“嗀”(0xDCD1及0xDDFC)。

3.字符编码方法

Big5码使用了双字节储存方法,以两个字节来编码一个字。第一个字节称为“高位字节”,第二个字节称为“低位字节”。高位字节的编码范围0xA1-0xF9,低位字节的编码范围0x40-0x7E及0xA1-0xFE。

各编码范围对应的字符类型如下:0xA140-0xA3BF为标点符号、希腊字母及特殊符号,另外于0xA259-0xA261,存放了双音节度量衡单位用字:兙兛兞兝兡兣嗧瓩糎;0xA440-0xC67E为常用汉字,先按笔划再按部首排序;0xC940-0xF9D5为次常用汉字,亦是先按笔划再按部首排序。

4.Big5 的局限性

尽管Big5码内包含一万多个字符,但是没有考虑社会上流通的人名、地名用字、方言用字、化学及生物科等用字,没有包含日文平假名及片假名字母。

例如台湾视“着”为“著”的异体字,故没有收录“着”字。康熙字典中的一些部首用字(如“亠”、“疒”、“辵”、“癶”等)、常见的人名用字(如“堃”、“煊”、“栢”、“喆”等) 也没有收录到Big5之中。

Unicode字符集

1.名称的由来

Unicode字符集编码是Universal Multiple-Octet Coded Character Set 通用多八位编码字符集的简称,是由一个名为 Unicode 学术学会(Unicode Consortium)的机构制订的字符编码系统,支持现今世界各种不同语言的书面文本的交换、处理及显示。该编码于1990年开始研发,1994年正式公布,最新版本是2005年3月31日的Unicode 4.1.0。

2.特征

Unicode是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

3.编码方法

Unicode 标准始终使用十六进制数字,而且在书写时在前面加上前缀“U+”,例如字母“A”的编码为 004116 和字符“?”的编码为 20AC16。所以“A”的编码书写为“U+0041”。

4.UTF-8 编码

UTF-8的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

下表总结了编码规则,字母x表示可用编码的位。

Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
——————–+———————————————
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

下面,还是以汉字“严”为例,演示如何实现UTF-8编码。

已知“严”的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此“严”的UTF-8编码需要三个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,“严”的UTF-8编码是“11100100 10111000 10100101”,转换成十六进制就是E4B8A5。

5.UTF-16 和 UTF-32 编码
UTF-32、UTF-16 和 UTF-8 是 Unicode 标准的编码字符集的字符编码方案,UTF-16 使用一个或两个未分配的 16 位代码单元的序列对 Unicode 代码点进行编码;UTF-32 即将每一个 Unicode 代码点表示为相同值的 32 位整数。

—————————————–分割线再一枚———————————–

实例

下面,举一个实例。

打开”记事本“程序Notepad.exe,新建一个文本文件,内容就是一个”严“字,依次采用ANSI,Unicode,Unicode big endian 和 UTF-8编码方式保存。

然后,用文本编辑软件UltraEdit中的”十六进制功能“,观察该文件的内部编码方式。

1)ANSI:文件的编码就是两个字节“D1 CF”,这正是“严”的GB2312编码,这也暗示GB2312是采用大头方式存储的。

2)Unicode:编码是四个字节“FF FE 25 4E”,其中“FF FE”表明是小头方式存储,真正的编码是4E25。

3)Unicode big endian:编码是四个字节“FE FF 4E 25”,其中“FE FF”表明是大头方式存储。

4)UTF-8:编码是六个字节“EF BB BF E4 B8 A5”,前三个字节“EF BB BF”表示这是UTF-8编码,后三个“E4B8A5”就是“严”的具体编码,它的存储顺序与编码顺序是一致的。

 延伸阅读

The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets(关于字符集的最基本知识)

谈谈Unicode编码

RFC3629:UTF-8, a transformation format of ISO 10646(如果实现UTF-8的规定)

————————————-分割线又一枚——————————————

//TO-Do

1.主流语言中的编码支持

2.编程当中需要注意的编码问题