rest 的理解

rest:表現層狀態轉移。java

什麼是restful協議?https://en.wikipedia.org/wiki/Representational_state_transfer 使用restful的好處。web

Rest是一種體系結構樣式,他定義了一組用於建立web服務的約束。符合REST體系結構風格或RESTful Web服務的Web服務提供Internet上計算機系統之間的互操做性。與rest兼容的web服務容許請求系統經過使用統一的和預約義的無狀態操做集來訪問和操做web資源的文本表示。其餘類型的web服務,如SOAP web服務,公開它們本身的任意操做集。spring

「Web資源」最初在萬維網上定義爲由url標識的文檔或文件。然而,如今它們有了一個更加通用和抽象的定義,它包含了全部能夠在web上以任何方式識別、命名、處理或處理的事物或實體。在基於rest的web服務中,對資源URI的請求將經過HTML、XML、JSON或其餘格式的有效負載引起響應。響應能夠確認對存儲的資源進行了一些更改,而且響應能夠提供到其餘相關資源或資源集合的超文本連接。當使用HTTP時,最多見的操做是GET、POST、PUT、DELETE和其餘預約義的CRUD HTTP方法。數據庫

經過使用無狀態協議和標準操做,REST系統旨在經過重用可管理和更新的組件來實現快速性能、可靠性和增加能力,即便在系統運行時也不影響整個系統。編程

表徵狀態轉移(rest)一詞是由Roy Fielding在2000年的博士論文中提出並定義的。從1994年開始,Fielding的論文解釋了REST原則,即「HTTP對象模型」,並被用於設計HTTP 1.1和統一資源標識符(Uniform Resource identifier, URI)標準。[4][5][6]這個詞是爲了喚起的形象設計良好的Web應用程序的行爲:它是一個網絡的網絡資源(虛擬狀態機),用戶經過應用程序經過選擇連接,如/ user /湯姆,和獲取或刪除等操做(狀態轉換),致使下一個資源(表明應用程序的下一個狀態)傳輸給用戶使用。json

1建築屬性api

REST架構風格的約束影響如下架構屬性:瀏覽器

組件交互中的性能,這是影響用戶感知性能和網絡效率的主要因素緩存

可伸縮性容許支持大量組件和組件之間的交互。Roy Fielding將REST對可伸縮性的影響描述以下:rest的客戶機-服務器關注點分離簡化了組件實現,下降了鏈接器語義的複雜性,提升了性能調優的有效性,並提升了純服務器組件的可伸縮性。分層系統約束容許中介——代理、網關和防火牆——在通訊的各個點引入,而無需更改組件之間的接口,從而容許它們幫助通訊轉換或經過大規模共享緩存提升性能。REST經過將消息約束爲自描述的方式實現了中間處理:請求之間的交互是無狀態的,標準方法和媒體類型用於指示語義和交換信息,響應顯式地指示可緩存性。安全

統一接口的簡單性;

組件的可修改性以知足不斷變化的需求(甚至在應用程序運行時);

服務代理之間組件間通訊的可見性;

利用數據移動程序代碼實現組件的可移植性;

在組件、鏈接器或數據中存在故障時,在系統級別對故障的抵抗的可靠性。

2體系結構約束

六個指導約束定義了一個RESTful系統。這些約束限制了服務器處理和響應客戶機請求的方式,所以,經過在這些約束中操做,服務能夠得到理想的非功能屬性,如性能、可伸縮性、簡單性、可修改性、可見性、可移植性和可靠性。若是服務違反了任何須需的約束,就不能認爲它是RESTful的。

形式REST約束以下:

客戶機-服務器體系結構

客戶機-服務器約束背後的原則是關注點分離。將用戶界面關注與數據存儲關注分離能夠提升用戶界面跨多個平臺的可移植性。它還經過簡化服務器組件來提升可伸縮性。然而,對Web來講最重要的多是分離容許組件獨立地演進,從而支持多個組織領域的internet規模需求

