久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

跨越邊界: REST on Rails

 魚非魚 2007-03-27
跨越邊界 系列中以前的文章說 Ruby on Rails 是一個突然流行起來的框架,充當(dāng)著 Ruby 編程語言的催化劑,。隨著 Ruby 的經(jīng)驗不斷成功,,開發(fā)人員開始尋求把他們的 Ruby 應(yīng)用程序與用其他語言編寫的應(yīng)用程序集成,。Rails 對 Web 服務(wù)提供了優(yōu)秀的支持,。本文介紹 Rails 中的 Web 服務(wù),重點放在一個名為 Representational State Transfer (REST) 的策略上,。

過去的 20 年間,,一個趨勢主導(dǎo)了商業(yè)軟件工具的開發(fā):用復(fù)雜性對抗復(fù)雜性。這一趨勢在任何地方都沒有比在分布式計算領(lǐng)域更明顯,。C 和 Java™ 社區(qū)已經(jīng)看到一些驚人復(fù)雜的框架被構(gòu)建出來支持分布式通信,。分布式計算環(huán)境(DCE)支持用 C 語言編寫的應(yīng)用程序之間的遠程過程調(diào)用。公共對象請求代理架構(gòu)(CORBA)標(biāo)準(zhǔn)支持面向?qū)ο髴?yīng)用程序之間的通信,。企業(yè) JavaBean(EJB)規(guī)范提供安全性,、持久性、事務(wù),、消息和遠程的服務(wù),。對各個框架的宣傳甚囂塵上,但是這些框架都沒有滿足預(yù)期,有些甚至因為它們的復(fù)雜性而成為災(zāi)難,。在這些框架中,,只有 EJB 3.0 屬于大力簡化的結(jié)果,有潛力在分布式應(yīng)用程序上成功,。市場可能給,、也可能不給這個面臨強敵的框架另一個空間,但 EJB 仍然需要交付使用,。

最新的大型分布式框架是 Web 服務(wù),。Web 服務(wù)技術(shù)讓應(yīng)用程序可以用平臺獨立或編程語言獨立的方式相互通信(請參閱 參考資料)。Web 服務(wù)標(biāo)準(zhǔn)也受到復(fù)雜性惡魔的威脅,,但是稱作 REST 的替代策略承諾了更簡單的方式,。本文介紹了如何在 Ruby on Rails 中添加 REST 風(fēng)格的 Web 服務(wù),并從 Ruby 和 Java 代碼調(diào)用服務(wù),。

關(guān)于本系列

跨越邊界 系列中,,作者 Bruce Tate 推動了這樣一個概念:今天的 Java 程序員通過學(xué)習(xí)其他方法和語言,可以受益,。編程陣營中 Java 技術(shù)是所有開發(fā)項目最佳選擇的情況已經(jīng)變了,。其他框架正在改變 Java 框架構(gòu)建的方式,從其他語言學(xué)到的概念有助于 Java 編程,。編寫的 Python(或 Ruby,、Smalltalk 或 ……)代碼可以改變 Java 編碼的方式。

本系列介紹了與 Java 開發(fā)有根本不同,,但是卻直接適用的編程概念和技術(shù),。在某些情況下,需要集成這些技術(shù)以利用它,。在其他情況下,,將可以直接應(yīng)用這些概念。單獨的工具不如其他語言和框架中影響 Java 社區(qū)的開發(fā)人員,、框架甚至基本方法的思想重要,。

Web 服務(wù)領(lǐng)域

就像 EJB、CORBA 和 DCE 一樣,,Web 服務(wù)的核心抽象也是遠程過程調(diào)用,。Web 服務(wù)利用叫做 SOAP(最初,SOAP 代表簡單對象存取協(xié)議,,但是這個術(shù)語現(xiàn)在降級了)的協(xié)議,,用 XML 表示消息的結(jié)構(gòu)。這里有一個技巧:如果協(xié)議用代表簡單的 S 開始,,那它就不簡單,。Web 服務(wù)定義語言(WSDL)提供了服務(wù)的標(biāo)準(zhǔn)規(guī)范,。像 SOAP 一樣,WSDL 也是一個棘手而復(fù)雜的 API,,而 SOAP 和 WSDL 僅僅涉及到了構(gòu)成 Web 服務(wù)這個大怪物的眾多 API 的表面(請參閱 參考資料),。Web 服務(wù)需要一次大修,感謝 Roy Fielding 的一份有影響的博士論文,,Web 服務(wù)得到了大修(請參閱 參考資料),。

