Web框架如何快速入門(mén)

Web框架正如前文所述, 在整個(gè)項(xiàng)目結(jié)構(gòu)中處于一個(gè)承上啟下的位置, 是整個(gè)項(xiàng)目的核心組件, 所以這次來(lái)聊聊Web框架的一些普適性特性和如何快速的入門(mén).

為什么Web框架需要快速入門(mén)?

Web框架是一組工具的集合, 為你的Web應(yīng)用開(kāi)發(fā)提供了基礎(chǔ)環(huán)境, 從如何獲取參數(shù), 到如何返回結(jié)果, 從如何獲取cookie到如何修改返回的http header. Web框架幫你隱藏了HTTP協(xié)議的細(xì)節(jié), 你作為一個(gè)使用者只需要關(guān)心如何使用, 而毋須去了解細(xì)節(jié)( 當(dāng)然如果你打算自己實(shí)現(xiàn)一個(gè)Web框架除外 ).

第二個(gè)原因是Web框架很多, 不同的語(yǔ)言都有自己實(shí)現(xiàn)的不同的Web框架(Python尤其的多). 每一種都有各自不同的實(shí)現(xiàn)思路, 有不同的開(kāi)發(fā)哲學(xué), 不管是就換工作換開(kāi)發(fā)棧的需要, 還是學(xué)習(xí)本身的需要, 快速的多掌握幾個(gè)框架還是很有必要的.

繼續(xù)閱讀本文需要掌握HTTP協(xié)議的基本知識(shí), 如果不了解請(qǐng)前往?<關(guān)于HTTP協(xié)議,一篇就夠了>

以下是一個(gè)Web框架的通用Guide, 基本上你能涉及到的大多數(shù)Web框架都是遵循下面的模式來(lái)的, 少數(shù)奇葩不在本文描述的范疇, 但是需要理解的知識(shí)點(diǎn)和問(wèn)題領(lǐng)域是大致相同, 你可以參考著來(lái).

一. Web框架的工作方式

現(xiàn)代的Web框架,不管其采用何種設(shè)計(jì)思想, 開(kāi)發(fā)哲學(xué), 根本的工作模式是相似的,均是從接收HTTP請(qǐng)求,處理HTTP的各項(xiàng)參數(shù),路由到相應(yīng)的用戶實(shí)現(xiàn)的處理器上, 再獲取返回的結(jié)果, 生成HTTP的Response.如下圖:

web框架工作流程

其中, 只有URL路由和控制器部分是由用戶來(lái)定義的, 所以, 如果要快速上手一個(gè)Web框架, 就要先從這兩個(gè)部分入手.

一. URL路由

一般來(lái)說(shuō)現(xiàn)在大部分的Web框架對(duì)于將HTTP請(qǐng)求交給哪一個(gè)邏輯來(lái)處理, 是由URL路由框架的模塊來(lái)決定的. URL路由模塊會(huì)提供一些函數(shù)或者裝飾器等方式, 讓用戶來(lái)寫(xiě)一些代碼, 將URL和控制器的綁定關(guān)系注冊(cè)到框架中.

大多數(shù)的框架都支持在URL路由的定義中使用正則表達(dá)式.有的支持在URL中定義參數(shù),框架會(huì)自動(dòng)在URL中將參數(shù)截取出來(lái)保存在框架的上下文中以供控制器使用.

舉幾個(gè)例子:

Django的URL路由定義

Django是通過(guò)定義了一個(gè)數(shù)組, 其中包含了url和控制器的關(guān)系來(lái)定義的URL路由

SpringMVC定義URL路由

SpringMVC是通過(guò)在控制器上定義裝飾器來(lái)將控制器和URL的關(guān)系注冊(cè)到框架中的.

以上兩種是最長(zhǎng)用的兩種注冊(cè)的模式

二.控制器

控制器是用戶自己實(shí)現(xiàn)的類(lèi)或者函數(shù), 用來(lái)處理HTTP請(qǐng)求, 確切的說(shuō)是指定URL發(fā)來(lái)的請(qǐng)求, 并且將業(yè)務(wù)邏輯的結(jié)果返回給框架, 有框架去決定如何解析成HTTP的響應(yīng)數(shù)據(jù)輸出.

