《RESTful Web Services》学习笔记

《RESTful Web Services》Leonard Ricbardson & Sam Ruby
前言
每个Web应用(包括每个网站)都是一个服务。
Web 服务就是为机器设计的网站。 
REST: Representational State Transfer(表示性状态转移)
我们引入了面向资源的架构(Resource-Oriented Architecture, ROA)作为用于设计REST式Web服务(RESTful web services)的一组切合实际的原则。
从HTTP0.9中我们可以看到可寻址性(addressablity)和无状态性(statelessness)-正是这两条基本设计原则,另HTTP较其同类更加优秀,并得以延伸到今天如此巨大的规模。
万维网(World Wide Web)是一个简单而灵活的分布式编程环境。
为人类使用而设计的 human web, 跟为软件程序调用而设计的 programmable web 没有本质区别。
第1章  Programmable Web 及其分类
programmable web 跟 human web 的主要不同在于:programmable web 返回的不是令人赏心悦目的HTML页面,而是冷漠刻板的XML文档。
Web服务客户端必须自动从HTTP响应中提取含义,并根据含义决定下一个动作。
programmable web 是基于 HTTP 和 XML 技术的。
HTTP:信封里的文档
HTTP 是一种基于文档的协议。客户端把文档放在信封里,然后发给服务器,作为回应,服务器把响应文档放在信封里,然后发给客户端。
方法信息
作用域信息
常见的Web服务架构主要有三种:REST 式架构、RPC 式架构和 REST-RPC 混合架构
REST式、面向资源的架构
REST式意味着,方法信息(method information)都在 HTTP 方法(HTTP method)里;面向资源的架构(ROA)意味着,作用域信息(scoping information)都在 URI 里。
RPC 式架构
RPC式架构意味着:方法信息和作用域信息都在信封或报头里。
REST 式服务为不同的作用域信息暴露不同的URI;而RPC式服务一般为每个“文档处理器”暴露一个URI。
REST-RPC 混合架构
由于 HTTP 工作方式的原因,任何采用普通 HTTP 并暴露多个 URI 的 RPC 式服务,往往最终成为 REST 式架构或混合架构。
Human Web 是基于 Programmable Web 的
只要 Web 服务客户端是基于 Web 的,它就是 Web 服务。
Programmable Web 涉及的技术
HTTP
对于一个 REST 式 Web 服务,它会在 HTTP 方法里寻找方法信息,在 URI 里寻找作用域信息;而 RPC 式 Web 服务则往往忽略 HTTP 方法,在 URI、HTTP 报头或实体主体里寻找方法信息和


作用域信息。
URI
一个 REST 式面向资源的服务为客户端可能操作的每一则数据暴露一个URI;一个 REST-RPC 混合服务,为客户端可能进行的每一个操作暴露一个 URI(比如取数据用一个 URI,删除数据用一


个 URI);一个 RPC 式服务,为每个处理远程调用的进程暴露一个 URI,一般来说这样的 URI 只有一个,即服务的“端点(endpoint)”。
XML-RPC
XML-RPC 是一种用于表达“函数调用及其返回值”的数据机构格式,它是专门用于 RPC 式 Web 服务的。
SOAP
跟 HTTP 一样,SOAP 也是一种信封格式,只不过它是基于 XML 的。基本上,现在每个采用 SOAP 的 Web 服务都属于 RPC 式架构。
WS-*
这些标准定义各种特定用途的 SOAP 报头。
WSDL
WSDL(Web Service Description Language, Web 服务描述语言) 是一套用于描述 SOAP Web 服务的 XML 词汇。
WADL
WADL(Web Application Description Language, Web 应用描述语言) 是一套用于描述 REST 式 Web 服务的 XML 词汇。


第2章  编写 Web 服务客户端
Web 服务就是网站


示例2-1:用 Yahoo!Web 服务搜索 Web
#!/usr/bin/ruby
# yahoo-web-search.rb
require 'open-uri'
require 'rexml/document'
require 'cgi'


BASE_URI = 'http://api.search.yahoo.com/WebSearchService/V1/webSearch'


