第219期 / January 5, 2016

分享到臉書!分享到維特!分享到噗浪!分享到Google+!分享到微博!轉寄友人友善列印

淺談Rest設計架構風格

作者/梁孝平

[發表日期:2016/1/5]

前言

REST,全名為Representational State Transfer,中文大致上可稱做為” 表徵性狀態傳輸”,是Dr. Roy Fielding在2000年所提出的一篇博士論文中所討論的軟體架構風格(Architectural Styles andthe Design of Network-based Software Architectures[1]),將此風格應用在Web Service上會比起複雜的SOAP和XML-RPC更加的簡單易懂,因此也有許多的Web Service開始採用REST風格來設計以及實作,例如Yahoo的Social REST APIs[2]。

REST簡介

就像前言所說,REST是一種設計風格,然而在這種風格下所設計出來的系統可稱之為RESTful,表示系統在設計上遵循著REST的原則與理念。而這樣的設計風格在眾人的驗證下,發現到REST 非常符合現今的網路架構與行為模式,尤其在需要高速運算能力的雲端運算服務(Cloud Computing)與分散式系統中更能夠展現 REST 其合適的一面[3]。不過也是有人提出質疑,認為像是REST這種簡易的設計模式,對於較為複雜的大型系統來說則稍嫌不足,至於使用上是否合適,還是必須評估當下的環境以及系統狀態來衡量其實用性才是較為妥當的做法。

而說到REST的設計架構,簡單來說可大致上分為:

一、REST Constraints:包含Client-Server、Stateless、Cacheable等等。

二、REST Architectural Elements :

  • REST Data Elements:包含Resource、Resource identifier等等。

  • REST Connectors:包含Client、Server等等。

  • REST Components:包含User Agent、Origin Server等等。


  • 由於其架構設計內容過於冗長及繁複,所以就不再此一一列出解釋,若想詳細了解,請參閱Dr. Roy Fielding的博士論文[1],裡面有非常完整詳盡的解釋。

    RESTful Web Service的設計

    如果以實作車輛管理Web Service來作解釋,若要達成CRUD(Create, Read, Update and Delete)的基本需求,並且使用POST XML以及回傳XML的格式定義,其設計規格如下:Web Service 網址連結

    根據上述網址來解釋RESTful Web Service的設計概念,大致上可分為三種:

    一、名詞(Nouns):為 Resources (資源) 定義唯一的識別,在 HTTP 中我們借用 URI 為資源進行識別定義,範例:http://car.com/cars/{carName}

    二、動詞(Verbs):在 HTTP 中使用 GET, POST, PUT, DELETE 來操作資源。

    三、格式(Content types):就是REST 所謂的 Representation,也是 Header 所送出的 Content-type,其使用 MIME Types 進行定義。

    套用上述設計,簡單的以表格呈現如下:



    上述的設計是參考POST, GET, PUT, DELETE 來對應資料的 CRUD 操作,其中 Web Service 的處理狀態也直接使用 HTTP Status Code,這樣的設計就可以讓整體的Web Service理解起來更直覺,實作起來更簡單。

    RESTful Web Service & Java

    在Java的部分,如果要設計RESTful Web Service,可以使用Jersey來實作,其支援Servlet 2.5以上
    的版本,可以使用Maven來建立,也可建立在JavaEE等其他環境上,至於初期建立細節,就請參閱Jersey的官網使用手冊[5],接下來會介紹Java API for RESTful Web Services(JAX-RS)的應用。

    在Root Resource Classes的部分可以透過JAX-RS的annotation的描述像是@ Path、@GET、@PUT、@POST、@DELETE等等,對應到Java的class或method或parameter,也就是以POJO(Plain Old Java Objects)的形式存在,以下為簡單介紹:

  • @ Path:@PATH是一個URI的相對路徑,URI的路徑可以由URIs和放入URI的參數所組成,例如:@Path ("/users/{username}"),按照這個例子,若有用戶輸入名字” Galileo”,Jersey就會依照這個URI路徑” http://example.com/users/Galileo”來作發送。


  • @GET, @PUT, @POST, @DELETE, @HEAD :這些都是JAX-RS 所定義的annotation,其非常類似HTTP的方法,如果使用@GET annotation,java就會當作HTTP GET requests 來作處理。


  • @Produces:是用來定義回應給Client的MIME 媒體類型,像是"application/xml"或"application/json" 等等,其可以同時定義多個MIME媒體類型。


  • @Consumes :是用來定義可接受請求的MIME媒體類型。


  • 綜合以上部分,以下圖一是一個簡單例子:


    《圖一》


    可以看到這邊是以HTTP GET 來作接收,接收的MIME媒體型態是text/plain,回應的MIME媒體型態可以為application/xml或application/json,其中application/xml為主要的回應型態,因為application/json被設定的權重較低。

    而在收到對應的@Path的服務請求之後,可以透過Parameter Annotations來取得URL請求中的參數,例如:


    《圖二》


    從圖二可以看到這邊是藉由@QueryParam來取得URL路徑中的參數,並且對於每個參數都會藉由@DefaultValue來給予預設值。


    《圖三》


    至於另一個例子如圖三所示,這是一個POST的例子,並且是以application/x-www-form-urlencoded的形式藉由@FormParam來接收HTML表單中名稱為”name”的資訊。而至於其他像是@HeaderParam是從HTTP的HEADER取得資訊,@CookieParam是從cookies裡取的資訊等等許多方式,若想了解其他使用方式,請進一步參考官方使用手冊[5]。

    結語

    善用REST的設計風格可以利用快取達到更有效率的回應速度,並且因為在伺服器互相溝通的過程中是無狀態性的,因此可以讓不同的伺服器的處理一系列請求中的不同請求,提高伺服器的擴展性,而且只需要瀏覽器就可以作為客戶端,不須使用其他軟體,進一步降低軟體需求。

    參考資料

    [1] https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
    [2] https://developer.yahoo.com/social/rest_api_guide/web-services-intro.html
    [3] http://blog.toright.com/posts/1399/%E6%B7%BA%E8%AB%87-rest-%E8%BB%9F%E9%AB%94%E6%9E%B6%E6%A7%8B%E9%A2%A8%E6%A0%BC-part-ii-%E5%A6%82%E4%BD%95%E8%A8%AD%E8%A8%88-restful-web-service.html
    [4] http://www.codedata.com.tw/java/java-restful-1-jersey-and-jax-rs
    [5] https://jersey.java.net/documentation/latest/getting-started.html