Enterprise REST = Customize, Invent and Standardize Media Types

 


关于REST, 经常容易引起困惑的一个问题是:在 Machine-to-machine 的 REST 应用中, 客户端怎么可能在没有任何预先知识的情况下就能跟随服务器端返回的超文本来自适应的将应用程序逻辑进行下去?

答案是不可能 . Client端必须提前了解足够的 server端返回的超文本的知识 , 才能跟随其中的指示将逻辑进行下去 . 那跟 SOAP, WSDL之类的又有啥区别 ? 答案在于 REST 要求的 “足够知识 ”要远远弱于 WSDL对服务接口定义的约束 , 其灵活性则高于 WSDL. 毕竟 , REST 架构风格着眼于生命周期较长的 , 不断演化的 , 跨组织边界的应用程序 . 可以用来满足 HATEOAS这个 REST约束的武器就是 Media Type: 扩展已有的 Media Type, 发明新的 Media Type, 并在合适的范围内标准化

 

来看两个例子 .

 

Web的成功与其说是 HTTP的成功 , 不如说是 HTML的成功 , 或者说 text/html这种 Media Type的成功 . HTML定义了一组有限的 , 标准化的 , 特定领域的标签 . 所有的 HTML客户端都能理解并按照自己的能力渲染出 Web服务器返回的任何合法的 HTML. 从全功能的 Chrome/FireFox /Safari/IE, 到只是显示文本的 lynx, 到资源受限环境下如手机中的各种浏览器 , 都能将多姿多彩的 Web呈现给最终用户 , 并引导他们进行下一步交互

最经常被拿来作为 machine-to-machine REST 应用成功案例的则是 RSS/ATOM. 这族标准定义了新的 Media Type, application/rss+xml , application/atom+xml . 不出意外的 , 这组 Media Types定义了一组有限的 , 标准化的 , 特定领域的标签 . 每一个 RSS/ATOM客户端应用都可以从某个资源的 application/rss (atom)+xml的表述开始 , 顺藤摸瓜的遍历每个感兴趣的资源 . 这些客户端都理解每一个 RSS/ATOM定义的标签 . 服务端可以自由的改变新资源的 URI/URL Template而不必担心破坏现有的 Client, 因为这些 Client并不依赖于预先设定的 URL Template, 而仅仅依赖于一个 Root的表述 , 及标准的 link relations

 

回到我们的问题 . 那么 REST要求的 “足够知识 ”要弱到什么程度 , 才能既使客户端能理解服务器给出的线索 , 又不致于耦合的太紧以致服务器和客户端无法独立演化 ? 观察上面两个例子 , 它们有以下共同特点 :

1. Response是 Well-formed ,可以被客户端解析 . 这是废话 , 除了 AI应用 , 绝大部分网络应用都得有明确定义的协议 . 但这意味着 REST 应用中也必须明确定义客户端和服务器数据交换的格式

