RESTful的理解

REST(Representational State Transfer ),有中文翻譯爲"具象狀態傳輸"(也有:"代表性狀態傳輸")。是由 Roy Thomas Fielding博士 在2000年就讀加州大學歐文分校期間在學術論文中提出的一個術語。他首次系統全面地闡述了REST的架構風格和設計思想。這篇論文是Web發展史上一篇非常重要的技術文獻,他也爲WEB架構的設計與評判奠定了理論基礎。
 
 
REST 定義了一組體系架構原則,您可以根據這些,包括使用不同語言編寫的客戶端如何通過 HTTP 處理和傳輸資源狀態。所以在事實上,REST 對 Web的影響非常大,由於其使用相當方便,已經普遍地取代了基於 SOAP 和 WSDL 的接口設計。在多年以後的今天,REST的主要框架已經開始雨後春筍般的出現。
 
 個人理解:
(一)  首先REST只是一種風格,不是一種標準
(二)  REST是以資源爲中心的
(三)  REST充分利用或者說極端依賴HTTP協議
 
一.對於今天正在吸引如此多注意力的最純粹形式的 REST Web 服務,其具體實現應該遵循以下基本設計原則:
 
1.1.顯式地使用不同的 HTTP 請求方法
1.2.無狀態
1.3.公開目錄結構式的 URI(通過邏輯URI定位資源)。
 
1.1.顯式地使用不同的 HTTP 請求方法
 
    我們在 Web 應用中處理來自客戶端的請求時,通常只考慮 GET 和 POST 這兩種 HTTP 請求方法。實際上,HTTP 還有 HEAD、PUT、DELETE 等請求方法。而在 REST 架構中,用不同的 HTTP 請求方法來處理對資源的 CRUD(創建、讀取、更新和刪除)操作:
 
    若要在服務器上創建資源,應該使用 POST 方法。 
    若要檢索某個資源,應該使用 GET 方法。 
    若要更改資源狀態或對其進行更新,應該使用 PUT 方法。 
    若要刪除某個資源,應該使用 DELETE 方法。
 
經過這樣的一番擴展,我們對一個資源的 CRUD 操作就可以通過同一個 URI 完成了:
 
讀取) [GET] http://www.example.com/photo/logo
仍然保持爲 [GET] http://www.example.com/photo/logo
 
(創建)http://www.example.com/photo/logo/create
改爲 [POST] http://www.example.com/photo/logo
 
(更新)http://www.example.com/photo/logo/update
改爲 [PUT] http://www.example.com/photo/logo
 
(刪除)http://www.example.com/photo/logo/delete
改爲 [DELETE]  http://www.example.com/photo/logo
 
從而進一步規範了資源標識的使用。
 
通過 REST 架構,Web 應用程序可以用一致的接口(URI)暴露資源給外部世界,並對資源提供語義一致的操作服務。這對於以資源爲中心的 Web 應用來說非常重要。
 
1.2.無狀態
 
在 REST 的定義中,一個 Web 應用總是使用固定的 URI 向外部世界呈現一個資源。
它認爲Web是由一系列的抽象資源組成,這些抽象的資源具有不同的具體表現形式。
譬如,定義一個資源爲photo,含義是照片,它的表現形式可以是一個圖片,也可以是一個.xml的文件,其中包含一些描述該照片的元素,或是一個html文件。 並且這些具體的表現可以分佈在不同的物理位置上。
 
1.3.通過邏輯URI定位資源
 
實現這種級別的可用性的方法之一是定義目錄結構式的 URI。
此類 URI 具有層次結構,其根爲單個路徑,從根開始分支的是公開服務的主要方面的子路徑。 根據此定義,URI 並不只是斜槓分隔的字符串,而是具有在節點上連接在一起的下級和上級分支的樹。
 例如,在一個收集photo的相冊中,您可能定義類似如下的結構化 URI 集合:
 
http://www.example.com/photo/topics/{topic}
 
如:http://www.example.com/photo/topics/home
 
根 / photo之下有一個 /topics 節點。 該節點之下有一系列主題名稱,例如生日照片,聚會照片等等,每個主題名稱指向某個討論線。 在此結構中,只需在 {topic}輸入某個內容即可容易地收集討論線程。
在某些情況下,指向資源的路徑尤其適合於目錄式結構。 例如,以按日期進行組織的資源爲例,這種資源非常適合於使用層次結構語法。 
此示例非常直觀,因爲它基於規則:
 
http://www.example.com/photo/2010/02/22/{topic}
 
第一個路徑片段是四個數字的年份,第二個路徑片斷是兩個數字的月份,第三個片段是兩個數字的日期。這就是我們追求的簡單級別。 在語法的空隙中填入路徑部分就大功告成了,因爲存在用於組合 URI 的明確模式:
http://www.example.com/photo/{year}/{day}/{month}/{topic}
 
從而不需要我們去這樣去傳遞信息:http://www.example.com/photo?year=xxxx&day=xxx$month=xxx&topic=xxxx
 
二.Restful web service的優點:
 
2.1 HTTP頭中可見的統一接口和資源地址
 