Fielding 的論文描述了 REST 應(yīng)用程序聯(lián)網(wǎng)策略。REST 與全堆棧 Web 服務(wù)根本不同,,主要原因有三個:

  • REST 的核心抽象是遠程資源而不是遠程過程調(diào)用,。
  • REST 沒有發(fā)明一個詳盡的標(biāo)準(zhǔn)列表,而是采用現(xiàn)有的 Internet 標(biāo)準(zhǔn),,包括 HTTP,、XML 和 TCP/IP。
  • REST 沒有覆蓋每個可能場景,,而是覆蓋了最常見的問題,。

請把 REST 想像成瀏覽。REST 客戶使用與瀏覽器相同的 HTTP 命令訪問資源,。當(dāng) REST 客戶訪問到資源的表示時,,客戶轉(zhuǎn)換到一個狀態(tài)。使用不同的 HTTP 命令,,REST 客戶可以創(chuàng)建,、讀取、更新或刪除資源的記錄,。

例如,,以典型的博客為例。通過輸入 URL,,例如 blog.rapidred.com,,得到貼子的列表。然后,,如果想編輯博客條目,,可以在 URL 中輸入 HTTP 參數(shù)(例如 blog.rapidred.com/edit?article=12345),然后顯示編輯表單,。由于每個博客條目都有自己的 URL,所以點擊鏈接或直接輸入 URL,,就可以用 HTTP 命令讀取,、修改或刪除內(nèi)容。

簡而言之,,REST 可以:

  • 用 TCP/IP 命名標(biāo)準(zhǔn)命名 Web 上的資源
  • 用 HTTP 查詢和操縱這些資源
  • 使用基于文本的標(biāo)準(zhǔn)消息格式(例如 XML 或 HTML)來構(gòu)造數(shù)據(jù)

Ruby on Rails 用 REST 對 Web 服務(wù)提供了優(yōu)秀的支持,。





回頁首


Action Web Services 概述

Rails 用叫做 Action Web Services 的模塊實現(xiàn) Web 服務(wù)。許多開發(fā)框架鼓勵視圖和 Web 服務(wù)使用獨立的控制器。這個策略可以維護控制器之間的風(fēng)格一致,。問題是針對所服務(wù)的每種內(nèi)容,,都需要一個新控制器。例如,,Ajax 用戶界面要求從控制器取得到 JavaScript 的遠程 XML 調(diào)用,。

不必為 Web 服務(wù)專門分配一個控制器,使用 Rails,,可以通用地用同一個控制器向基于 HTML 的視圖,、基于 XML 的 Web 服務(wù)和基于 XML 的 JavaScript 組件提供內(nèi)容。理解 Action Web Services 的最好方式就是在工作應(yīng)用程序的環(huán)境下查看它的實際作用,。

請用自己選擇的數(shù)據(jù)庫管理器創(chuàng)建一個叫做 service_development 的數(shù)據(jù)庫,。接下來,用以下命令創(chuàng)建 Rails 項目和模型:

> rails service
            > script/generate model Person
            

在生成模型之后,,就有了一個叫做 db/migrate/001_create_people.rb 的遷移,。請把這個遷移編輯成像清單 1 一樣:


清單 1. people 表的遷移
class CreatePeople < ActiveRecord::Migration
            def self.up
            create_table :people do |t|
            t.column :first_name, :string, :limit => 40
            t.column :last_name, :string, :limit => 40
            t.column :email, :string, :limit => 40
            t.column :phone, :string, :limit => 15
            end
            end
            def self.down
            drop_table :people
            end
            end
            

把 config/database.yml 中的數(shù)據(jù)庫配置修改成與自己的數(shù)據(jù)庫配置匹配,并輸入 rake migrate,。最后,,輸入 script/generate scaffold Person People,為 Person 模型和 People 控制器生成工作臺?,F(xiàn)在可以用 script/server 啟動服務(wù)器了,。請把瀏覽器指向 localhost:3000/people,以看到針對 Person 的經(jīng)典的 Rails 腳手架,。圖 1 顯示了帶有標(biāo)準(zhǔn) Rails 腳手架的應(yīng)用程序:


圖 1. 簡單的 Rails 應(yīng)用程序
映射框架