2. Response中包含了当前上下文 ( 或资源 )相关的信息 , 但对我们这个问题来说更重要的是包含了对其它资源进行访问的线索 . 是的 , 它是用最最基本 , 最最普通的 link 来实现的 . 足够弱 . 那语义是否足够清晰到客户端能理解每一个 link, 能够选择正确的 link并知道如何访问呢 ? 我们来看看 link上都能承载啥语义 (from http://www.ietf.org/rfc/rfc5988.txt):

  Link           = "Link" ":" #link-value
  link-value     = "<" URI-Reference ">" *( ";" link-param )
  link-param     = ( ( "rel" "=" relation-types )
                 | ( "anchor" "=" <"> URI-Reference <"> )
                 | ( "rev" "=" relation-types )
                 | ( "hreflang" "=" Language-Tag )
                 | ( "media" "=" ( MediaDesc | ( <"> MediaDesc <"> ) ) )
                 | ( "title" "=" quoted-string )
                 | ( "title*" "=" ext-value )
                 | ( "type" "=" ( media-type | quoted-mt ) )
                 | ( link-extension ) )
  link-extension = ( parmname [ "=" ( ptoken | quoted-string ) ] )
                 | ( ext-name-star "=" ext-value )
  ext-name-star  = parmname "*" ; reserved for RFC2231-profiled
                                ; extensions.  Whitespace NOT
                                ; allowed in between.
  ptoken         = 1*ptokenchar
  ptokenchar     = "!" | "#" | "$" | "%" | "&" | "'" | "("
                 | ")" | "*" | "+" | "-" | "." | "/" | DIGIT
                 | ":" | "<" | "=" | ">" | "?" | "@" | ALPHA
                 | "[" | "]" | "^" | "_" | "`" | "{" | "|"
                 | "}" | "~"
  media-type     = type-name "/" subtype-name
  quoted-mt      = <"> media-type <">
  relation-types = relation-type
                 | <"> relation-type *( 1*SP relation-type ) <">
  relation-type  = reg-rel-type | ext-rel-type
  reg-rel-type   = LOALPHA *( LOALPHA | DIGIT | "." | "-" )
  ext-rel-type   = URI

这里我们重点考察一下 rel media-type 属性

 

在 ATOM(http://www.ietf.org/rfc/rfc4287.txt)里 , 缺省定义了 5种 link relations, 分别是 alternate, related, self, enclosure和 via. 标准赋予它们明确的语义 , 比如 alternate表示 link所指向的目标是当前资源的备用版本 . 客户端因此可以理解每个 link的含义 , 自动或引导用户完成后面的操作 . 如何完成?则牵扯到 media-type . 比如如果 media-type定义的是 audio/mp4,客户端则可以显示播放选项或自动播放或干脆忽略 .

 

这里 link以及 media-type等属性帮助形成了一个递归的过程 . 我们从某个 link开始 , 知晓它的 media-type(所谓知晓它的 media-type, 就是能理解这种 media-type定义的每一个元素的语义 ), 我们就能够得到这个 link所指向的资源以这种 media-type表现出来的一种表述 , 其中包含了其它可用的 link以及 media-type, 可以让这个过程一直继续下去 , 直到客户端觉得可以了或者服务端返回了不包含任何其它 link的表述 .

 

然而初始的 media-type和 link relations总是有限的 , 我们如何应对现有 media-type表达不了的语义?这就是 HTML和 RSS/ATOM例子包含的第三个要素

 

3. 定义领域相关的 media-type . HTML的问题域是如何表达各种显示效果 , RSS/ATOM则是如何发布信息 . media-type以及 link relations等都是可扩展的 . 我们要做的就是为我们的特定领域的应用定义扩展 , 如果现存的被标准化的元素不够用的话 . 这里有一个问题 , 就是 REST应用的范围的问题 . 如果我们的应用是面向 internet的 , 面向无数已知的未知的客户端应用的 , 则意味着我们必须尽可能标准化我们扩展的 media-type, 或者至少让它广泛接受 . 而对于企业内部以 REST架构的应用 , 我们同样面临标准化的问题 , 只不过范围可能小一点 , 至少是企业内部需要有共同接受的 media-type

 

前面我们看到了良好定义的 media-type是如何帮助客户应用理解 server端的 response而又不致紧密耦合服务端的实现的 . 我们需要一个企业开发的例子来验证一下我们的理解 . 比如要开发一个企业内部不同应用之间共享用户信息的应用 , 包括权限信息 , 当前可以执行的操作 , 可以访问的应用 , 以及应用之间共享的 Preference设置等 . 我们可以定义一种叫 application/vnd.tw.account+xml 的 media-type 可以有以下的片段

<account> <preference> <link rel="preference" media-type="application/vnd.tw.account.preference+xml" href="http://xxx/preference" mce_href="http://xxx/preference" /> <link rel="edit" media-type="text/html" href="http://xxx/preference/editForm" mce_href="http://xxx/preference/editForm"> </preference> <subscribed-services> <subscribed-service> <name>Taxes</name> <link rel="subscription" media-type="text/html" href="http://taxes.xxx.com" mce_href="http://taxes.xxx.com" /> </subscribed-service> <subscribed-service> <name>Audit</name> <link rel="subscription" media-type="text/html" href="http://audit.xxx.com" mce_href="http://audit.xxx.com" /> </subscribed-service> </subscribed-services> <contacts> <contact> <name>Tom</name> <link rel="contact" media-type="application/xfn+xml" href="http://account.xxx.com/tom" mce_href="http://account.xxx.com/tom" /> </contact> </contacts> </account>
这样无论是交互式客户端像浏览器还是自动化的后台应用 , 都可以 follow 这段 media 的指示进行自己感兴趣的操作

 

URL Template Considered Harmful

如果这些都实现的话 , 就可以有一个推论: URL Template不是必须的,甚至是有害的 . 它限制了服务器端的变化 . 客户应用应总是从 Root Resource开始 , 在特定 Media Type的引导下解析出其它的 URI, 给予服务程序演化的灵活性而不是按照 URL Template这种预先的知识来推算 .

用REST做过很多项目的Xu Hao 对Url template也有同样的看法:"URL template在我看来是有害的,它是一种隐含的服务器和客户端约定。此外还有一点,由于大多数URL template是用来表达state transfer的URL的,比如/xxx/approve之类的,使得客户端必须了解服务器的状态转移的细节,这在我看来是一个更大的问题。这使得客户 端和服务器的耦合变得更加紧密,同时这种风格极度鼓励服务器借由客户端来维持状态的一致性"

很多REST相关的文章都把大量的篇幅给了 HTTP, 比如 HTTP Verbs POST/GET/PUT/DELETE, HTTP Status Code等 , 而 media type着墨不多 . Xu Hao在社区中曾很多次的提起自定义Media Type, 对REST应用不多可能当时不太明白, 现在越来越多的人认识到扩展和标准化更多的 media type才能更多的发挥 REST的潜力

 

参考资料

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven 尤其后面的讨论

http://www.iana.org/assignments/link-relations/link-relations.xml

http://microformats.org/wiki/existing-rel-values

http://www.w3.org/TR/html401/types.html#type-links

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值