通過對於HTTP Head 的解析,我們便可以瞭解到當前所請求的資源和請求的方式。這樣做對於一些代理服務器的設置,將帶來很高的處理效率。
REST 系統中所有的動作和要訪問的資源都可以從HTTP和URI中得到,這使得代理服務器、緩存服務器和網關很好地協調工作。而RPC模型的SOAP 要訪問的資源僅從 URI無法得知,要調用的方法也無法從HTTP中得知,它們都隱藏在 SOAP 消息中。
同樣的,在REST系統中的代理服務器還可以通過 HTTP 的動作 (GET 、 POST)來進行控制。
 
2.2 返回一般的XML格式內容
一般情況下,一個RESTful Web Service將比一個傳統SOAP RPC Web Service佔用更少的傳輸帶寬。
 
2.3 安全機制
REST使用了簡單有效的安全模型。REST中很容易隱藏某個資源,只需不發佈它的URI;而在資源上也很容易使用一些安全策略,比如可以在每個 URI 針對 4個通用接口設置權限;再者,以資源爲中心的 Web服務是防火牆友好的,因爲 GET的 意思就是GET, PUT 的意思就是PUT,管理員可以通過堵塞非GET請求把資源設置爲只讀的,而現在的基於RPC 模型的 SOAP 一律工作在 HTTP 的 POST上。而使用 SOAP RPC模型,要訪問的對象名稱藏在方法的參數中,因此需要創建新的安全模型。
 
 
三. 使用REST架構
 
  對於開發人員來說,關心的是如何使用REST架構,這裏我們來簡單談談這個問題。REST帶來的不僅僅是一種嶄新的架構,它更是帶來一種全新的Web開發過程中的思維方式:通過URL來設計系統結構。REST是一套簡單的設計原則、一種架構風格(或模式),不是一種具體的標準或架構。到今天REST有很多成功的使用案例,客戶端調用也極其方便。
 
下面是我通過Spring3.0來舉個例子:
@Controller 
public class ArticleController { 
   
    @RequestMapping(value = "/article/{category}/{id}", method = RequestMethod.GET) 
    public ModelAndView loadArticle(@PathVariable String category, @PathVariable int id, 
            @RequestParam(value = "mode", required = false) String mode) { 
          // ...
    } 
   
    @RequestMapping(value = "/article", method = RequestMethod.GET) 
    public ModelAndView loadArticleCategories() { 
        // ...
    } 
   
    @RequestMapping(value = "/article", method = RequestMethod.DELETE) 
    public ModelAndView delArticleCategories() { 
         // ...
    } 
   
    @RequestMapping(value = "/addarticle", method = RequestMethod.POST) 
    public ModelAndView addArticleCategories(Category category) { 
        // ...
    } 
   
    @RequestMapping(value = "/addarticle/{name}", method = RequestMethod.POST) 
    public ModelAndView addArticleCategoriesForName(@PathVariable String name) { 
         // ...
    } 
   
}  
 
然後使用Spring提供的RestTemplate來調用這些服務:
@Component("articleClient") 
public class ArticleClient { 
   
    @Autowired 
    protected RestTemplate restTemplate; 
   
    private final static String articleServiceUrl = "http://localhost:8082/articleservice/"; 
   
    @SuppressWarnings("unchecked") 
    public List<Category> getCategories() { 
        return restTemplate.getForObject(articleServiceUrl + "article", List.class); 
    } 
   
    public Article getArticle(String category, int id) { 
        return restTemplate.getForObject(articleServiceUrl + "article/{category}/{id}", Article.class, category, id); 
    } 
   
    @SuppressWarnings("unchecked") 
    public void delCategories() { 
        restTemplate.delete(articleServiceUrl + "article"); 
    } 
   
    @SuppressWarnings("unchecked") 
    public List<Category> postCategories() { 
        Map<String, String> params = new HashMap<String, String>(); 
        params.put("name", "jizhong"); 
        return restTemplate.postForObject(articleServiceUrl + "addarticle/{name}", null, List.class, params); 
   
    } 
   
}  

 
提示一下:使用RestTemplate來驗證Controller層是一個很不錯的選擇。
 
需要注意的是:
 
RestTemplate 默認並不支持對 DELETE 方法使用請求體。
 
因爲RestTemplate 默認是使用 spring 自身的 SimpleClientHttpRequestFactory 創建請求對象和對其進行相關設置(如請求頭、請求體等),它只支持 PUT 和 POST 方法帶請求體,RestTemplate 的 DELETE 方法不支持傳入請求體是因爲 JDK 中 HttpURLConnection 對象的 delete 方法不支持傳入請求體(如果對 HttpURLConnection 對象的 delete 方法傳入請求體,在運行時會拋出 IOException)。
 
我們可以通過修改 RestTemplate 的 RequestFactory 實現 delete 方法對請求體的支持。具體實現可以參考:http://blog.csdn.net/hemingwang0902/article/details/9152431
 
參考資料:
1.     利用 Spring MVC 和 RestTemplate 實現 CorsProxy

博文轉自:http://www.cnblogs.com/rollenholt/p/3693229.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章