在我介紹 Rails 的 Web 服務(wù)之前,,請查看控制器代碼。編輯 app/controllers/people_controller.rb,,使之與清單 2 的代碼匹配:


清單 2. PeopleController 的控制器代碼
class PeopleController < ApplicationController
            def index
            list
            render :action => ‘list‘
            end
            # GETs should be safe (see
            http://www./2001/tag/doc/whenToUseGet.html)
            verify :method => :post, :only => [ :destroy, :create, :update
            ],
            :redirect_to => { :action => :list }
            def list
            @person_pages, @people = paginate :people, :per_page => 10
            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 項目,就會知道典型的控制器方法的一般流程是:

  1. 用戶通過跟隨鏈接或指定 URL,,通過 HTTP 發(fā)送請求,。
  2. Web 服務(wù)器根據(jù)域的配置把請求轉(zhuǎn)給 Ruby on Rails。
  3. Rails 路由器根據(jù) URL 模式把請求路由給控制器,。默認模式是 http://主機名/控制器/動作/參數(shù),。
  4. 路由器用與動作相同的參數(shù)調(diào)用控制器上的方法。
  5. 動作參數(shù)為視圖設(shè)置實例變量,,并呈現(xiàn)視圖,。
  6. 動作方法把實例變量拷貝到視圖。

例如,,請看 清單 2 中的 show 方法,??刂破髟O(shè)置視圖使用的 @person 實例變量。因為方法沒有指定視圖的名稱,,所以 Rails 用與控制器動作相同的名稱調(diào)用視圖 —— 在這個示例中,,視圖位于 app/views/people/show.rhtml。

再來看 list 方法,。如果想讓這個方法呈現(xiàn) XML,,需要:

  • 刪除分頁
  • people 實例變量轉(zhuǎn)換成 XML
  • 呈現(xiàn) XML 而不是 HTML

Rails 使得處理 Web 服務(wù)和呈現(xiàn)來自同一 Web 服務(wù)的視圖成為可能。實際上也不需要分頁,。為了把 Web 服務(wù)的 list 方法簡化一些,,可以把控制器中的 list 方法變成像清單 3 一樣,清除分頁,。還需要刪除靠近 app/views/people/list.rhtml 代碼底部的 “Next Page” 和 “Previous Page” 鏈接,。


清單 3. 簡化 list
def list
            @people = Person.find_all
            end
            

由于刪除了分頁,也就刪除了讓用戶界面更健壯的一個特性,,但是又得到了一些回報,。可以用相同的代碼來驅(qū)動 Web 服務(wù)和視圖,。如果日后發(fā)現(xiàn)需要分頁,,可以編寫一些定制的助手。

現(xiàn)在基本應(yīng)用程序出來了,,可以添加一些 Web 服務(wù)了,。





回頁首


向 Rails 控制器添加 Web 服務(wù)

如果我想說大話,我可以說 “現(xiàn)在已經(jīng)有了一個 Web 服務(wù)”,。記得我對 REST 說過什么,?這種風(fēng)格的 Web 服務(wù)使用指定的資源。我的 Rails 應(yīng)用程序也具有指定的資源:host_name/people/list 調(diào)用我的 list 服務(wù),。REST 風(fēng)格的 Web 服務(wù)也使用 TCP/IP 和 HTTP,。我的 Rails 應(yīng)用程序就是這么做的。而且格式良好的 HTML 就是 XML 的子集,,也滿足最后一條 REST 要求,。只需在 localhost:3000/people/list 上調(diào)用 HTTP get,并解析結(jié)果,,就可以得到人員列表,。這就是關(guān)鍵。REST 的工作方式與 Internet 的工作方式一樣,。但這并不是真正基于 REST 的 Web 服務(wù),。理想情況下,應(yīng)當(dāng)提供反映 Person 含義的 XML 文檔而不是用戶界面的結(jié)構(gòu),。

真正的服務(wù)應(yīng)當(dāng)產(chǎn)生純數(shù)據(jù)的表示,,一個專門針對服務(wù)的預(yù)期客戶而構(gòu)建的表示。但是示例應(yīng)用程序有兩個客戶:終端用戶和 REST 客戶,。要為兩個目的重用相同的代碼,,需要給 Rails 提供更多信息。Rails 的設(shè)計者可能決定使用額外的 URL 參數(shù),,但是處理 URL 可是一項費勁的工作,。Rails 不應(yīng)當(dāng)用這些細節(jié)增加用戶負擔(dān)。相反,,HTTP 提供了指定更多信息的工具:HTTP 頭,。

