第三天node.js,路由與中間件及 項目的搭建


一、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            

 

 

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