一、Express框架
Express框架是後臺的Node框架,所以和jQuery、zepto、yui、bootstrap都不一個東西。
Express在後臺的受歡迎的程度,和jQuery一樣,就是企業的事實上的標準。
● 原生Node開發,會發現有很多問題。比如:
■ 呈遞靜態頁面很不方便,需要處理每個HTTP請求,還要考慮304問題
■ 路由處理代碼不直觀清晰,需要寫很多正則表達式和字符串函數
■ 不能集中精力寫業務,要考慮很多其他的東西
我們自己可以把第一天的作業,就是那個靜態文件服務給封裝成爲模塊。封裝的越多,就自己做出了類似Express的東西。
● EXPRESS的哲學是在你的想法和服務器之間充當薄薄的一層。這並不意味着他不夠健壯,或者沒有足夠的有用特性,而是儘量少干預你,讓你充分表達自己的思想,同時提供一些有用的東西。
英語官網:http://expressjs.com/
中文官網:http://www.expressjs.com.cn/
整體感知,Express框架。
安裝Express框架,就是使用npm的命令。
1 npm install --save express |
--save參數,表示自動修改package.json文件,自動添加依賴項。
路由能力:
1 var express = require("express"); 2 3 var app = express(); 4 5 app.get("/",function(req,res){ 6 res.send("你好"); 7 }); 8 9 app.get("/haha",function(req,res){ 10 res.send("這是haha頁面,哈哈哈哈哈哈"); 11 }); 12 13 app.get(/^\/student\/([\d]{10})$/,function(req,res){ 14 res.send("學生信息,學號" + req.params[0]); 15 }); 16 17 app.get("/teacher/:gonghao",function(req,res){ 18 res.send("老師信息,工號" + req.params.gonghao); 19 }); 20 21 app.listen(3000); |
靜態文件伺服能力:
1 app.use(express.static("./public")); |
模板引擎:
1 var express = require("express"); 2 3 var app = express(); 4 5 app.set("view engine","ejs"); 6 7 app.get("/",function(req,res){ 8 res.render("haha",{ 9 "news" : ["我是小新聞啊","我也是啊","哈哈哈哈"] 10 }); 11 }); 12 13 app.listen(3000); |
我們學習的是Express4.X,和Express3.X差別非常大。
二、路由
當用get請求訪問一個網址的時候,做什麼事情:
1 app.get("網址",function(req,res){ 2 3 }); |
當用post訪問一個網址的時候,做什麼事情:
1 app.post("網址",function(req,res){ 2 3 }); |
如果想處理這個網址的任何method的請求,那麼寫all
1 app.all("/",function(){ 2 3 }); |
這裏的網址,不分大小寫,也就是說,你路由是
1 app.get("/AAb",function(req,res){ 2 res.send("你好"); 3 }); |
實際上小寫的訪問也行。
所有的GET參數,? 後面的都已經被忽略。錨點#也被忽略
你路由到/a , 實際/a?id=2&sex=nan 也能被處理。
正則表達式可以被使用。正則表達式中,未知部分用圓括號分組,然後可以用req.params[0]、[1]得到。
req.params類數組對象。
1 app.get(/^\/student\/([\d]{10})$/,function(req,res){ 2 res.send("學生信息,學號" + req.params[0]); 3 }); |
冒號是更推薦的寫法。
1 app.get("/student/:id",function(req,res){ 2 var id = req.params["id"]; 3 var reg= /^[\d]{6}$/; //正則驗證 4 if(reg.test(id)){ 5 res.send(id); 6 }else{ 7 res.send("請檢查格式"); 8 } 9 }); |
表單可以自己提交到自己上。
1 app.get("/",function(req,res){ 2 res.render("form"); 3 }); 4 5 app.post("/",function(req,res){ 6 //將數據添加進入數據庫 7 res.send("成功"); 8 }); |
適合進行 RESTful路由設計。簡單說,就是一個路徑,但是http method不同,對這個頁面的使用也不同。
/student/345345
get 讀取學生信息
add 添加學生信息
delete 刪除學生新
三、中間件
如果我的的get、post回調函數中,沒有next參數,那麼就匹配上第一個路由,就不會往下匹配了。
如果想往下匹配的話,那麼需要寫next()
1 app.get("/",function(req,res,next){ 2 console.log("1"); 3 next(); 4 }); 5 6 app.get("/",function(req,res){ 7 console.log("2"); 8 }); |
下面兩個路由,感覺沒有關係:
1 app.get("/:username/:id",function(req,res){ 2 console.log("1"); 3 res.send("用戶信息" + req.params.username); 4 }); 5 6 app.get("/admin/login",function(req,res){ 7 console.log("2"); 8 res.send("管理員登錄"); 9 }); |
但是實際上衝突了,因爲admin可以當做用戶名 login可以當做id。
解決方法1:交換位置。 也就是說,express中所有的路由(中間件)的順序至關重要。
匹配上第一個,就不會往下匹配了。 具體的往上寫,抽象的往下寫。
1 app.get("/admin/login",function(req,res){ 2 console.log("2"); 3 res.send("管理員登錄"); 4 }); 5 6 app.get("/:username/:id",function(req,res){ 7 console.log("1"); 8 res.send("用戶信息" + req.params.username); 9 }); |
解決方法2:
1 app.get("/:username/:id",function(req,res,next){ 2 var username = req.params.username; 3 //檢索數據庫,如果username不存在,那麼next() 4 if(檢索數據庫){ 5 console.log("1"); 6 res.send("用戶信息"); 7 }else{ 8 next(); 9 } 10 }); 11 12 app.get("/admin/login",function(req,res){ 13 console.log("2"); 14 res.send("管理員登錄"); 15 }); |
路由get、post這些東西,就是中間件,中間件講究順序,匹配上第一個之後,就不會往後匹配了。next函數才能夠繼續往後匹配。
app.use()也是一箇中間件。與get、post不同的是,他的網址不是精確匹配的。而是能夠有小文件夾拓展的。
比如網址: http://127.0.0.1:3000/admin/aa/bb/cc/dd
1 app.use("/admin",function(req,res){ 2 res.write(req.originalUrl + "\n"); // /admin/aa/bb/cc/dd 3 res.write(req.baseUrl + "\n"); // /admin 4 res.write(req.path + "\n"); // /aa/bb/cc/dd 5 res.end("你好"); 6 }); |
如果寫一個/
1 //當你不寫路徑的時候,實際上就相當於"/",就是所有網址 2 app.use(function(req,res,next){ 3 console.log(new Date()); 4 next(); 5 }); |
app.use()就給了我們增加一些特定功能的便利場所。
實際上app.use()的東西,基本上都從第三方能得到。
●大多數情況下,渲染內容用res.render(),將會根據views中的模板文件進行渲染。如果不想使用views文件夾,想自己設置文件夾名字,那麼app.set("views","aaaa");
●如果想寫一個快速測試頁,當然可以使用res.send()。這個函數將根據內容,自動幫我們設置了Content-Type頭部和200狀態碼。send()只能用一次,和end一樣。和end不一樣在哪裏?能夠自動設置MIME類型。
●如果想使用不同的狀態碼,可以:
res.status(404).send('Sorry, we cannotfind that!');
●如果想使用不同的Content-Type,可以:
res.set('Content-Type', 'text/html');
四、GET請求和POST請求的參數
● GET請求的參數在URL中,在原生Node中,需要使用url模塊來識別參數字符串。在Express中,不需要使用url模塊了。可以直接使用req.query對象。
● POST請求在express中不能直接獲得,必須使用body-parser模塊。使用後,將可以用req.body得到參數。但是如果表單中含有文件上傳,那麼還是需要使用formidable模塊。
Node中全是回調函數,所以我們自己封裝的函數,裏面如果有異步的方法,比如I/O,那麼就要用回調函數的方法封裝。
錯誤:
1 res.reder("index",{ 2 "name" : student.getDetailById(234234).name 3 }); 4 5 |
正確:
6 7 student.getDetailByXueHao(234234,function(detail){ 8 res.render("index",{ 9 "name" : detail.name 10 }) 11 }); 12 1 |
|