在RESTful应用程序中的超媒体

超媒体到底是什么?!

如果你有幸听说过REST架构风格,那么你也可能听说某些人认为统一接口是最重要的约束,尤其是该接口在制约资源上能被调用的方法方面。但是,你没有意识到的是,对于统一接口还有很多东西。特别是一个被笨拙地冠以“超媒体即应用状态引擎(hypermedia as the engine of application state)”名字的子约束,它可以认为是REST最重要的约束,在某种意义上它独力塑造了我们所熟知的RESTful系统的大部分的“形状”。

定义

不幸的是,REST论文没有在这个约束上展开,除了它的名字和对它实际应用的描述:

所以,模型应用是一个从一个状态迁移到下一个状态的引擎,迁移是通过对当前表述性集合中可选状态进行检查和选择而完成的。

尽管它给我们提供了一个有用的描述,但是在我看来,它不能帮助我们真正理解约束本身的作用域;约束真正允许的是什么,不允许的又是什么。由此开始,接下来还值得注意的是我们能从约束自身名字中获取些什么信息。

“应用状态”指的是一个状态,它决定了用户在完成一个任务的流程中所处的“位置”。例如,在做个人银行业务的时候,用户是正在浏览帐户余额,还是在填写账目付款单,或者是在订购新的支票?它们每个都是不同的应用状态。有些人错误地认为“状态”是指资源状态,在上面例子里,资源是指帐户余额或者近期付款清单。但“应用状态”和“资源状态”是不同的。

应用状态也被称为“会话状态”,该状态也是REST的“无状态”约束所指的状态,这种约束要求客户端独自维持状态。反之,如果你使用诸如VNC或者Windows远程桌面的远程会话技术,那么应用状态完全保存在服务器上。

Ted Nelson在1962年创造了“超媒体”一词,是他发明的“超文本”泛化。鉴于超文本产生了内部互联的文本文档,那么超媒体将范围扩展到了任何形式的媒体。当然,两者的关键点都是我们可以在使用的内容嵌入链接。

约束实战

REST在2003/2004年开始获得一些从事面向互联网服务开发者的关注——至少这些开发者确实将他们的服务冠以“REST”的绰号——最明显的是两个高调、自我标榜的“REST API”:Flickr和Amazon。有趣的是两个服务也同时提供了基于SOAP的接口,但是与“REST API”相比,这两个SOAP API都没有显出更多的使用。最终,REST社区拥抱了这些服务,并且将它们作为一种进一步解释在Web上使用REST风格的价值和魅力的工具。不幸的是,这些API存在一个问题:它们不完全是RESTful的,因为它们无视(至少)一个REST约束。事实上,Flickr API(以及Amazon、del.icio.us等等)的问题比我们在此讨论的要多得多,此处我们只关注那些和超媒体有关系的问题。

幸运的是,我们不需要为寻找这些问题花太多时间。以“flickr.contacts.getList”操作返回的样本数据为例,用户可使用该操作获得他们自己的联系人清单:

<contacts page="1" pages="1" perpage="1000" total="3">
<contact nsid="12037949629@N01" username="Eric" iconserver="1"
realname="Eric Costello"
friend="1" family="0" ignored="1" />
<contact nsid="12037949631@N01" username="neb" iconserver="1"
realname="Ben Cerveny"
friend="0" family="0" ignored="0" />
<contact nsid="41578656547@N01" username="cal_abc" iconserver="1"
realname="Cal Henderson"
friend="1" family="1" ignored="0" />
</contacts>

这里,“nsid”属性包含了一个表示单个联系人的唯一标识符,在这个例子里是其中的三个联系人。但是一旦客户端已经检索到了这个文档,接下来会怎样?如果他们想了解更多关于Cal Henderson的信息怎么办?通过快速检查Flickr API文档,可以发现有一个叫做"flickr.people.getInfo"的操作,它接收nsid作为一个参数,返回那个nsid字符串所标识联系人的更多信息。那么为了获得关于Cal的更多信息,我们在HTTP GET消息中需要使用的URI将是:

http://api.flickr.com/services/rest/?method=flickr.people.getInfo?auth_key=xxxx&user_id=41578656547@N01这不是超媒体。一个超媒体解决方案会使用标准化的标识符——对于Web来说就是URI——而非私有的标识符,这避免了客户端在从联系人清单文档浏览到个人信息文档过程中需要特定于Flickr的知识。如果采用标准标识符,那么第一个文档应该是:<contacts page="1" pages="1" perpage="1000" total="3">
<contact nsid="http://api.flickr.com/services/rest/?method=flickr.people.getInfo?auth_key=xxxx&user_id=12037949629@N01" username="Eric" iconserver="1"
realname="Eric Costello"
friend="1" family="0" ignored="1" />
<contact nsid="http://api.flickr.com/services/rest/?method=flickr.people.getInfo?auth_key=xxxx&user_id=12037949631@N01" username="neb" iconserver="1"
realname="Ben Cerveny"
friend="0" family="0" ignored="0" />
<contact nsid="http://api.flickr.com/services/rest/?method=flickr.people.getInfo?auth_key=xxxx&user_id=41578656547@N01" username="cal_abc" iconserver="1"
realname="Cal Henderson"
friend="1" family="1" ignored="0" />
</contacts>