由于是由框架來(lái)調(diào)用控制器, 所以框架不同, 對(duì)控制器的定義規(guī)范是各不相同的. 有的框架要求控制器是一個(gè)類(lèi), URL將會(huì)Map到類(lèi)上, 類(lèi)中定義了GET, PUT, DELETE等方法, 用來(lái)對(duì)應(yīng)處理HTTP的GET, PUT, DELETE等方法的請(qǐng)求. 有的是將URL的不同方法的請(qǐng)求Map到不同的函數(shù), 或者將URL的不同方法Map到同一個(gè)函數(shù)上執(zhí)行. 這些差異和實(shí)現(xiàn)框架的語(yǔ)言有關(guān)系, 比如Java, C#等語(yǔ)言, 函數(shù)必須以類(lèi)方法的形式定義而不能成為頂級(jí)元素, 那么這些語(yǔ)言的框架大多會(huì)要求將控制器定義成類(lèi), 而Python, Ruby, Javascript這些函數(shù)是頂級(jí)元素的語(yǔ)言, 大多數(shù)的框架都是將控制器用函數(shù)來(lái)定義, 當(dāng)然也有異類(lèi), 非要用類(lèi)來(lái)定義的, 比如說(shuō) Python的Tornado, 有的是兩種方式都支持. 這個(gè)跟框架作者的喜好關(guān)系比較大.

框架需要給控制器提供HTTP請(qǐng)求的完整上下文環(huán)境,那么我們?cè)趯W(xué)習(xí)框架使用的時(shí)候, 首先就要在文檔中整理清楚下面的這些問(wèn)題:

1. 如何獲取Query String參數(shù)?

QueryString是url中?后定義的由&符號(hào)分割的key=value形式的參數(shù), 框架會(huì)在解析HTTP協(xié)議的時(shí)候?qū)⑦@個(gè)部分的數(shù)據(jù)轉(zhuǎn)化成比如字典之類(lèi)的數(shù)據(jù)結(jié)構(gòu)存起來(lái), 然后提供相應(yīng)的API去訪問(wèn).但是QueryString都是只讀的, 有一些框架會(huì)提供一些工具幫助用戶組裝URL, 比如Flask提供了url_for用來(lái)組裝轉(zhuǎn)跳到指定控制器的URL, 方便你在頁(yè)面上渲染相應(yīng)的<a>標(biāo)簽

2.如何獲取Form表單的數(shù)據(jù)(Json body)?

POST和PUT方法是HTTP協(xié)議中主要的接收數(shù)據(jù)的語(yǔ)義, 傳輸數(shù)據(jù)需要相應(yīng)的編碼方式將數(shù)據(jù)編碼后放在HTTP協(xié)議的Body部分. 編碼方式現(xiàn)在主要有兩種, 一種是最古老的用Form表單編制數(shù)據(jù)的方式, 另外一種是將數(shù)據(jù)用json字符串直接放到HTTP協(xié)議的body部分. 網(wǎng)頁(yè)上的應(yīng)用多數(shù)會(huì)采用Form表單, 因?yàn)檫@是瀏覽器對(duì)Form表單的默認(rèn)支持, 而App的后端大多采用JSONString放在body來(lái)傳數(shù)據(jù)的方式, 優(yōu)點(diǎn)是可以傳送復(fù)雜的數(shù)據(jù)結(jié)構(gòu).

Web框架會(huì)提供相應(yīng)的API去按照這兩種方式獲取Body的內(nèi)容, 但是有的框架會(huì)根據(jù)header里的mime type來(lái)判斷是不是可以按照J(rèn)SON去解析body的內(nèi)容.

3. 如何讀取和修改cookie?

cookie是瀏覽器(客戶端)在多次請(qǐng)求之間共享數(shù)據(jù)的一個(gè)數(shù)據(jù)結(jié)構(gòu), 因?yàn)镠TTP協(xié)議是無(wú)狀態(tài)的,所以cookie在每一次請(qǐng)求的時(shí)候都會(huì)從瀏覽器放到HTTP請(qǐng)求中傳到服務(wù)端, 在服務(wù)端生成響應(yīng)的時(shí)候也會(huì)寫(xiě)入HTTP響應(yīng)里傳回瀏覽器. 從而實(shí)現(xiàn)了在兩次請(qǐng)求之間共享了數(shù)據(jù).

Web框架會(huì)提供對(duì)應(yīng)的API去讀取和修改cookie的值, cookie是key-value形式的, 訪問(wèn)的方式應(yīng)該和字典類(lèi)似.

4. 如何獲取headers?

headers對(duì)應(yīng)到HTTP協(xié)議中HTTP請(qǐng)求的頭部, 是一個(gè)key-value形式的數(shù)據(jù)格式.headers是HTTP請(qǐng)求的一些額外的描述信息, 比如客戶端類(lèi)型, 字符編碼方式, 認(rèn)證信息等. headers的key是固定的, 你不能自己隨便定義一些特殊key, 并且headers部分也是只讀的.框架會(huì)提供對(duì)應(yīng)API去讀取headers.

5. 如何實(shí)現(xiàn)頁(yè)面轉(zhuǎn)跳?

