Java後端自頂向下方法——一切從HTTP開始

Java後端自頂向下方法——一切從HTTP開始

(一)爲什麼要先學HTTP請求

HTTP協議是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用於從萬維網(WWW:World Wide Web )服務器傳輸超文本到本地瀏覽器的傳送協議。很顯然,HTTP協議是客戶端與服務端之間通信的一個重要橋樑。可見其重要性。
在這裏插入圖片描述
在這個技術日新月異的時代,1991年就已經發布的HTTP協議一直未被淘汰,也一直擔任着傳遞請求和響應的重要任務。對於我們後端開發者來說,我們從客戶端獲取的數據和發送給客戶端的數據,十有八九要藉助HTTP協議來完成,所以我們就從HTTP協議開始學習。

(二)HTTP協議的特點

瞭解一下HTTP協議位於應用層:
在這裏插入圖片描述
我們先來看看神奇的HTTP協議有哪些特點:

  1. 簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑。由於HTTP協議簡單,使得HTTP服務器的程序規模小,因而通信速度很快。
  2. 靈活:HTTP允許傳輸任意類型的數據對象,正在傳輸的類型由Content-Type加以標記。
  3. 無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,斷開TCP連接。這種方式在請求多個資源時,建立TCP連接會浪費較多的時間(HTTP1.1版本支持了持久連接,改善了這個情況)。
  4. 無狀態:HTTP協議是無狀態協議,對於事務處理沒有記憶能力。缺少狀態意味着如果後續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大(cookie的出現打破了這一局面)。

由此可見,HTTP的劣勢在一次次的更新中不斷被改善當然,我能猜到你可能現在是一臉懵,在這裏你可能不需要知道每個特點究竟是什麼意思,咱們暫且混個臉熟,在未來我們對HTTP協議的使用過程中,這些你都會自己慢慢體會到。

(三)HTTP之統一資源定位符

什麼是統一資源定位符?

HTTP使用統一資源標識符(Uniform Resource Identifiers,URI)來傳輸數據和建立連接。URL是一種特殊類型的URI,包含了用於查找某個資源的足夠的信息。URL,全稱是UniformResourceLocator,中文叫統一資源定位符,是互聯網上用來標識某一處資源的地址。

說人話說人話!用專業名詞來解釋專業名詞可不是我的風格!其實這個URL我們天天都能看見,不信你就擡頭,看你瀏覽器的地址欄,你就知道我在說什麼了。這個地址欄裏的地址就是所謂的統一資源定位符了。我隨便來舉個例子,現在我在Google裏搜索“http”,然後地址欄裏變成了

https://www.google.com/search?newwindow=1&sxsrf=ALeKk026EAz0wpwdHgaITghcVcbrZXPt8g%3A1587289292913&ei=zBycXsSbN6S38QOLxriQCw&q=http&oq=http&gs_lcp=CgZwc3ktYWIQAzIHCAAQgwEQQzICCAAyAggAMgIIADIFCAAQgwEyAggAMgIIADICCAAyAggAMgIIADoECCMQJzoGCAAQBxAeOgUIABDNAjoGCAAQBRAeOgQIABBDUMSV3CBY9JncIGDXntwgaAJwAHgAgAHWAYgBkAeSAQUwLjUuMZgBAKABAaoBB2d3cy13aXo&sclient=psy-ab&ved=0ahUKEwjEsdazmfToAhWkW3wKHQsjDrIQ4dUDCAw&uact=5

你現在可以想想我們是怎麼樣通過這個URL獲得這個網頁的內容的。首先,資源都是保存在服務器中的,那麼我們的瀏覽器必然要告訴服務器,我需要哪個資源?這樣服務器才知道要發送給你什麼資源啊。顯然,這個URL就代表了一種資源。細心的你可能發現,這個URL裏面怎麼又那麼多亂七八糟的東西,比如?&=-%/:之類的,那麼下面我們就來講一講URL的組成。

  1. 協議部分:該URL的協議部分爲“https:”,這代表網頁使用的是HTTPS協議(是一種更加安全的HTTP協議,現階段我們就把他當HTTP協議來看)。在"HTTPS"後面的“//”爲分隔符。
  2. 域名部分:該URL的域名部分爲“www.google.com”。他會被DNS服務器解析爲IP地址,所以也可以直接使用IP地址代替域名使用。
  3. 端口部分:(非必須)跟在域名後面的是端口(我們這個URL中沒有寫端口),域名和端口之間使用“:”作爲分隔符。如果省略端口部分,將採用默認的80端口。
  4. 虛擬目錄部分:(非必須)從域名後的第一個“/”開始到“?”前爲止,是虛擬目錄部分,是資源在服務器所在的位置。該URL中的虛擬目錄是“/search”。虛擬目錄的根目錄會映射到服務器的特定真實目錄下。當我們使用Restful API時(後面會講)這個虛擬目錄又有新的理解。
  5. 錨部分:(非必須)從“#”開始到最後,都是錨部分。這個東西不算特別重要,暫時先不講。
  6. 參數部分:從“?”開始到“#”爲止之間的部分爲參數部分,又稱搜索部分、查詢部分。參數以鍵值對的形式出現,即key = value。參數可以允許有多個參數,參數與參數之間用“&”作爲分隔符。該URL中參數很多,大家可以依次找找看,增加理解。