时间: 2024-11-08 23:23:39

在RESTful应用程序中的超媒体的相关文章

jersey-Jersey+Spring程序中如何实现拦截器

问题描述 Jersey+Spring程序中如何实现拦截器 如题,项目中采用了Jersey+Spring实现Restful webservice,现在要对接口进行身份验证,方案已经确定,但如何实现类似于struts或SpringMVC的interceptor的效果?对所有请求进行身份验证1,备选方案是利用J2EE的filter2,想通过Spring的AOP来实现,切面是Jersey的Resource,但怎样注入HttpServletRequest呢? 解决方案 Jersey本身就提供了Reques

在Java程序中实现FTP的上传下载

FtpList部分是用来显示FTP服务器上的文件:GetButton部分为从FTP服务器下传一个文件:PutButton部分为向FTP服务器上传一个文件. 别忘了在程序中还要引入两个库文件(importsun.net.*,import sun.net.ftp.*). 以下是这三部分的JAVA源程序: (1)显示FTP服务器上的文件 void ftpList_actionPerformed(ActionEvent e) { String server=serverEdit.getText(); /

应用-android中设置支持javascript会引入xss变量到你的程序中,请检查清楚

问题描述 android中设置支持javascript会引入xss变量到你的程序中,请检查清楚 Using setJavaScriptEnabled can introduce XSS vulnerabilities into you application, review carefully. 如何理解上面这句英语啊?? 解决方案 你指的是在webView上设置支持JavaScript么? 解决方案二: @SuppressLint("SetJavaScriptEnabled") 忽略

声音文件-Borland C++ 想在程序中增加播放声频

问题描述 Borland C++ 想在程序中增加播放声频 如果操作有误的话就像Windows操作系统一样有个声音提示,具体该怎么操作?最好提供源码,谢谢,声音文件来自于C:windowsMedisWindows xp 错误.wav,我不太会定义,是Borland C++中有关于声频的控件么?

在android程序中打开HPROF文件时出错

问题描述 在android程序中打开HPROF文件时出错 当我用Memory Analyzer打开HPROF文件时(由Debug.dumpHprofData创建),得到的是以下的异常: java.io.IOException: Unknown HPROF Version (JAVA PROFILE 1.0.3) at org.eclipse.mat.hprof.AbstractParser.readVersion(AbstractParser.java:124) at org.eclipse.m

为什么c程序中创建了数据文件,再次打开源代码运行时数据没了?

问题描述 为什么c程序中创建了数据文件,再次打开源代码运行时数据没了? 为什么c程序中创建了数据文件,再次打开源代码运行时数据没了? http://blog.csdn.net/hackbuteer1/article/details/6573488# 就是这个通讯录的代码,在里面创建通讯录后,再次打开运行显示通讯录时就提示通讯录为空. 解决方案 写入文件是否错误,用winhex或者ultraedit看看写文件本身有没有写对. 如果没有,就是写的问题,如果对的,那么就是读的问题.再具体调试有问题的程

android-如何隐藏应用程序中的软键盘?

问题描述 如何隐藏应用程序中的软键盘? 当启动程序时,我想隐藏应用程序中的软键盘.我使用下面的代码,但是没有实现效果.请问如何隐藏应用程序中的软键盘? InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);imm.hideSoftInputFromWindow(notes.getWindowToken() 0); 解决方案 getWindow().setSoftIn

在整个应用程序中锁定 android 方向为横向模式

问题描述 在整个应用程序中锁定 android 方向为横向模式 如何在整个应用程序中锁定 android 方向为横向模式? <activity android:screenOrientation=""landscape"" android:name="".BasicLayoutCheckActivity"" /> 这段代码不能运行,如果使用另外一个 activity,就变成纵向模式. 解决方案 在 Manifest

ios-越狱的iPhone程序中删除应用图标

问题描述 越狱的iPhone程序中删除应用图标 在越狱设备上,通过编程删除应用图标.不知道怎么做?谢谢 解决方案 修改应用绑定的Info.plist文件,填上这个 : <key>SBAppTags</key><array> <string>hidden</string></array> 点击这里