知识大全 跨越边界: REST on Rails

Posted 控制器

篇首语:世上无难事,只要肯登攀本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 跨越边界: REST on Rails相关的知识,希望对你有一定的参考价值。

跨越边界: REST on Rails  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  过去的 年间 一个趋势主导了商业软件工具的开发 用复杂性对抗复杂性 这一趋势在任何地方都没有比在分布式计算领域更明显 C 和 Java&# ; 社区已经看到一些惊人复杂的框架被构建出来支持分布式通信 分布式计算环境(DCE)支持用 C 语言编写的应用程序之间的远程过程调用 公共对象请求代理架构(CORBA)标准支持面向对象应用程序之间的通信 企业 JavaBean(EJB)规范提供安全性 持久性 事务 消息和远程的服务 对各个框架的宣传甚嚣尘上 但是这些框架都没有满足预期 有些甚至因为它们的复杂性而成为灾难 在这些框架中 只有 EJB 属于大力简化的结果 有潜力在分布式应用程序上成功 市场可能给 也可能不给这个面临强敌的框架另一个空间 但 EJB 仍然需要交付使用

  最新的大型分布式框架是 Web 服务 Web 服务技术让应用程序可以用平台独立或编程语言独立的方式相互通信 Web 服务标准也受到复杂性恶魔的威胁 但是称作 REST 的替代策略承诺了更简单的方式 本文介绍了如何在 Ruby on Rails 中添加 REST 风格的 Web 服务 并从 Ruby 和 Java 代码调用服务

关于本系列

  在 跨越边界 系列中 作者 Bruce Tate 推动了这样一个概念 今天的 Java 程序员通过学习其他方法和语言 可以受益 编程阵营中 Java 技术是所有开发项目最佳选择的情况已经变了 其他框架正在改变 Java 框架构建的方式 从其他语言学到的概念有助于 Java 编程 编写的 Python(或 Ruby Smalltalk 或 ……)代码可以改变 Java 编码的方式

  本系列介绍了与 Java 开发有根本不同 但是却直接适用的编程概念和技术 在某些情况下 需要集成这些技术以利用它 在其他情况下 将可以直接应用这些概念 单独的工具不如其他语言和框架中影响 Java 社区的开发人员 框架甚至基本方法的思想重要

  Web 服务领域

  就像 EJB CORBA 和 DCE 一样 Web 服务的核心抽象也是远程过程调用 Web 服务利用叫做 SOAP(最初 SOAP 代表简单对象存取协议 但是这个术语现在降级了)的协议 用 XML 表示消息的结构 这里有一个技巧 如果协议用代表简单的 S 开始 那它就不简单 Web 服务定义语言(WSDL)提供了服务的标准规范 像 SOAP 一样 WSDL 也是一个棘手而复杂的 API 而 SOAP 和 WSDL 仅仅涉及到了构成 Web 服务这个大怪物的众多 API 的表面 Web 服务需要一次大修 感谢 Roy Fielding 的一份有影响的博士论文 Web 服务得到了大修

  Fielding 的论文描述了 REST 应用程序联网策略 REST 与全堆栈 Web 服务根本不同 主要原因有三个

REST 的核心抽象是远程资源而不是远程过程调用 REST 没有发明一个详尽的标准列表 而是采用现有的 Internet 标准 包括 HTTP XML 和 TCP/IP REST 没有覆蓋每个可能场景 而是覆蓋了最常见的问题

  请把 REST 想像成浏览 REST 客户使用与浏览器相同的 HTTP 命令访问资源 当 REST 客户访问到资源的表示时 客户转换到一个状态 使用不同的 HTTP 命令 REST 客户可以创建 读取 更新或删除资源的记录

  例如 以典型的博客为例 通过输入 URL 例如 得到贴子的列表 然后 如果想编辑博客条目 可以在 URL 中输入 HTTP 参数(例如 /edit?article= ) 然后显示编辑表单 由于每个博客条目都有自己的 URL 所以点击链接或直接输入 URL 就可以用 HTTP 命令读取 修改或删除内容

  简而言之 REST 可以