無國籍(無狀態協議

客戶機-服務器通訊受到請求之間服務器上沒有存儲客戶機上下文的約束。來自任何客戶機的每一個請求都包含服務請求所需的全部信息,會話狀態保存在客戶機中。服務器能夠將會話狀態轉移到另外一個服務(如數據庫),以便在一段時間內保持持久狀態並容許身份驗證。客戶端在準備轉換到新狀態時開始發送請求。當一個或多個請求未完成時,客戶端被認爲處於過渡狀態。每一個應用程序狀態的表示都包含可在下次客戶端選擇發起新的狀態轉換時使用的連接。

緩存能力

在萬維網上,客戶機和中介體能夠緩存響應。所以,響應必須隱式或顯式地將本身定義爲可緩存的或不可緩存的,以防止客戶機在響應進一步請求時獲取陳舊或不合適的數據。管理良好的緩存部分或徹底消除了一些客戶機-服務器交互,進一步提升了可伸縮性和性能。

可緩存:

        HTTP狀態碼(org.springframework.http.HttpStatus)

             200:HttpStatus#ok

             304:HttpStatus#NOT_MODIFIED  第一次完整請求,獲取響應頭(200),body直接獲取,第二次請求,只讀取頭信息,響應頭(304),客戶端(瀏覽器)取上次body結果。

             400:HttpStatus#BAD_REQUEST

              ....

       響應:

              響應頭(Headers)

                     元信息(Meta-Data)

                             Accept-Language->Locale

                            Connection->Keep-Alive

                            實現多值Map:MutiValueMap

                                    key:value=1:n

                                    name:value=1:n

             響應體

                    業務信息(Business Data)

                    Body:HTTP實體、REST

                            @ResponseBody

                             HttpEntity.body屬性(泛型結構)

                   Payload:消息JMS、事件、SOAP

 

                    

 

分層系統

客戶端一般沒法分辨它是直接鏈接到終端服務器,仍是一路鏈接到中介。中介服務器能夠經過啓用負載平衡和提供共享緩存來提升系統的可伸縮性。它們還能夠執行安全策略。

按需編碼(可選)

參見:客戶端腳本

服務器能夠經過傳輸可執行代碼臨時擴展或定製客戶機的功能。例如,編譯組件(如Java applet)和客戶端腳本(如JavaScript)。

3統一的接口

統一接口約束是任何REST服務設計的基礎。它簡化和解耦了體系結構,使每一個部分可以獨立發展。這個統一接口的四個約束條件是:

請求中的資源標識:即自定義消息

在請求中標識單個資源,例如在基於web的REST系統中使用uri。資源自己在概念上與返回給客戶機的表示是分開的。例如,服務器能夠從數據庫中以HTML、XML或json的形式發送數據——這些都不是服務器的內部表示。

經過表示操做資源----http動詞

當客戶機持有資源的表示形式(包括附加的任何元數據)時,它有足夠的信息來修改或刪除資源。

自描述信息

每一個消息都包含足夠的信息來描述如何處理消息。例如,能夠經過媒體類型指定要調用的解析器

       註解驅動

              @RequestBody

               JSON-> MappingJackson2HttpMessageConverter

               @ResponseBody

                JSON->MappingJackson2HttpMessageConverter

       接口編程

              ResponseEntity extends HttpEntity

              RequestEntity extends HttpEntity

 

超媒體做爲應用程序狀態(HATEOAS)的引擎

訪問了REST應用程序的初始URI(相似於人工Web用戶訪問Web站點的主頁)以後,REST客戶機應該可以動態地使用服務器提供的連接來發現它所需的全部可用操做和資源。隨着訪問的繼續,服務器將使用文本進行響應,其中包括指向當前可用的其餘操做的超連接。客戶端不須要硬編碼有關REST服務的結構或動態的信息。

應用於Web服務

遵循REST體系結構約束的Web服務api稱爲RESTful api。基於http的RESTful api的定義以下

一個基本URL,例如http://api.example.com/resources;

定義狀態轉換數據元素(例如,Atom、微格式、應用程序/vnd)的媒體類型。當前表示告訴客戶端如何組合轉換到全部下一個可用應用程序狀態的請求。這能夠像URL同樣簡單,也能夠像Java applet同樣複雜

標準HTTP方法(例如,選項、GET、PUT、POST和DELETE)

URL和HTTP方法之間的關係

下表顯示了在RESTful API中一般如何使用HTTP方法:

HTTP方法

Get、put、patch、Post、delete

GET方法是一種安全的方法(或無效),這意味着調用它不會產生反作用:檢索或訪問記錄不會改變它。PUT和DELETE方法是等冪的,這意味着不管重複請求多少次,API公開的系統狀態都是不變的。

與基於soap的Web服務不一樣,RESTful Web api沒有「官方」標準。這是由於REST是一種體系結構風格,而SOAP是一種協議。REST自己不是標準,可是RESTful實現使用了標準,例如HTTP、URI、JSON和XML。許多開發人員還將他們的api描述爲RESTful,儘管這些api實際上並無實現上面描述的全部架構約束(尤爲是統一接口約束)

        資源定位-URI

        資源操做-HTTP動詞

                GET

                         @GetMapping

                                   註解屬性別名和覆蓋:在Spring framework4.2中引入,Spring Boot1.3才能使用,Spring Boot加以發展,能夠看一下AnnotatedElementUtils.getMergedAnnotationAttributes

                                   根據這個,能夠本身實現相似的註解,好比:

                    

                PUT

                         @PutMapping

                POST

                         @PostMapping

                        @PostMapping是註解,@RequestMapping是@PostMapping的註解:

                                     @RequestMapping是@PostMapping的元註解

                                     @RequestMapping元標註了@PostMapping

                                     @AliasFor只能標註在目標註解的屬性,所annotation()的註解必須是元註解,該註解attribute必須是是元註解的屬性。

 

                PATCH

                         @PatchMapping

                         限制,在Servlet API中並無規定PATCH方法,Spring Web對其作了擴展。

 

javax.servlet.http.HttpServlet

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String method = req.getMethod();
 long lastModified;
 if (method.equals("GET")) {
        lastModified = this.getLastModified(req);
 if (lastModified == -1L) {
            this.doGet(req, resp);
 } else {
            long ifModifiedSince;
 try {
                ifModifiedSince = req.getDateHeader("If-Modified-Since");
 } catch (IllegalArgumentException var9) {
                ifModifiedSince = -1L;
 }

            if (ifModifiedSince < lastModified / 1000L * 1000L) {
                this.maybeSetLastModified(resp, lastModified);
 this.doGet(req, resp);
 } else {
                resp.setStatus(304);
 }
        }
    } else if (method.equals("HEAD")) {
        lastModified = this.getLastModified(req);
 this.maybeSetLastModified(resp, lastModified);
 this.doHead(req, resp);
 } else if (method.equals("POST")) {
        this.doPost(req, resp);
 } else if (method.equals("PUT")) {
        this.doPut(req, resp);
 } else if (method.equals("DELETE")) {
        this.doDelete(req, resp);
 } else if (method.equals("OPTIONS")) {
        this.doOptions(req, resp);
 } else if (method.equals("TRACE")) {
        this.doTrace(req, resp);
 } else {
        String errMsg = lStrings.getString("http.method_not_implemented");
 Object[] errArgs = new Object[]{method};
 errMsg = MessageFormat.format(errMsg, errArgs);
 resp.sendError(501, errMsg);
 }

}

 

 

                DELETE

                         @DeleteMapping

 

根據別名覆蓋和這幾個註解,咱們能夠嘗試寫一個組合註解,把2個註解的功能結合起來,好比:

以上還能夠對事務起個別名:

 

 

相關文章
相關標籤/搜索