要理解 Web 服務(wù)的 REST 模型,了解一點 HTTP 是有幫助的,。curl(請把它想像成 查看 URL)命令允許用一個命令查詢 URL,,并查看響應(yīng)?;?Unix 的操作系統(tǒng)默認包含 curl,,可以為其他操作系統(tǒng)下載免費的 curl 工具。通過輸入 curl http://some-url,,可以將請求限制成只輸出默認的響應(yīng)體(瀏覽器呈現(xiàn)的 HTML),。輸入 curl -i http://some-url 可以得到更多信息。這個命令返回 HTTP 頭,,如清單 4 所示,。可以看到頭配置由表示每個請求的配置的鍵-值對組成,。


清單 4. 用 curl 調(diào)用 HTTP 請求
> curl -i http://localhost:3000/people/list
            HTTP/1.1 200 OK
            Cache-Control: no-cache
            Connection: Keep-Alive
            Date: Tue, 27 Jun 2006 14:54:49 GMT
            Content-Type: text/html; charset=UTF-8
            Server: WEBrick/1.3.1 (Ruby/1.8.4/2005-12-24)
            Content-Length: 854
            Set-Cookie: _session_id=216912045de52786f032b22755c903dd; path=/
            

后面將頻繁地看到 HTTP get,、putpostdelete 命令,。REST 利用達些命令執(zhí)行經(jīng)典的 CRUD(CRUD 是create, read,、update 和 delete 的共同縮寫)。HTTP 命令到 CRUD 的映射是這樣的:

  • Create(創(chuàng)建):HTTP put
  • Read(讀?。篐TTP get
  • Update(更新):HTTP post
  • Delete(刪除):HTTP delete

瀏覽器利用 HTTP 頭,,通過相同的服務(wù)器端代碼來滿足不同類型的請求。行為良好的應(yīng)用程序提供正確處理文檔的充足信息,。其中一條信息叫做 HTTP Accept 頭,。只要多花一點力氣,控制器就能利用一些助手,,用 Accept 頭決定如何響應(yīng)進入的請求,。然后,控制器可以呈現(xiàn)適當(dāng)?shù)捻憫?yīng),。請把 PeopleController 中的 list 方法改成像清單 5 一樣:


清單 5. 擴展 list方法以呈現(xiàn) XML
def list
            # wants is determined by the http Accept header in the request
            @people = Person.find_all
            respond_to do |wants|
            wants.html
            wants.xml { render :xml => @people.to_xml }
            end
            end
            

在清單 5 中,,可以看到完整的基于 REST 的 Web 服務(wù),。生成的代碼是 Rails 中小型的特定于域的語句的優(yōu)美示例,它擴展 Ruby 以構(gòu)造一種 switch 語句,。它的工作方式是這樣的:

  1. respond_to 方法接受單個代碼塊,,并傳遞一個實例變量(標(biāo)為 wants)到代碼塊。
  2. wants 對每個可能的類型都有一個方法,??刂破骺梢詾榭刂破髌谕拿總€類型指定一個代碼塊。
  3. 如果方法名稱與 HTTP Accept 頭中的類型匹配,,wants 方法執(zhí)行對應(yīng)的代碼塊,。
  4. 如果沒有指定代碼塊(例如 wants.html),Rails 就執(zhí)行默認動作(在這個示例中,,呈現(xiàn) app/views/people/list.rhtml),。

這個策略允許在所有預(yù)期的客戶之間共享相同的設(shè)置代碼。如果需要添加期望 HTML 的 JavaScript 客戶,,以便讓應(yīng)用程序支持 Ajax,,只需要添加 wants.js,如清單 6 所示:


清單 6. 為 JavaScript 客戶呈現(xiàn) HTML
            def list
            # wants is determined by the http Accept header in the request
            @people = Person.find_all
            respond_to do |wants|
            wants.html
            wants.js
            wants.xml { render :xml => @people.to_xml }
            end
            end
            

現(xiàn)在已經(jīng)看到了如何向只讀的方法中添加 REST Web 服務(wù),。show 方法也類似,,如清單 7 所示:


清單 7. 實現(xiàn) show
def show
            @person = Person.find(params[:id])
            respond_to do |wants|
            wants.html
            wants.xml { render :xml => @person.to_xml }
            end
            end
            