有些時(shí)候在處理完數(shù)據(jù)后需要通知瀏覽器轉(zhuǎn)跳到對(duì)應(yīng)的看數(shù)據(jù)的URL上去, 就需要在文檔里找找如何實(shí)現(xiàn)頁(yè)面轉(zhuǎn)跳. 服務(wù)端返回給客戶端一個(gè)HTTP協(xié)議中的301或者302的狀態(tài), 就可以讓瀏覽器去執(zhí)行轉(zhuǎn)跳的動(dòng)作, 作出這樣子的HTTP響應(yīng)在框架中會(huì)有對(duì)應(yīng)的API.

6. 如何輸出Http響應(yīng)?

大多數(shù)的Web框架都是用函數(shù)(方法)的返回值來(lái)作為Http響應(yīng)的body的, 所以你在很多示例中可以看到 return "hello world" 這樣子的寫(xiě)法, 框架會(huì)自動(dòng)把字符串轉(zhuǎn)換成Response的對(duì)象再去做編碼成Http響應(yīng)的操作.

當(dāng)然有一些例外, 比如Python的Tornado就是用控制器繼承的基類(lèi)中提供的write方法, 來(lái)向輸出的流中寫(xiě)入數(shù)據(jù)的.

針對(duì)App的API會(huì)比較方便, 輸出JSON的字符串就行了. 如果是網(wǎng)站的話, 需要輸出HTML頁(yè)面,有一些框架提供了內(nèi)置的模板引擎, 用于渲染輸出html內(nèi)容(其實(shí)不限html, xml的內(nèi)容也可以由模板引擎來(lái)渲染). 有的框架自己不提供模板引擎, 你可以用你喜歡的模板引擎來(lái)渲染.

在框架的文章中找到上述問(wèn)題的答案后, 我們就可以在控制器中獲取請(qǐng)求的上下文和控制輸出了.

搞定上面內(nèi)容我們就可以寫(xiě)邏輯了, 控制器中邏輯的一般性結(jié)構(gòu)如下:

控制器代碼一般邏輯


在學(xué)習(xí)完URL路由和控制器部分后, 你就可以嘗試寫(xiě)一些簡(jiǎn)單的東西了, 起碼一些簡(jiǎn)單的demo可以跑起來(lái)了. 接下來(lái)為了讓你的Demo可以跑起來(lái), 還需要繼續(xù)學(xué)習(xí)框架的一些進(jìn)一步的特性

三. 開(kāi)發(fā)環(huán)境

Web框架的開(kāi)發(fā)環(huán)境由其實(shí)現(xiàn)的語(yǔ)言來(lái)決定, 比如用Java的很多是Eclipse, C#是visual studio, 大公司IDE產(chǎn)品很多都內(nèi)置集成了開(kāi)發(fā)運(yùn)行的環(huán)境方便調(diào)試, 而很多開(kāi)源產(chǎn)品就五花八門(mén)了, 所以比如Python, Ruby和nodejs下的web框架大多都內(nèi)置了開(kāi)發(fā)服務(wù)器, 啟動(dòng)開(kāi)發(fā)服務(wù)器就等于啟動(dòng)了一個(gè)小web服務(wù)器, 并且大多數(shù)都提供了檢測(cè)文件改變后自動(dòng)重啟服務(wù)的auto reload功能.

四. 配置或者約定

配置用來(lái)自定義框架的一些特性, 不同的框架配置區(qū)別是蠻大的, 有的基于配置文件, 有的是約定優(yōu)先, 有的代碼本身就是配置, 所以這部分仔細(xì)看文檔即可, 并且可配置的項(xiàng)目可能很多, 在學(xué)習(xí)階段其實(shí)可以將文檔的這部分做成Cheat Sheet方便平時(shí)查閱.

如果是約定優(yōu)先的框架多半會(huì)提供腳手架工具, 熟悉腳手架工具也是很重要的一點(diǎn).

五. 模板引擎

前面在控制器的部分提到了模板引擎, 模板引擎主要負(fù)責(zé)用數(shù)據(jù)替換模板上的占位符生成最終結(jié)果的文本. 工作方式可以簡(jiǎn)化為下圖:

這里詳細(xì)的說(shuō)一下模板引擎部分在學(xué)習(xí)的時(shí)候要注意那一些要點(diǎn):

1. 占位符如何定義

2. 如何定義循環(huán)

3. 如何定義判斷條件

4. 如何對(duì)占位符加過(guò)濾器

5. 如何定義繼承模板

6. 如何定義嵌套模板

在文檔中學(xué)習(xí)完上面六點(diǎn)基本上就能玩轉(zhuǎn)一個(gè)模板引擎了, 當(dāng)然你之后還是可以繼續(xù)深入學(xué)習(xí)的, 但是這六點(diǎn)已經(jīng)可以支撐你做完完整的應(yīng)用了.

六. 中間件