用 TCP/IP 命名标准命名 Web 上的资源 用 HTTP 查询和操纵这些资源 使用基于文本的标准消息格式(例如 XML 或 HTML)来构造数据

  Ruby on Rails 用 REST 对 Web 服务提供了优秀的支持

  Action Web Services 概述

  Rails 用叫做 Action Web Services 的模块实现 Web 服务 许多开发框架鼓励视图和 Web 服务使用独立的控制器 这个策略可以维护控制器之间的风格一致 问题是针对所服务的每种内容 都需要一个新控制器 例如 Ajax 用户界面要求从控制器取得到 JavaScript 的远程 XML 调用

  不必为 Web 服务专门分配一个控制器 使用 Rails 可以通用地用同一个控制器向基于 HTML 的视图 基于 XML 的 Web 服务和基于 XML 的 JavaScript 组件提供内容 理解 Action Web Services 的最好方式就是在工作应用程序的环境下查看它的实际作用

  请用自己选择的数据库管理器创建一个叫做 service_development 的数据库 接下来 用以下命令创建 Rails 项目和模型

  

  > rails service > script/generate model Person

  在生成模型之后 就有了一个叫做 db/migrate/ _create_people rb 的迁移 请把这个迁移编辑成像清单 一样

  清单 people 表的迁移

  class CreatePeople < ActiveRecord::Migration def self up create_table :people do |t| lumn :first_name :string :limit => lumn :last_name :string :limit => lumn :email :string :limit => lumn :phone :string :limit => end end def self down drop_table :people end end

  把 config/database yml 中的数据库配置修改成与自己的数据库配置匹配 并输入 rake migrate 最后 输入 script/generate scaffold Person PeoplePerson 模型和 People 控制器生成工作台 现在可以用 script/server 启动服务器了 请把浏览器指向 localhost: /people 以看到针对 Person 的经典的 Rails 脚手架 图 显示了带有标准 Rails 脚手架的应用程序

  图 简单的 Rails 应用程序

  在我介绍 Rails 的 Web 服务之前 请查看控制器代码 编辑 app/controllers/people_controller rb 使之与清单 的代码匹配

  清单 PeopleController 的控制器代码

  class PeopleController < ApplicationController def index list render :action => list end # GETs should be safe (see ) verify :method => :post :only => [ :destroy :create :update ] :redirect_to => :action => :list def list @person_pages @people = paginate :people :per_page => end def show @person = Person find(params[:id]) end def new @person = Person new end def create @person = Person new(params[:person]) if @person save flash[:notice] = Person was successfully created redirect_to :action => list else render :action => new end end def edit @person = Person find(params[:id]) end def update @person = Person find(params[:id]) if @person update_attributes(params[:person]) flash[:notice] = Person was successfully updated redirect_to :action => show :id => @person else render :action => edit end end def destroy Person find(params[:id]) destroy redirect_to :action => list end end

  如果跟着做过这个系列以前的 Ruby on Rails 项目 就会知道典型的控制器方法的一般流程是

    用户通过跟随链接或指定 URL 通过 HTTP 发送请求 Web 服务器根据域的配置把请求转给 Ruby on Rails Rails 路由器根据 URL 模式把请求路由给控制器 默认模式是// 主机名/ 控制器/ 动作/ 参数 路由器用与动作相同的参数调用控制器上的方法 动作参数为视图设置实例变量 并呈现视图 动作方法把实例变量拷贝到视图

  例如 请看 清单 中的 show 方法 控制器设置视图使用的 @person 实例变量 因为方法没有指定视图的名称 所以 Rails 用与控制器动作相同的名称调用视图 —— 在这个示例中 视图位于 app/views/people/show r

  再来看 list 方法 如果想让这个方法呈现 XML 需要

