1. 移動APP開發框架盤點2:Web移動前端框架大全
開源項目其實有一個成熟周期,這個周期大概是三年左右,自React框架在2013年發布並引爆了前端框架的大潮,這個屬於前端的周期就此開始了。
之後在2015年5月開源的React Native又開啟了屬於Web移動前端的周期,15-16年,18-19年,21-22年正好就是屬於移動前端的三個爆發點。
三年前,在第一個成熟收獲期,我盤點了移動開發框架。在這第二個成熟收獲期,理所當然要來盤點一波。
不過,當我點開github項目的code-frequency時,還是被這個准到嚇人的周期猜想驚呆了,先給你們看一波,剩下的自行驗證。
1、https://github.com/youzan/vant/graphs/code-frequency
2、https://github.com/quasarframework/quasar/graphs/code-frequency
再來說第二個比較有意思的發現,停止維護的項目絕大多數是Vue框架項目。
盤點開始的時候我還覺得React框架處於絕對劣勢,到完成時我發現React無論在選擇面還是成熟度上都超過了Vue。
原因我這里就不分析了,反正大家都有自己的看法。
網頁類框架就是前端組件框架,這一次雖然有大量項目停止維護,但是也有很多項目堅持了下來,而且還涌現出了一批新項目。
大廠佔了主導,因為這些年大廠在移動開發上的需求,遠高於其它方面。個人項目要堅持確實不易。
本來是想要做一個驗證項目,把所有框架都試用一遍並給出推薦度的。由於進度太慢,還是下一次再發吧。
這次的重點是漸進類框架,就是所謂多端同構框架(小程序框架)。這幾年國內的重點的各種小程序平台,所以多端框架的需求很是旺盛。
不過大多數先行者都沒挺過來還是讓我很意外,只有Taro成功了,想想還是有很多讓人唏噓的東西。
在這里還是先預測一波吧,因為這一類框架最變化最大,最終還是有很多框架要出局的。
漸進類框架是一個過渡性的產品,最終會變成橋接類框架的一部分,所以,與橋接類框架協同才是框架的出路。
這個賽道基本全是大廠了。
騰訊新一代跨端開發框架Hippy
Hippy一看就是淘寶Weex的對標項目,Kpi功能全面壓制。所以官方支持 React 和 Vue 兩種主流前端框架。在Weex2019年實質停更後發布,要不要這么卷?
Hippy 2.x 架構主要分成三層,UI(JS) 層 Hippy-React 和 Hippy-Vue 負責驅動 UI 指令生成;中間層 C++ HippyCore 負責抹平平台差異性和提供高性能模塊;渲染層 Android 和 iOS 負責提供終端底層模塊、組件,並與布局引擎通信。
對Weex慘遭遺棄,我上次就說過:「ReactNative提供工具,Weex提供框架,將平台差異化屏蔽(Write Once, Run Everywhere)。所以Weex則註定功能相對弱小,並且坑比較多。」Weex最終下馬也是必然的,淘寶又發布升級版北海,為了實現(Write Once, Run Everywhere),它採用自繪,而且是基於Flutter自繪。
所以Hippy3.x就一如既往的Kpi功能層層加碼,很有騰訊風格。在未來的 3.x 中業務與渲染層中的具體實現可根據用戶實際場景進行切換:業務層上不再局限於 JS 驅動,還可選擇(如:DSL/Dart/WASM 等)其它語言進行驅動;在渲染層中,渲染引擎除了支持現有原生(Native)渲染之外,還可以選擇其他渲染 Renderer,如 Flutter(Voltron) 渲染。
「Kraken 北海」是一款高性能Web渲染引擎。底層基於 Flutter 進行渲染。
Kraken 不限制上層開發者使用的框架,無論你是使用 Vue 、Rax 還是 React 都可以開發 Kraken 應用。
Kraken 的 runtime 通過 JS Engine Binding 的方式提供了一系列 Web 標準的 API 介面,調用相應 API 會執行相關邏輯並創建一系列需要發送給 Dart 層處理的指令。
Kraken 其實就是一個小程序平台,而且追求全平台完全一致。我雖然認為各平台不一致是很自然的事情,但是也表示理解,畢竟別人吹牛有當真的傳統(KFC表示認同)。
Kraken 現在也是一個小號瀏覽器,所以它的主要工作就是摳標准,畢竟它是一款基於 W3C 標準的高性能渲染引擎。
最後,我勸淘寶領導定Kpi要理智些,畢竟Hippy4我還蠻期待的。
滴滴出品的超輕量級動態化跨端開發框架,主打輕量和實用。
Hummer 以 JS 引擎為基石,目前已支持 JavaScriptCore、Hermers、QuickJS 等業內知名 JS 引擎(這里本來還有個V8的,我刪除了,源碼裡面沒有,Kpi需要)。再配合經過調優的 Yoga 布局引擎,抹平了兩端視圖布局差異(性能更佳的自研布局引擎開發中)。順便提一下,Hippy採用V8(功能更強)自研布局引擎(性能更佳)。
Hummer 的特點是拋棄了業界其他動態化跨端框架普遍使用的DSL層和VDOM層,因此原生 Hummer 不具備前端開發常用的響應式編程的能力,但同時換來的是接近原生開發的體驗和性能。再以原生 Hummer 為基礎,在此之上開發了一套基於MVVM架構的開發框架 —— Tenon ,通過 Tenon,可以把使用 Vue/React 編寫的代碼,轉換成原生 Hummer 的代碼。
Hummer也是一個小程序平台,而且超輕量。如果想要無限提升自己APP的能力,可以考慮嵌入Hummer。
Web移動前端框架正在迎來第三個高速發展期,各類框架得到極大繁榮。
個人在具體項目的貢獻已經微乎其微了,創新、架構創新是唯一制勝的手段,這也是我看好React的根本原因。
最後,還是想做點微不足道的 探索 ,現在前端組件庫層出不窮,更換組件庫帶來的代價有點大。想創建一個框架,來實現上次說的組件公約數和公倍數,無縫切換組件庫。理論上支持所有組件庫 ,也能為後來者提供彎道超車的機會。我想大廠可能沒有需求,也不會願意發布這種框架,畢竟都是平台部門說了算。
這個庫就是useMobile,當然分為useMobileReact和useMobileVue。下次先發布useMobileReact。等我發布後,再來填上面表中缺的推薦度。
原文地址: https://www.cnblogs.com/windfic/p/16019457.html
2. 如何開發一個Python web框架
首先你需要知道一個Web應用基本的請求處理流程。以最簡單最原始的動態網頁為例,你點擊鏈接(GET),提交表單(POST),就是與伺服器端建立了連接之後發送了一個HTTP請求(RFC2616 5.1節,之後都以HTTP 1.1為例),裡面至少有方法(動詞,就是GET啦POST什麼的,詳見RFC2616第9節),地址(URL),HTTP版本,還可能帶上Cookie(會話的一般實現機制),緩存相關的信息(RFC2616 13節),User-Agent串等等一堆信息。對於POST請求我們還有表單內容作為請求實體(RFC2616 7.2節),裡面是你填寫的表單內容。
於是我們有了一些關於請求的數據,不過現在一般來講這些數據還在前端伺服器(反向代理,比如nginx,暫且忽略掉負載均衡,反正是透明的,也不考慮裸WSGI容器直接扛請求的情況)的手上,還沒有傳進後端語言(這里是Python)。我們就針對每一種語言都有特定的機制,用來將HTTP的請求信息映射到相應的編程語言范疇,叫做Web伺服器界面(Web server interface),通用如CGI/FCGI/SCGI,特定於某一語言如WSGI/PSGI/Rack/...,特定於某一操作系統如ISAPI(這貨還活著?),一些已經不再使用的就不提了。總之在Python世界裡這就是WSGI(PEP 3333, Web Server Gateway Interface),它就定義了Python語言與Web伺服器之間的界面。在WSGI里,
請求的處理過程被映射為對應用callable的調用(application(environ, start_response),知乎不支持inline代碼塊?);
請求信息被映射到environ字典中的相應鍵值,比如請求方法被映射到environ['REQUEST_METHOD'],請求的「相對路徑」被映射到environ['PATH_INFO'](過度簡化;暫且不提WSGI應用掛載點,框架層一般也不用關心這個,掛載WSGI應用一般是WSGI容器如gunicorn、uWSGI之類組件的工作);
發送響應頭的動作被映射到調用start_response(status, response_headers)(不考慮可選的第三個參數異常信息);
返回響應數據被映射到application返回iterable的動作。
於是響應便從Python返回到Web伺服器,再被發送回瀏覽器,瀏覽器將響應內容渲染,一個請求就完成啦。
有了這樣的感性認識,那麼我們作為Python Web開發框架的作者,要做的事情就是在WSGI規范的基礎之上,提供盡可能便捷的開發手段和盡可能低的框架開銷,也即我們的代碼將要工作在WSGI與業務邏輯的中間層。架構上,Web開發框架或多或少都遵循MVC的設計模式(Django管它叫MTV,其實差不多)。同時,由於框架位於中間件的位置,加上其鼓勵模塊化與代碼復用的性質,自然需要為常見的HTTP操作提供抽象。這里就可以展開一些話題:
請求路徑到view/controller的映射,請求參數的解析(routing,也叫路由)。
正則匹配的方案,比如Django內置了一個簡單的正則表達式解析組件,能解析一般常見語法的正則表達式,把capturing groups解析成位置參數,named capturing groups解析成關鍵字參數。
也有DSL的方案,比如Werkzeug的路由組件。
請求實體的處理。表單解析,配合Web伺服器進行上傳文件處理。
正常的urlencoded表單,JSON表單,text/plain數據,multi-part表單
multi-part附件,附件操作API
大文件上傳(這個一般會被前端伺服器保存在磁碟上的臨時文件里,比方說nginx就是這么實現的)。
會話。HTTP是無狀態(stateless)的,這個特點非常重要。如果沒有會話,你連續做幾個請求,卻沒有手段證明你們是同一個人/同一台機器(你完全可能是代理伺服器)。
存儲會話數據的會話後端(內存數據結構?文件?RDBMS?Redis?Memcache?)
安全機制(HMAC什麼的,可以參考beaker的secure cookie實現)
請求處理流程中的會話中間件(從Cookie中提取會話,從query string中提取會話,從自定義頭中提取會話,等等)
View/Controller界面。發揮你的創造力,用上你的工程經驗。
Function-based or Class-based views? 參考:Django, Bottle, web.py, Tornado等一票框架的做法
框架的可選機制與服務如何暴露,
裝飾器?(比如@login_required 這種額外要求)
回調?(能想到的只有Tornado和Twisted這種非同步框架做事情的方式,還有整個JS生態系統都是回調(不考慮Promise什麼的)的思路)
傳入應用(業務邏輯)層的數據結構如何設計?(HttpRequest等價物,名字可能記不清了)
響應數據結構如何設計?(HttpResponse等價物,同上)
資料庫操作封裝。Web應用基本都是數據為中心,這個組件非常有必要,也是撰寫可復用代碼必須的一環,畢竟光是框架抽象了,資料庫操作還是裸sql什麼的,到時候生產環境一換(比如MySQL變pgsql)還不是傻眼。
關系型資料庫。一站式解決方案參考:Django ORM、SQLAlchemy;輕量級解決方案參考各資料庫Python綁定。
非關系資料庫。各資料庫Python綁定(pymongo, riak, redis-py之類),這個沒什麼可替代方案了,因為本來各種NoSQL庫都是適應某一特殊需求設計的,沒什麼互相替換的必要,那意味著重新進行技術選型。
3. 這五個Web前端開發必不可少的開源框架,閉眼入
很多Web小白在學習、在選擇適合自己的Web語言時,比較糾結。其實有很多流行的、強大的前端開源框架,幫助你輕松構建漂亮的網站前端。
1、Pure
Bootstrap,Patternfly和MDC Web是功能非常強大的CSS框架,但它們可能非常繁瑣和復雜。如果你想要一個輕量級的CSS框架,可以嘗試Pure.css,它本身更接近於CSS編程,但又可以幫助你構建一個不錯的網頁。Pure是具有最小佔用空間的輕量級CSS框架,它由Yahoo開發,根據BSD許可是開源的。
2、Foundation
Foundation聲稱是世界上最先進的響應式前端框架。它提供了用於構建專業網站的高級功能和教程。許多公司,組織都使用該框架,並且該框架具有大量可用的文檔。
3、Skeleton
如果說還有什麼框架比Pure更加輕量級,那一定是Skeleton。Skeleton庫只有大約400行,並且該框架僅提供一些基本的CSS框架組件。盡管如此,Skeleton還是提供了詳細的文檔來幫助你快速上手。
4、Materialize
Materialize是一個基於Material Design風格的一個現代化的響應式前端框架,解決了最繁重的工作,結合你的自定義組件,為你提供默認的樣式。Materialize的文檔頁面非常全面,並且很容易遵循。其組件頁麵包括按鈕,卡片,導航等。
5、Bootstrap
Bootstrap無疑是最流行的CSS框架,它是最早的Web前端框架,由Twitter開發。Bootstrap還提供了許多示例來幫助你入門。使用Bootstrap,你可以將不同的組件和布局組合在一起,從而創建有趣的頁面設計。它還提供了大量詳細的文檔。目前在Github上已經有1100多個貢獻者,19000多個提交。
4. 用python做個簡單web介面選什麼框架最簡單
用python做個簡單web介面選什麼框架最簡單
不是很清楚。
只是知道用django的比較多。
以下資料供參考:
我整理的:
【整理】Python中常見的Web框架
我折騰django的:
【記錄】安裝Django
【記錄】基於通過pip安裝官網Django後,折騰第一個Django的app
【記錄】基於通過pip安裝官網Django後,折騰第二個Django的app
要自己寫框架,首先你要知道web框架都需要哪些,你可以看一下框架原始碼,或者參與到框架開源開發中。如果你要自己看原始碼,推薦看bottle.py,這個python的web框架只有一個檔案,很方便。如果你要參與專案,推薦django,大而全,github上的原始碼很多人在做支援。如果解決了您的問題請採納!如果未解決請繼續追問!
python網站框架哪個簡單
Flask 很輕,花很少的成本就能夠開發一個簡單的網站。非常適合初學者學習。
Flask 框架學會以後,可以考慮學習外掛的使用。例如使用 WTForm + Flask-WTForm 來驗證表單資料,用 SQLAlchemy + Flask-SQLAlchemy 來對你的資料庫進行控制。
榮耀6p怎麼安裝xp框架最簡單
華為手機使用的是自身定製的安卓系統。
在安裝框架的過程中可能會產生各種問題。
建議使用刷機精靈,將手機系統刷至安卓原生系統。
然後安裝例如XP框架,執行更為穩定。
什麼銀行的網銀介面最簡單?
工商銀行是最常用,網銀介面比較簡單,但是如果跨行轉賬匯款的話手續費比較高。招商銀行的網銀頁面也不錯。這都是日常使用過程中個人覺得比較簡單好用的。
javaweb三大框架中,哪種最簡單,你覺得?
Struts相對來說簡單些。
因為Strusts只操作與Serlvert,不關繫到別的(有些牽強,但是他對於表示式,國際化,都是在使用者體驗上,也都是與Servlet打交道)。就算是Strusts2X,也是使用攔截器攔截使用者的請求,作用到servlet。
但是Spring所設計的東西和層面太多,而且都是微型的、切面的程式設計,配置檔案和核心對於基礎較差的還是很有難度的,尤其是初學者。
Hibernate的使用,要對資料庫要相對很熟悉,尤其是資料庫的理論方面,而且,Hibernate的配置需要資料的基礎好,但是學好了Hibernate的話,對於程式設計有很大的好處
求個最簡單易用的PHP框架,不用太多的功能,適合新手的,最簡單的。
thinkphp輕量級框架,企業網站的經典運用
thinkphp是最簡單的框架了,如果的的網站實在小就不用框架會更快做好,因為它也是MVC架構,而MVC就是為了方便快速開發大型網站的
5. 如何開發自己的web框架
Python 10min系列之面試題解析丨Python實現tail -f功能
發布時間:2018-02-28 來源:網路 上傳者:用戶
關鍵字:Python題解面試實現功能系列10mintail
發表文章
摘要:寫這篇文章的初衷是有人去面試遇到了這個筆試題,不知道怎麼做,沒有什麼思路,就發到了Reboot的交流群里,讓大家一起討論討論。關於這道題,簡單說一下我的想法吧。當然,也有很好用的pyinotify模塊專門監聽文件變化,不過我更想介紹的,是解決的思路。畢竟作為面試官,還是想看到一下解決問題的思路,而且我覺得這一題的難點不在於監控文件增量,而在於怎麼列印最後面10行。希望大家在讀這篇文章前,對Python基礎、處理文件和常用模塊有一個簡單的了解,知道下面幾個名詞是什麼:open(
代碼說明:
seek第二個參數2,意思就是從文件結尾處開始seek,更標準的寫法使用os模塊下面的SEEK_END,可讀性更好
只寫出了簡單的邏輯,代碼簡單粗暴,如果這個題目是10分的話,最多也就拿4分吧,不能再多了
優化點:
print有缺陷,每次都是新的一行,換成sys.stdout.write(line)更和諧
文件名傳參,不能寫死
直接列印可以當成默認行為,具體要做什麼,可以寫成函數處理,這樣我們就可以把新行做其他處理,比如展示在瀏覽器里
加上容錯處理,比如文件不存在會報錯
while True一直都文件,比較耗性能,每讀一次,間隔一秒比較靠譜
調用time.sleep(1)
用類來組織代碼
實例代碼如下:
# coding=utf-8
import sys
import time
class Tail():
def __init__(self,file_name,callback=sys.stdout.write):
self.file_name = file_name
self.callback = callback
def follow(self):
try:
with open(self.file_name) as f:
f.seek(0,2)
while True:
line = f.readline()
if line:
self.callback(line)
time.sleep(1)
except Exception,e:
6. 誰可以教教我如何搭建一個java web框架
1,在MyEclipse新建出來的web project就是一個web項目,
2,假如你想使用別的開源框架,你開以下載相關jar包,比如可以下載Struts,hibernate和Spring的jar包,將jar包導入到項目中,最後配置xml文件,就是SSH項目了,
7. 如何用Node去寫一個Web應用框架
第一步,用node輸出一個hello world
varhttp=require('http');
http.createServer(function(req,res){
varurlPares=url.parse(req.url);
varquery=querystring.parse(urlPares.query);
res.end('helloworld');
}).listen(80);
大部分的node教程在這里會告訴你,我們很容易的建立的一個伺服器。但是在實際使我們通常使用的是express.(f**k,難道Node必須要用express嗎?自己實現一個Web應用框架真的很難嗎?)其實並不是。
那麼既然打算自己寫我們首先要知道我們要做哪些事情。 1.路由或者智能路由 2.靜態文件輸出 3.session/cookie 4.模版渲染 5.資料庫處理 6.文件上傳
第二步,路由
路由好高大上的名字,它是幹啥的?url對應具體方法就是它該做的事情。 那麼我們為什麼不讓url對應xxx文件的xx方法。 例如:/user/login能不能自動對應到user.js的login方法上。實現起來很難么?其實只需要幾句代碼
varfs=require("fs");
mole.exports=function(req,res){
varquery=req.query;
varurlPares=req.urlPares;
varpathname=urlPares.pathname;
vararr=pathname.split("/");
req.arr=arr;
//start這段代碼處理默認行為。可以先忽略
if(arr.length==0||arr.length==1){
arr=["","index","index"];
}elseif(arr.length==2){
arr.push("index");
}
if(arr[1]==""){
arr[1]="index";
}
if(arr[2]==""){
arr[2]="index";
}
//end這段代碼處理默認行為。可以先忽略
if(fs.existsSync(APP_PATH+'/controller/'+arr[1]+'.js')){
varcontroller=require('./controller/'+arr[1]);
if(controller[arr[2]]){
controller[arr[2]](req,res);
}else{
res.writeHead(404,{'Content-Type':'text/plain'});
res.end("你訪問的控制器不存在指定方法");
}
}else{
res.writeHead(404,{'Content-Type':'text/plain'});
res.end("你訪問的路徑不存在");
}
}
通過fs判斷文件是否存在。然後去require它就行了。APP_PATH是個全局變數表示程序入口的路徑。
第三步,靜態文件輸出
靜態文件輸出我們需要一個庫MIME
varurl=require("url");
varfs=require("fs");
varmime=require('mime');
/**
*[[檢測是否為靜態資源]]
*@param{Object}req[[Description]]
*@param{[[Type]]}res[[Description]]
*@returns{bool}[[Description]]
*/
mole.exports=function(req,res){
//正則表達式檢測文件後綴
varurl_resource_reg=/.*.(html|htm|gif|jpg|jpeg|bmp|webp|htc|swf|png|ico|txt|js|css)/;
if(!url_resource_reg.test(req.url)){
returnfalse;
}
varurlPares=url.parse(req.url);
varpathname=urlPares.pathname;
varfileUrl=APP_PATH+"/static"+pathname;
if(fs.existsSync(fileUrl)){
varcontentType=mime.lookup(fileUrl);
res.setHeader('Content-Type',contentType||"text/plain");
varfileStream=fs.createReadStream(fileUrl);
fileStream.pipe(res);
fileStream.on('end',function(){
res.end();
});
returntrue;
}else{
returnfalse;
}
}
第四步,session/cookie
這里稍微有點。但是代碼量也不多
varsessions={};
varsessionKey='session_key';
varEXPIRES=30*60*1000;
functionrandString(size){
varresult='';
varallChar='';
size=size||1;
while(size--){
result+=allChar.charAt(rand(0,allChar.length-1));
}
returnresult;
}
vargenerate=function(){
varsession={};
session.id=Date.now()+randString(12);
session.cookies={
expire:Date.now()+EXPIRES
}
sessions[session.id]=session;
returnsession;
}
varparseCookie=function(cookie){
varcookies={};
if(!cookie){
returncookies;
}
varlist=cookie.split(";");
for(vari=0;i<list.length;i++){
varpair=list[i].split("=");
cookies[pair[0].trim()]=pair[1];
}
returncookies;
}
varserializeCookies=function(cookies){
vararr=[];
for(varkeyincookies){
arr.push(serialize(key,cookies[key]));
}
returnarr;
}
varserialize=function(name,value,option){
varpairs=[name+'='+encodeURI(value)];
//設置cookie默認共用"/"路徑
option=option||{
path:"/"
};
if(option.maxAge)pairs.push('Max-Age='+option.maxAge);
if(option.domain)pairs.push('Domain='+option.domain);
if(option.path)pairs.push('Path='+option.path);
if(option.expires)pairs.push('Expires='+option.expires);
if(option.httpOnly)pairs.push('HttpOnly');
if(option.secure)pairs.push('Secure');
returnpairs.join(';');
}
mole.exports=function(req,res){
req.cookies=parseCookie(req.headers.cookie);
varid=req.cookies[sessionKey];
if(!id){
req.session=generate();
}else{
varsession=sessions[id];
if(session){
if(session.cookies.expire>Date.now()){
session.cookies.expire=Date.now()+EXPIRES;
req.session=session;
}else{
deletesessions[id];
req.session=generate();
}
}else{
req.session=generate();
}
}
for(varkeyinsessions){
if(sessions[key].cookies.expire<Date.now()){
deletesessions[key];
}
}
varwriteHead=res.writeHead;
res.writeHead=function(){
deletereq.cookies[ham_sessionKey];
varsessionStr=serialize(ham_sessionKey,req.session.id);
res.setHeader('Set-Cookie',serializeCookies(req.cookies).concat(sessionStr));
returnwriteHead.apply(res,arguments);
}
}
第五步,模版渲染
這是最簡單的。
第六步,資料庫處理
這里可以是用一些ORM框架。
第七步,文件上傳,post
第八步,就是你把上面的代碼組織起來。
8. 如何開發一個Python web框架
預備知識
web框架主要是實現web伺服器和web應用之間的交互。底層的網路協議主要有web伺服器完成。譬如監聽埠,填充報文等等。
Python內建函數__iter__和__call__和WSGI
迭代器iterator
為類序列對象提供了類序列的介面,也就是說類序列對象可以通過迭代器像序列一樣進行迭代。
__call__
在類定義的時候實現了__call__方法,那麼該類的對象就是可調有的,即可以將對象當做函數來使用。
WSGI
用可調用的對象實現的:一個函數,一個方法或者一個可調用的實例。
9. 純 Python 寫一個 Web 框架,就是這么簡單
造輪子是最好的一種學習方式,本文嘗試從0開始造個Python Web框架的輪子,我稱它為 ToyWebF 。
本文操作環境為:MacOS,文中涉及的命令,請根據自己的系統進行替換。
ToyWebF的簡單特性:
下面我們來實現這些特性。
首先,我們需要安裝gunicorn,回憶一下Flask框架,該框架有內置的Web伺服器,但不穩定,所以上線時通常會替換成uWSGI或gunicorn,這里不搞這個內置Web服務,直接使用gunicorn。
我們創建新的目錄與Python虛擬環境,在該虛擬環境中安裝gunicorn
在啥都沒有的情況下,構建最簡單的Web服務,在ToyWebF目錄下,創建app.py與api.py文件,寫入下面代碼。
運行 gunicorn app:app 訪問 http://127.0.0.1:8000 ,可以看見 Hello, World! ,但現在請求體中的參數在environ變數中,難以解析,我們返回的response也是bytes形式。
我們可以使用webob庫,將environ中的數據轉為Request對象,將需要返回的數據轉為Response對象,處理起來更加直觀方便,直接通過pip安裝一下。
然後修改一下API類的 __call__方法 ,代碼如下。
上述代碼中,通過webob庫的Request類將environ對象(請求的環境信息)轉為容易處理的request,隨後調用handle_request方法對request進行處理,處理的結果,通過response對象返回。
handle_request方法在ToyWebF中非常重要,它會匹配出某個路由對應的處理方法,然後調用該方法處理請求並將處理的結果返回,在解析handle_request前,需要先討論路由注冊實現,代碼如下。
其實就是將路由和方法存到self.routes字典中,可以通過route裝飾器的形式將路由和方法關聯,也可以通過add_route方法關聯,在app.py中使用一下。
因為url中可以存在變數,如 @app.route("/hello/{name}") ,所以在匹配時,需要進行解析,可以使用正則匹配的方式進行匹配,parse這個第三方庫已經幫我們實現了相應的正則匹配邏輯,pip安裝使用一下則可。
這里定義find_handler方法來實現對self.routes的遍歷。
了解了路由與方法關聯的原理後,就可以實現handle_request方法,該方法主要的路徑就是根據路由調度對應的方法,代碼如下。
在該方法中,首先實例化webob庫的Response對象,然後通過self.find_handler方法獲取此次請求路由對應的方法和對應的參數,比如。
它將返回hello方法對象和name參數,如果是 /hello/二兩 ,那麼name就是二兩。
因為route裝飾器可能裝飾器的類對象,比如。
此時self.find_handler方法返回的hanler就是個類,但我們希望調用的是類中的get、post、delete等方法,所以需要一個簡單的判斷邏輯,通過inspect.isclass方法判斷handler如果是類對象,那麼就通過getattr方法獲取類對象實例的中對應的請求方法。
如果類對象中沒有該方法屬性,則拋出該請求類型不被允許的錯誤,如果不是類對象或類對象中存在該方法屬性,則直接調用則可。
此外,如果方法的路由並沒有注冊到self.routes中,即404的情況,定義了defalut_response方法返回其中內容,代碼如下。
如果handle_request方法中調度的過程出現問題,則直接raise將錯誤拋出。
至此,一個最簡單的web服務就編寫完成了。
回顧Flask,Flask可以支持HTML、CSS、JavaScript等靜態文件,利用模板語言,可以構建出簡單但美觀的Web應用,我們讓TopWebF也支持這一功能,最終實現圖中的網站,完美兼容靜態文件。
Flask使用了jinja2作為其html模板引擎,ToyWebF同樣使用jinja2,jinja2其實實現一種簡單的DSL(領域內語言),讓我們可以在HTML中通過特殊的語法改變HTML的結構,該項目非常值得研究學習。
首先 pip install jinja2 ,然後就可以使用它了,在ToyWebF項目目錄中創建templates目錄,以該目錄作為默認的HTML文件根目錄,代碼如下。
首先利用jinja2的FileSystemLoader類將file system中的某個文件夾作為loader,然後初始化Environment。
在使用的過程中(即調用template方法),通過get_template方法獲得具體的某個模板並通過render方法將對應的內容傳遞給模板中的變數。
這里我們不寫前端代碼,直接去互聯網中下載模板,這里下載了Bootstrap提供的免費模板,可以自行去 https://startbootstrap.com/themes/freelancer/ 下載,下載完後,你會獲得index.html以及對應的css、jss、img等文件,將index.html移動到ToyWebF/templates中並簡單修改了一下,添加一些變數。
然後在app.py文件中為index.html定義路由以及需要的參數。
至此html文件的支持就完成了,但此時的html無法正常載入css和js,導致頁面布局非常醜陋且交互無法使用。
接著就讓ToyWebF支持css、js,首先在ToyWebF目錄下創建static文件夾用於存放css、js或img等靜態文件,隨後直接將前面下載的模板,其中的靜態文件復制到static中則可。
通過whitenoise第三方庫,可以通過簡單的幾行代碼讓web框架支持css和js,不需要依賴nginx等服務,首先 pip install whitenoise ,隨後修改API類的 __init__ 方法,代碼如下。
其實就是通過WhiteNoise將self.wsgi_app方法包裹起來,在調用API的 __call__ 方法時,直接調用self.whitenoise。
此時,如果請求web服務獲取css、js等靜態資源,WhiteNoise會獲取其內容並返回給client,它在背後會匹配靜態資源在系統中對應的文件並將其讀取返回。
至此,一開始的網頁效果就實現好了。
web服務如果出現500時,默認會返回 internal server error ,這顯得比較丑,為了讓框架使用者可以自定義500時返回的錯誤,需要添加一些代碼。
首先API初始化時,初始self.exception_handler對象並定義對應的方法添加自定義的錯誤
在handler_request方法進行請求調度時,調度的方法執行邏輯時報500,此時不再默認將錯誤拋出,而是先判斷是否有自定義錯誤處理。
在app.py中,自定義錯誤返回方法,如下。
custom_exception_handler方法只返回自定義的一段話,你完全可以替換成美觀的template。
我們可以實驗性定義一個路由來看效果。
Web服務的中間件也可以理解成鉤子,即在請求前可以對請求做一些處理或者返回Response前對Response做一下處理。
為了支持中間件,在TopWebF目錄下創建middleware.py文件,在編寫代碼前,思考一下如何實現?
回顧一下現在請求的調度邏輯。
1.通過routes裝飾器關聯路由和方法 2.通過API.whitenoise處理 3.如果是請求API介面,那麼會將參數傳遞給API.wsgi_app 4.API.wsgi_app最終會調用API.handle_request方法獲取路由對應的方法並調用該方法執行相應的邏輯
如果希望在request前以及response後做相應的操作,那麼其實就需要讓邏輯在API.handle_request前後執行,看一下代碼。
其中add方法會實例化Middleware對象,該對象會將當前的API類實例包裹起來。
Middleware.handle_request方法其實就是在self.app.handle_request前調用self.process_request方法處理request前的數據以及調用self.process_response處理response後的數據,而核心的調度邏輯,依舊交由API.handle_request方法進行處理。
這里的代碼可能會讓人感到疑惑, __call__ 方法和handle_request方法中都有self.app.handle_request(request),但其調用對象似乎不同?這個問題暫時放一下,先繼續完善代碼,然後再回來解釋。
接著在api.py中為API創建middleware屬性以及添加新中間件的方法。
隨後,在app.py中,自定義一個簡單的中間件,然後調用add_middleware方法將其添加。
定義好中間件後,在請求調度時,就需要使用中間件,為了兼容靜態文件的情況,需要對css、js、ing文件的請求路徑做一下兼容,在其路徑中加上/static前綴
緊接著,修改API的 __call__ ,兼容中間件和靜態文件,代碼如下。
至此,中間件的邏輯就完成了。
但代碼中依舊有疑惑,Middleware類中的 __call__ 方法和handle_request方法其調用的self.app到底是誰?
為了方便理解,這里一步步拆解。
如果沒有添加新的中間件,那麼請求的調度邏輯如下。
在沒有添加中間件的情況下,self.app其實就是API本身,所以 middleware.__call__ 中的self.app.handle_request就是調用API.handle_request。
如果添加了新的中間件,如上述代碼中添加了名為SimpleCustomMiddleware的中間件,此時的請求調度邏輯如下。
因為注冊中間件時,Middleware.add方法替換了原始Middleware實例中的app對象,將其替換成了SimpleCustomMiddleware,而SimpleCustomMiddleware也有app對象,SimpleCustomMiddleware中的app對象,才是API類實例。
在請求調度的過程中,就會觸發Middleware類的handle_request方法,該方法就會執行中間件相應的邏輯去處理request和response中的數據。
當然,你可以通過Middleware.add方法添加多個中間件,這就會構成棧式調用的效果,代碼如下。
啟動web服務後,其執行效果如下。
10. web前端開發框架有哪些
常見的web前端開發框架如下:
1、Bootstrap:
主流框架之一,Bootstrap 是基於 HTML、CSS、JavaScript的,它簡潔靈活,使得 Web 開發更加快捷。
2、html5-boilerplate:
該框架可以快速構建健壯,且適應力強的web app或網站。
3、Meteor:
Meteor是新一代的開發即時web應用的開源框架,它能在較短時間內完成開發。
4、Materialize:
基於材料設計的現代化響應式前端框架。可提供默認的樣式,自定義組件。此外,Materialize還改進動畫和過渡,為開發人員提供流暢的體驗。
5、Amaze UI:
國內首個開源HTML5跨屏前端框架產品系列,中文排版支持更優、本土化組件豐富。該產品系列中有專門針對移動端的HTML5混合應用開發框架Amaze UI Touch以及針對跨屏HTML5網頁開發的Amaze UI Web。
(10)創建自己web框架擴展閱讀:
web框架程序的作用:
Web框架使得在進行Web應用開發的時候,減少了工作量。Web框架主要用於動態網路開發,動態網路主要是指現在的主要的頁面,可以實現數據的交互和業務功能的完善。
使用Web框架進行Web開發的時候,在進行數據緩存、資料庫訪問、數據安全校驗等方面,不需要自己再重新實現,而是將業務邏輯相關的代碼寫入框架就可以。也就是說,通過對Web框架進行主觀上的「縫縫補補」,就可以實現自己進行Web開發的需求了。
以PHP為例,PHP可以在apache伺服器上進行Web開發,而不必使用框架。使用PHP進行開的時候,在不適用框架的情況下,資料庫連接就需要自己來實現,頁面的生成和顯示也是一樣。比如框架的話可以完成避免sql注入的工作,而使用PHP在不用框架的情況下,這部分要自己做。
參考資料來源:網路-前端開發