中間件是AOP模式統(tǒng)一在每個(gè)請(qǐng)求的開(kāi)始和結(jié)束部分注入代碼的機(jī)制, 最常見(jiàn)的有兩個(gè)級(jí)別的中間件, 一個(gè)是Application級(jí)別的, 也就是在應(yīng)用啟動(dòng)和結(jié)束的時(shí)候執(zhí)行注入的代碼, 另一個(gè)是Request級(jí)別的, 主要是在每個(gè)請(qǐng)求開(kāi)始和結(jié)束的時(shí)候執(zhí)行, 比如統(tǒng)一的鑒權(quán),數(shù)據(jù)庫(kù)連接管理(打開(kāi),關(guān)閉), 統(tǒng)一的錯(cuò)誤處理 都可以在這里完成.

簡(jiǎn)單的來(lái)說(shuō)如下圖所示:

七. 統(tǒng)一錯(cuò)誤處理

有的框架是提供了統(tǒng)一錯(cuò)誤處理機(jī)制的, 當(dāng)在控制器中發(fā)生了沒(méi)有捕獲或者重新拋出的異常的時(shí)候, 就會(huì)執(zhí)行到統(tǒng)一錯(cuò)誤處理的部分. 這里可以統(tǒng)一完成關(guān)閉數(shù)據(jù)庫(kù)連接等清理工作.一般都是由框架內(nèi)置的中間件來(lái)實(shí)現(xiàn)的.

八. 鑒權(quán)和Session

并不是所有的框架都提供了這兩個(gè)機(jī)制的, 因?yàn)橥ㄟ^(guò)cookie和中間件可以很輕松的實(shí)現(xiàn)鑒權(quán)和Session機(jī)制. 很多框架自己提供的也不怎么好用(比如Django), 所以很多人也會(huì)自己去實(shí)現(xiàn)這兩個(gè)機(jī)制, 如果你不知道怎么實(shí)現(xiàn), 我在后面會(huì)有專門(mén)的話題來(lái)詳細(xì)說(shuō)明.

九. 生產(chǎn)部署的方式

開(kāi)發(fā)的Server是頂不住正式上線后的壓力的, 所以要讓你應(yīng)用能夠正式的發(fā)布, 還需要了解如何部署生產(chǎn)環(huán)境.

不同的框架部署的方式也是大不一樣的, 所以這個(gè)要根據(jù)框架文檔來(lái)實(shí)施.

在完成上述9個(gè)步驟的學(xué)習(xí)后, 你就已經(jīng)可以說(shuō)是初步掌握了一個(gè)Web框架了, 還有很多細(xì)節(jié)的東西可以在開(kāi)發(fā)的過(guò)程中逐步的來(lái)補(bǔ)充. 可以說(shuō)上面的內(nèi)容就是一個(gè)Web框架的最小功能集合了, 如果你想自己實(shí)現(xiàn)一個(gè)Web框架的話也可以參考本文, 特別是寫(xiě)文檔的時(shí)候, 現(xiàn)在很多Web框架的文檔寫(xiě)得亂七八糟語(yǔ)焉不詳, 建議參考本文的結(jié)構(gòu)寫(xiě)一個(gè)Quick Guide, 也好讓更多的人體會(huì)到你的精心設(shè)計(jì)了.

現(xiàn)在你可以讓用戶看到頁(yè)面, 也可以收到用戶的請(qǐng)求內(nèi)容, 那么數(shù)據(jù)要如何保存, 如何查詢, 有那些<知識(shí)點(diǎn)>是需要我們掌握的? 所 以

下一章的內(nèi)容是<數(shù)據(jù)庫(kù)以及數(shù)據(jù)訪問(wèn)>

to be continue...

PS: 根據(jù)本文套路寫(xiě)了一個(gè)番外篇, 用一個(gè)實(shí)際框架來(lái)做了個(gè)入門(mén)指南:?實(shí)戰(zhàn):Flask快速入門(mén)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評(píng)論 19 139
  • 22年12月更新:個(gè)人網(wǎng)站關(guān)停,如果仍舊對(duì)舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,399評(píng)論 22 257
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,030評(píng)論 25 709
  • 姓名:潘雪娜 公司:寧波禾隆新材料有限公司 【日精進(jìn)打卡第3天】 【知~學(xué)習(xí)】 《六項(xiàng)精進(jìn)》誦讀1遍 《大學(xué)》1遍...
    潘童鞋89閱讀 172評(píng)論 0 0
  • 因?yàn)閭?cè)睡壓到腿跟手臂,會(huì)麻木的原因,晚上越發(fā)不想睡覺(jué)了。去看那了好幾個(gè)名醫(yī),都沒(méi)法確診癥宅跟對(duì)癥下藥,感覺(jué)身體麻木...
    rosemundq閱讀 267評(píng)論 0 0

友情鏈接更多精彩內(nèi)容