删除分页 把 people 实例变量转换成 XML 呈现 XML 而不是 HTML

  Rails 使得处理 Web 服务和呈现来自同一 Web 服务的视图成为可能 实际上也不需要分页 为了把 Web 服务的 list 方法简化一些 可以把控制器中的 list 方法变成像清单 一样 清除分页 还需要删除靠近 app/views/people/list r 代码底部的 Next Page 和 Previous Page 链接

  清单 简化 list

  def list @people = Person find_all end

  由于删除了分页 也就删除了让用户界面更健壮的一个特性 但是又得到了一些回报 可以用相同的代码来驱动 Web 服务和视图 如果日后发现需要分页 可以编写一些定制的助手

  现在基本应用程序出来了 可以添加一些 Web 服务了

  向 Rails 控制器添加 Web 服务

  如果我想说大话 我可以说 现在已经有了一个 Web 服务 记得我对 REST 说过什么?这种风格的 Web 服务使用指定的资源 我的 Rails 应用程序也具有指定的资源 host_name/people/list 调用我的 list 服务 REST 风格的 Web 服务也使用 TCP/IP 和 HTTP 我的 Rails 应用程序就是这么做的 而且格式良好的 HTML 就是 XML 的子集 也满足最后一条 REST 要求 只需在 localhost: /people/list 上调用 HTTP get 并解析结果 就可以得到人员列表 这就是关键 REST 的工作方式与 Internet 的工作方式一样 但这并不是真正基于 REST 的 Web 服务 理想情况下 应当提供反映 Person 含义的 XML 文档而不是用户界面的结构

  真正的服务应当产生纯数据的表示 一个专门针对服务的预期客户而构建的表示 但是示例应用程序有两个客户 终端用户和 REST 客户 要为两个目的重用相同的代码 需要给 Rails 提供更多信息 Rails 的设计者可能决定使用额外的 URL 参数 但是处理 URL 可是一项费劲的工作 Rails 不应当用这些细节增加用户负担 相反 HTTP 提供了指定更多信息的工具 HTTP 头

  要理解 Web 服务的 REST 模型 了解一点 HTTP 是有帮助的 curl(请把它想像成 查看 URL)命令允许用一个命令查询 URL 并查看响应 基于 Unix 的操作系统默认包含 curl 可以为其他操作系统下载免费的 curl 工具 通过输入 //some url 可以将请求限制成只输出默认的响应体(浏览器呈现的 HTML) 输入 curl //some url 可以得到更多信息 这个命令返回 HTTP 头 如清单 所示 可以看到头配置由表示每个请求的配置的键 值对组成

  清单 用 curl 调用 HTTP 请求

  > curl i Alive Date: Tue Jun : : GMT Content Type: text/; charset=UTF Server: WEBrick/ (Ruby/ / ) Content Length: Set Cookie: _session_id= de f b c dd; path=/

  后面将频繁地看到 HTTP getputpostdelete 命令 REST 利用达些命令执行经典的 CRUD(CRUD 是create read update 和 delete 的共同缩写) HTTP 命令到 CRUD 的映射是这样的

