分布式計算領域長期陷入「用複雜度對抗複雜度」的怪圈:DCE、CORBA、EJB、SOAP/WSDL 堆疊出驚人的規範與實現複雜度,卻鮮有兌現承諾。Roy Fielding 博士論文提出的 REST(Representational State Transfer) 架構風格,以「資源導向」取代「過程調用」,以 HTTP 現有標準替代重型協議棧,為 Web 服務帶來了久違的簡潔。Rails 對 REST 的原生支持,更將這一理念貫徹到代碼每一行。
簡言之:REST 就是把 Web 的工作方式套用到機器間交互——博客文章有唯一 URL,GET 讀取,POST 創建,PUT 更新,DELETE 刪除,瀏覽器與服務端同一套邏輯。
傳統框架常要求 Web 服務與 HTML 視圖使用獨立控制器,Rails 則允許同一控制器同時服務 HTML、XML、JSON、JavaScript 多種客戶端。關鍵在於 respond_to 塊與 HTTP Accept 頭協商:
def list
@people = Person.all
respond_to do |wants|
wants.html # 默認渲染 app/views/people/list.html.erb
wants.xml { render xml: @people.to_xml }
wants.json { render json: @people.to_json }
end
end
同一 list 動作,瀏覽器獲取 HTML,AJAX 客戶端獲取 JSON,第三方系統獲取 XML,零代碼重複。wants.html 無塊時自動渲染同名視圖,wants.xml { ... } 則執行自定義渲染邏輯。
rails service
script/generate model Person
# 編輯 db/migrate/xxx_create_people.rb 添加欄位
rake db:migrate
script/generate scaffold Person People
def list
@people = Person.all # 移除 paginate,便於服務端一次性返回全量數據
end
def list
@people = Person.all
respond_to do |wants|
wants.html
wants.xml { render xml: @people.to_xml }
end
end
def show
@person = Person.find(params[:id])
respond_to do |wants|
wants.html
wants.xml { render xml: @person.to_xml }
end
end
創建、更新、刪除動作無需修改:Rails 自動將提交的 XML/JSON 解析為參數哈希,params[:person] 直接可用於 Person.create/update_attributes。
REST 服務無需專用 SDK,任何語言的 HTTP 庫皆可調用。關鍵在於設置 Accept 頭:
require 'net/http'
Net::HTTP.start('localhost', 3000) do |http|
resp = http.get('/people/list', 'Accept' => 'application/xml')
puts resp.body
end
URL url = new URL("https://localhost:3000/people/list");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Accept", "application/xml");
try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
String line;
while ((line = in.readLine()) != null) System.out.println(line);
}
POST 創建同理:設置 Content-Type: application/xml,請求體發送 XML 文檔,Rails 自動反序列化。
| 維度 | SOAP/WSDL | REST |
|---|---|---|
| 核心抽象 | 遠程過程調用 (RPC) | 資源 |
| 協議棧 | SOAP + WSDL + WS-* 複雜棧 | HTTP + URI + XML/JSON |
| 耦合度 | 強契約,客戶端依賴 Stub | 鬆耦合,僅依賴資源協議 |
| 緩存/代理 | 困難(POST 通道) | 天然支持(GET/HEAD/ETag) |
| 防火牆穿透 | 需開放特定端口/協議 | 走標準 80/443 端口 |
Servlet 本質上就是服務端 REST 基礎設施。JAX-RS (JSR 311/339/370) 及其參考實現 Jersey、RESTEasy、CXF,已為 Java 提供成熟的 REST 框架。Spring MVC 4+ 亦全面支持 @RestController、@RequestMapping、消息轉換器等註解驅動開發。雙平台可通過 REST 無縫互操作:Java Servlet 提供高性能服務端,Rails 控制器快速構建業務原型,各取所長。
REST 不是新技術,而是對 Web 既有架構原理的歸納與昇華。Rails 以 respond_to、自動 XML/JSON 序列化、約定路由等極少代碼,將 REST 理念貫徹始終。對於追求輕量、可演進、跨語言互操作的系統,REST 是比 SOAP 更理性的選擇。正如 Fielding 所言:「REST 的約束造就了 Web 的規模與壽命」,而 Rails 讓這些約束在代碼層面變得觸手可及。