這樣我大概解釋完了這個URL的組成部分,相信大家都已經理解了,因爲這確實非常簡單。在以後的學習中,這個東西將常伴你左右。

(四)HTTP之Request

講了這麼多,終於講到向服務器發出的HTTP請求的內容了。首先我們先來看看一個標準的HTTP請求裏面有些什麼內容。

在這裏插入圖片描述
第一部分:請求行,用來說明請求類型,要訪問的資源以及所使用的HTTP版本。

第二部分:請求頭部,緊接着請求行(即第一行)之後的部分,用來說明服務器要使用的附加信息。

第三部分:空行,請求頭部後面的空行是必須的。即使第四部分的請求數據爲空,也必須有空行。

第四部分:請求數據也叫請求體,可以添加任意的其他數據。在這個例子中的請求數據爲空。

當然,直接看這些概念肯定會比較抽象,我們再來舉個例子。

POST /test HTTP1.1
Host:www.abc.com
User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Content-Type:application/x-www-form-urlencoded
Content-Length:40
Connection: Keep-Alive

name=TOM&age=21

第一部分:請求行,第一行明瞭是post請求,以及http1.1版本。
第二部分:請求頭部,第二行至第六行。標明瞭附加信息。
第三部分:空行,第七行的空行。
第四部分:請求體,第八行。

請大家仔細觀察這個HTTP的request請求,有沒有發現一些熟悉的東西?裏面是不是有一部分東西似乎在之前提到的URL中出現過?觀察完之後,試着能不能找出這個request中包含的URL是什麼。如果忘記了,趕緊回去看看上面的圖。

沒錯,就是:http://www.abc.com/test
很顯然,請求頭中的Host就對應了URL中的域名,請求行中的URL部分實際上是真正URL中的虛擬目錄部分。什麼?你問爲什麼請求體中的參數不見了?你一定是看見了“name=TOM&age=21”了吧,這當然不是我寫錯了。這涉及到我們接下來要講的HTTP請求的請求方式。

(五)HTTP之請求方式

首先我們看看HTTP到底支持哪些請求方式,下面列舉了一些常見的請求方式。

GET     	請求指定的頁面信息,並返回實體主體。
HEAD     	類似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭。
POST     	向指定資源提交數據進行處理請求,數據被包含在請求體中。
PUT     	從客戶端向服務器傳送的數據取代指定的文檔的內容。
DELETE      請求服務器刪除指定的頁面。
CONNECT     HTTP/1.1協議中預留給能夠將連接改爲管道方式的代理服務器。
OPTIONS     允許客戶端查看服務器的性能。
TRACE     	回顯服務器收到的請求,主要用於測試或診斷。

其中,我們最常用的,是POST、DELETE、PUT、GET這四個請求方式。他們分別對應了四種基本操作:增刪改查。但是有一點非常關鍵,這種規範只是一種人爲的約定而已,這四種請求方式的名字和他們的功能對應關係並不是絕對的,具體對請求的操作是服務端書寫控制器的時候才實現的,換句話說,我們在書寫Restful API時,當然可以用get請求來表示刪除數據,也可以用post請求來表示查詢數據,雖然這會讓人覺得怪怪的。這是初學者必須要注意的一點,非常重要!!!具體的用法我們會在下面和Restful API一起講。

PS:網上有許多博客都着重寫了GET和POST的區別,主要關注點是GET請求的參數放URL中、POST請求的參數放請求體中。我也特意查了相關的資料,HTTP協議好像並沒有這種規定。這應該只能算是一種約定。還有就是關於URL的長度限制問題,HTTP協議也未提及,這個限制可能是來自於瀏覽器和服務器,具體限制長度是多少,要具體情況具體分析。

(六)HTTP之Response

Http Response包括三個部分:響應狀態行,響應頭和響應體。第一行是響應狀態行包括Http版本+響應狀態,以空格分隔。從第二行開始是響應頭,包含若干個鍵值對,每個鍵值對佔一行。後面空一行,接着是響應體。
在這裏插入圖片描述
乍一看,這Response和Request區別也不大。首先我們可以想想,作爲一個HTTP響應,與HTTP請求相比,有哪些部分是沒必要加上的?首先,虛擬地址不需要。服務器已經開始返回數據了,證明他已經知道了需要訪問哪個資源了,這個虛擬地址也沒必要再返回給客戶端了。同理可得,請求方法也就不需要了。所以我們在學習過程中,不僅要學會協議的內容,還要思考協議爲什麼要這樣設計。下面我放一個Request來對比一下,看看是不是這樣。
在這裏插入圖片描述
很顯然,上面的Response還多了一個“200 OK”的狀態碼,這個是幹什麼用的?接下來就來講這個。

(七)HTTP之狀態碼

狀態碼由三位數字組成,第一個數字定義了響應的類別,共分五種類別:

1xx:指示信息–表示請求已接收,繼續處理
2xx:成功–表示請求已被成功接收、理解、接受
3xx:重定向–要完成請求必須進行更進一步的操作
4xx:客戶端錯誤–請求有語法錯誤或請求無法實現
5xx:服務器端錯誤–服務器未能實現合法的請求

我相信你們肯定在上網時看見過這種頁面:
在這裏插入圖片描述
現在,你終於知道404是什麼意思了吧。他是HTTP的其中一種“標準迴應消息”(HTTP狀態碼),此消息代表客戶端在瀏覽網頁時,服務器無法正常提供消息,或是服務器無法迴應且不知原因。通常是因爲用戶所訪問的對應網頁已被刪除、移動或從未存在。404也是互聯網上最常見的錯誤之一。

當然,我們沒必要把所有的狀態碼全都背下來,很困難也沒必要,因爲他們實在是太多了。下面我列出幾個最常用的,剩餘的我們可以遇到之後再問問Google。

200 OK                        客戶端請求成功
400 Bad Request               客戶端請求有語法錯誤,不能被服務器所理解
401 Unauthorized              請求未經授權
403 Forbidden                 服務器收到請求,但是拒絕提供服務
404 Not Found                 請求資源不存在
500 Internal Server Error     服務器發生不可預期的錯誤
503 Server Unavailable        服務器當前不能處理客戶端的請求,一段時間後可能恢復正常

狀態碼存在的必要是當客戶端收到請求,可以通過狀態碼快速的得知數據傳輸的情況和獲取資源的情況。在後面的開發中我們會講到,我們可以自定義錯誤類型,也就是說我們可以設計自己的狀態碼。

(八)HTTP與Restful API

如果我沒記錯,前面我不止一次提到了這個所謂的Restful API,那這是個什麼東西?
在這裏插入圖片描述
實際上,這東西是一個叫Roy Fielding的人的畢業論文,這哥們參與過設計HTTP協議。大家都知道,過去網頁設計是前端後端融在一起的,比如PHP,JSP等。但是近年來移動互聯網的發展,各種類型的Client層出不窮,RESTful可以通過一套統一的接口爲 Web,iOS和Android提供服務。另外對於廣大平臺來說,它們不需要有顯式的前端,只需要一套提供服務的接口,於是RESTful更是最好的選擇。
在這裏插入圖片描述
上面那段話不理解沒關係,以後你會慢慢理解的。其實,Restful是個很簡單的東西,相當於一種架構或是一種規範而已。網上許多博客都把他複雜化了,讓初學者很難去理解他究竟是什麼、怎麼用。我曾經在學習時看見過這樣的三句話,非常完美的概括了Restful API:

看URL就知道要什麼
看http method就知道幹什麼
看http status code就知道結果是什麼

現在你可能還看不出這三句話到底妙在哪裏,所以我們先慢慢一點一點講。

首先,我們要明確的一點是,請求的目的是操作資源。而Restful是面向資源的,也就是說URL中的內容代表的是一種資源,從語言上來看,這應該是一個名詞,比如書、雜誌、學生或者是汽車等等。但是,衆所周知,作爲一個請求,只有名詞是肯定不行的,還要有相應的動詞做支撐,比如,查詢一本書,添加一本雜誌,刪除一個學生等等,這樣纔是一個完整的請求,也就是所謂的動詞+名詞。

那麼,名詞已經有了,動詞該怎麼表示呢?別忘了,除了URL之外,我們還有請求方式。前文提過,POST、DELETE、PUT、GET四個請求方式分別對應了四種基本操作:增刪改查,這東西終於有用武之地了。加上相應的動詞之後,整個請求就算是拼裝完了。

下面我們來看一個小例子,當代大學生最喜歡的案例之一:圖書管理系統。

咱們先假設我們項目的域名是example.com,我們來完成圖書的增刪改查的Restful API設計。比如我現在要查詢圖書,那麼請求方式爲GET,請求的URL可以設計爲http://example.com/library/book,當然,這個URL可能無法精確指定我們具體想查哪一本書,所以我們就把他當做是查詢所有的書,服務器將會返回一個書的集合,裏面包括了所有的書。那麼問題來了,我現在就想查詢一本指定ID的書,該如何設計呢?別忘了,除了虛擬地址外,我們還有參數沒用呢。

所以,我們要爲這個API加上一個參數,使他變成一個新的API,我們可以這樣設計http://example.com/library/book?id=?,這裏的?就填你要查詢的ID就行,如果不填,那就相當於上面那個API,也就是查詢所有書。

同理,我們就可以設計出這個項目需要的所有的API了,我們以請求方式+請求URL的方式來展現一下。

GET http://example.com/library/book	          查詢所有書
GET http://example.com/library/book?id=k      查詢ID爲k的書
DELETE http://example.com/library/book?id=k   刪除ID爲k的書
PUT http://example.com/library/book?id=k      修改ID爲k的書
POST http://example.com/library/book?id=k     添加ID爲k的書

通過這個小案例,大家應該已經明白瞭如何去設計Restful API了,那麼HTTP的基礎部分就到此結束了。

2020年4月21日

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章