您可能已經(jīng)注意到,通過 REST 看到的只有只讀服務(wù),。原因是:讓應(yīng)用程序處理提交和刪除所需要的工作比較少,。刪除不需要額外的支持,因為當(dāng)前的代碼已經(jīng)用 URL 指定了要刪除的人的 ID,。Rails 自動轉(zhuǎn)換 post 請求中進入的 XML,,所以不需要構(gòu)建任何服務(wù)器端支持。實際上,,應(yīng)用程序不用變就能刪除,、更新和創(chuàng)建??梢孕扪a每個方法呈現(xiàn)的 HTTP 響應(yīng),,但是客戶代碼實際就在 HTTP 返回碼之后。

現(xiàn)在是調(diào)用 Web 服務(wù)的時候了,。





回頁首


調(diào)用 Web 服務(wù)

使用現(xiàn)有 HTTP 協(xié)議這一策略使得調(diào)用變得簡單,。清單 8 顯示了 Ruby 版本。請注意 HTTP Accept 頭,。記住,,控制器根據(jù)這個頭決定內(nèi)容的類型。


清單 8. 從 Ruby 調(diào)用服務(wù)
require ‘net/http‘
            Net::HTTP.start(‘localhost‘, 3000) do |http|
            response = http.get(‘/people/list‘, ‘Accept‘ => ‘text/xml‘)
            #Do something with the response.
            puts "Code: #{response.code}"
            puts "Message: #{response.message}"
            puts "Body:\n #{response.body}"
            end
            

清單 8 中的 Web 服務(wù)調(diào)用,在 http://localhost:3000/people/list 上調(diào)用 HTTP get 方法,,并輸出響應(yīng),。Ruby 有很好的庫可以處理生成的 XML,但是它們超出了本文的范圍,。不需要用 Ruby 調(diào)用這個服務(wù),。只需要 HTTP 的庫,。清單 9 顯示這個服務(wù)的 Java 調(diào)用:


清單 9. 用 Java 代碼調(diào)用服務(wù)
            package com.rapidred.ws;
            import java.net.*;
            import java.io.*;
            public class SimpleGet {
            void get() {
            try {
            URL url = new URL("http://localhost:3000/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 頭設(shè)置成 text/xml,,發(fā)出 get,,并輸出結(jié)果。Java 代碼有許多 XML 框架(請參閱 參考資料),,但是我在這個示例中硬編碼了 XML,,以保持示例簡單。

post 的調(diào)用也相似,。清單 10 顯示了簡單的 post


清單 10. 用 Java 代碼調(diào)用 HTTP post
void post() {
            try {
            String xmlText  = "<person> " +
            "<first-name>Maggie</first-name>" +
            "<last-name>Maggie</last-name>" +
            "<email>[email protected]</email>" +
            "</person>";
            URL url = new URL("http://localhost:3000/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 通過在 http://localhost:3000/people/create 上調(diào)用 post,,并在 HTTP 文檔體中傳遞一個 XML 文檔,創(chuàng)建了一個新 Person,。(通常應(yīng)當(dāng)用 Java XML 庫構(gòu)建 XML 文檔,。這次我還是硬編碼了 XML 文檔,以保持示例簡單,。)Rails 支持自動把進入的 XML 轉(zhuǎn)換成 Person 屬性的 Ruby 散列表,。





回頁首


結(jié)束語

在本文中,已經(jīng)看到只用少量代碼,,就使控制器支持基于 REST 的 Web 服務(wù),。動態(tài)類型化的 Internet 語句,例如 Ruby,,大量地利用 REST 代替基于 SOAP 的 Web 服務(wù),。一些簡單的調(diào)用,包括漂亮的 responds_to 語法和對進入提交的自動 XML 轉(zhuǎn)換,,使得可以容易地利用同一控制器處理 Web 服務(wù),、遠程 JavaScript 請求或 HTML。

Java 語言對 REST 也有非常好的支持,。畢竟,,servlet 實際上是服務(wù)器端基于 REST 的 Web 服務(wù)??梢栽?Java 端使用 servlet,,在 Ruby 端使用 Rails 控制器,把利用兩個平臺優(yōu)勢的應(yīng)用程序組合在一起。這就是 Web 服務(wù)的漂亮之處,。您真正需要的所有東西就是超群出眾的勇氣,。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多