def print_page_titles(term)
# 获取资源(一个包含搜索结果的 XML 文档)
term = CGI::escape(term)
xml = open(BASE_URI + "?appid=restbook&query=#{term}").read


# 把上述 XML 文档解析为一个数据结构
document = REXML::Document.new(xml)


# 用 XPath 在数据结构里寻找相关信息
REXML::XPath.each(document, '/ResultSet/Result/Title/[]') do |title|
puts title
end
end


(puts "Usage: #{$0} [search term]"; exit) if ARGV.empty?
print_page_title(ARGV.join(' '))


del.icio.us: 示例应用
服务器应该是理想主义的,客户端必须是实用主义的-这是 Postel 法则“严以律己,宽以待人”的一个变形。


Ruby: rest-open-uri 和 net/http
示例2-4:一个采用 open-uri 的 del.icio.us 客户端
#!/usr/bin/ruby -w
# delicious-open-uri.rb


require 'rubygems'
require 'open-uri'
require 'rexml/document'


# 获取一个 del.icio.us 用户的最近书签,并把每个书签打印出来。
def print_my_recent_bookmarks(username, password)
# 发送 HTTPS 请求
response = open('https://api.del.icio.us/v1/posts/recent', :http_basic_authentication => [username, password])


# 把返回的实体主体作为 XML 文档来读取
xml = response.read


# 把 XML 文档解析为一个数据结构
document = REXML::Document.new(xml)


# 对于每个书签...
REXML::XPath.each(document, "/posts/post") do |e|
# 打印书签的描述和网址
puts "#{e.attributes['description']}: #{e.attributes['href']}"
end
end


# 主程序
username, password = ARGV
unless username and password
puts "Usage: #{$0} [username] [password]"
exit
end
print_my_recent_bookmarks(username, password)


Python: httplib2
示例2-5:一个用 Python 编写的 del.icio.us 客户端
#!/usr/bin/python2.5
# delicious-httplib2.py
import sys
from xml.etree import ElementTree
import httplib2


# 获取一个 del.icio.us 用户的最近书签,并把每个书签打印出来
def print_my_recent_bookmarks(username, password)
client = httplib2.Http(".cache")
client.add_credentials(username, password)


# 发出 HTTP 请求,并获取响应和实体主体
response, xml = client.request('https://api.del.icio.us/v1/posts/recent')


# 把 XML 格式的实体主体转换成一个数据结构
doc = ElementTree.fromstring(xml)


# 打印出每个书签的信息
for post in doc.findall('post'):
print "%s: %s" % (post.attrib['description'], post.attrib['href'])


# 主程序
if len(sys.argv) != 3:
print "Usage: %s [username] [password]" % sys.argv[0]
sys.exit()


username, password = sys.argv[1:]
print_my_recent_bookmarks(username, password)


Java: HttpClient


C#: System.Web.HTTPWebRequest


PHP: libcurl


JavaScript: XMLHttpRequest


命令行:curl
$curl https://username:password@api.del.icio.us/v1/posts/recent


用 XML 解析器处理响应
有两种基本的 XML 解析策略:基于文档的策略(DOM 等树式解析器)和基于事件的策略(SAX 及拖式解析器)
Ruby: REXML
示例2-9:采用 REXML 的 SAX 解析器
#!/usr/bin/ruby -w
# delicious-sax.rb
require 'open-uri'
require 'rexml/parsers/sax2parser'


def print_my_recent_bookmarks(username, password)
# 发出 HTTPS 请求,并把响应实体主体作为 XML 文档来读取
xml = open('https://api.del.icio.us/v1/posts/recent', :http_basic_authentication => [username, password])


# 创建一个 SAX 解析器来解析 XML 实体主体
parser = REXML::Parsers::SAX2Parser.new(xml)


# 当 SAX 解析器遇到 "post" 标签时...
parser.listen(:start_element, ["post"]) do |uri, tag, fqtag, attributes|
# 打印出该标签信息
puts "#{attributes['description']}: #{attributes['href']}"
end


# 让解析器开始解析 XML 实体主体
parser.parse
end


# 主程序
username, password = ARGV
unless username and pass
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值