Create(创建) HTTP put Read(读取) HTTP get Update(更新) HTTP post Delete(删除) HTTP delete

  浏览器利用 HTTP 头 通过相同的服务器端代码来满足不同类型的请求 行为良好的应用程序提供正确处理文档的充足信息 其中一条信息叫做 HTTP Accept 头 只要多花一点力气 控制器就能利用一些助手 用 Accept 头决定如何响应进入的请求 然后 控制器可以呈现适当的响应 请把 PeopleController 中的 list 方法改成像清单 一样

  清单 扩展 list方法以呈现 XML

  def list # wants is determined by the Accept header in the request @people = Person find_all respond_to do |wants| l wants xml render :xml => @people to_xml end end

  在清单 中 可以看到完整的基于 REST 的 Web 服务 生成的代码是 Rails 中小型的特定于域的语句的优美示例 它扩展 Ruby 以构造一种 switch 语句 它的工作方式是这样的

    respond_to 方法接受单个代码块 并传递一个实例变量(标为 wants)到代码块 wants 对每个可能的类型都有一个方法 控制器可以为控制器期望的每个类型指定一个代码块 如果方法名称与 HTTP Accept 头中的类型匹配 wants 方法执行对应的代码块 如果没有指定代码块(例如 l) Rails 就执行默认动作(在这个示例中 呈现 app/views/people/list r)

  这个策略允许在所有预期的客户之间共享相同的设置代码 如果需要添加期望 HTML 的 JavaScript 客户 以便让应用程序支持 Ajax 只需要添加 wants js 如清单 所示

  清单 为 JavaScript 客户呈现 HTML

  def list # wants is determined by the Accept header in the request @people = Person find_all respond_to do |wants| l wants js wants xml render :xml => @people to_xml end end

  现在已经看到了如何向只读的方法中添加 REST Web 服务 show 方法也类似 如清单 所示

  清单 实现 show

  def show @person = Person find(params[:id]) respond_to do |wants| l wants xml render :xml => @person to_xml end end

  您可能已经注意到 通过 REST 看到的只有只读服务 原因是 让应用程序处理提交和删除所需要的工作比较少 删除不需要额外的支持 因为当前的代码已经用 URL 指定了要删除的人的 ID Rails 自动转换 post 请求中进入的 XML 所以不需要构建任何服务器端支持 实际上 应用程序不用变就能删除 更新和创建 可以修补每个方法呈现的 HTTP 响应 但是客户代码实际就在 HTTP 返回码之后

  现在是调用 Web 服务的时候了

  调用 Web 服务

  使用现有 HTTP 协议这一策略使得调用变得简单 清单 显示了 Ruby 版本 请注意 HTTP Accept 头 记住 控制器根据这个头决定内容的类型

  清单 从 Ruby 调用服务

  require net/ Net::HTTP start( localhost ) do || response = get( /people/list Accept => text/xml ) #Do something with the response puts Code: #de puts Message: #ssage puts Body:\\n #response body end

  清单 中的 Web 服务调用 在//localhost: /people/list 上调用 HTTP get 方法 并输出响应 Ruby 有很好的库可以处理生成的 XML 但是它们超出了本文的范围 不需要用 Ruby 调用这个服务 只需要 HTTP 的库 清单 显示这个服务的 Java 调用

  清单 用 Java 代码调用服务

  package rapidred ws; import *; import java io *; public class SimpleGet void get() try URL url = new URL(//localhost: /people/list ); URLConnection urlConnection = url openConnection(); urlConnection setRequestProperty( accept text/xml ); BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection getInputStream())); String str; while ((str = in readLine()) != null) System out println(str); in close(); catch (Exception e) System out println(e);

  像其 Ruby 等价物一样 这个代码打开一个 URL 连接 把 Accept 头设置成 text/xml 发出 get 并输出结果 Java 代码有许多 XML 框架 但是我在这个示例中硬编码了 XML 以保持示例简单

  post 的调用也相似 清单 显示了简单的 post

  清单 用 Java 代码调用 HTTP post

  void post() try String xmlText = <person> + <first name>Maggie</first name> + <last name>Maggie</last name> + <email></email> + </person> ; URL url = new URL(//localhost: /people/create ); HttpURLConnection conn = (HttpURLConnection)url openConnection(); conn setDoOutput(true); conn setRequestMethod( POST ); conn setRequestProperty( Content Type text/xml ); OutputStreamWriter wr = new OutputStreamWriter(conn getOutputStream()); wr write(xmlText); wr flush(); BufferedReader rd = new BufferedReader(new InputStreamReader(conn getInputStream())); String line; while ((line = rd readLine()) != null) System out println(line); wr close(); rd close(); catch (Exception e) System out println( Error + e);

  这个 HTTP post 通过在//localhost: /people/create 上调用 post 并在 HTTP 文档体中传递一个 XML 文档 创建了一个新 Person (通常应当用 Java XML 库构建 XML 文档 这次我还是硬编码了 XML 文档 以保持示例简单 )Rails 支持自动把进入的 XML 转换成 Person 属性的 Ruby 散列表

  结束语

  在本文中 已经看到只用少量代码 就使控制器支持基于 REST 的 Web 服务 动态类型化的 Internet 语句 例如 Ruby 大量地利用 REST 代替基于 SOAP 的 Web 服务 一些简单的调用 包括漂亮的 responds_to 语法和对进入提交的自动 XML 转换 使得可以容易地利用同一控制器处理 Web 服务 远程 JavaScript 请求或 HTML

cha138/Article/program/Java/hx/201311/26105

相关参考

知识大全 由Ruby on Rails想到的

反思Spring:由RubyonRails想到的  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!众所

知识大全 由Ruby on Rails想到的[2]

反思Spring:由RubyonRails想到的[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧

知识大全 由Ruby on Rails想到的[1]

反思Spring:由RubyonRails想到的[1]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧

知识大全 Java 与Ruby on Rails对接

Java与RubyonRails对接  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!Ruby和rai

知识大全 REST及RESTful的实现

REST及RESTful的实现  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  什么是REST? 

知识大全 RIA+REST如何来化解Java的劣势

RIA+REST如何来化解Java的劣势  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!Java的劣

知识大全 Rails 开发与 Java 编程的比较

Rails开发与Java编程的比较  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  年月日&nbs

知识大全 新Eclipse插件—为Java 、PHP和Rails的应用添加云托管功能

新Eclipse插件—为Java、PHP和Rails的应用添加云托管功能  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们

知识大全 求一首歌 里面有很多来来来come on,come on,come on 的,是一个女的唱的,蛮劲爆的,好像是欧美的。

求一首歌里面有很多来来来eon,eon,eon的,是一个女的唱的,蛮劲爆的,好像是欧美的。CheapThrills(RACRemix)-SiaComeoneonturntheradioonIt\'sF

知识大全 026 braindumps on 1/22 test!

  HithisismybraindumponJantest  Mostquestionsarefromhere  Ijustmentionsome!    WhatdoestheCONNECTION