Express框架筆記

暑い….jpg ![ ![WechatIMG61.jpeg](http://upload-images.jianshu.io/upload_images/1552225-887af54c9a68ce75.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ](http://upload-images.jianshu.io/upload_images/1552225-ef382318918f2c1b.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  • 個(gè)人入門(mén)學(xué)習(xí)用筆記、不過(guò)多作為參考依據(jù)。如有錯(cuò)誤歡迎斧正

  • Express框架

  • 路由能力

   const express = require('express');
   
   const app = express();
   //get請(qǐng)求的響應(yīng)
   app.get('/',(req,res) => {
       res.send('你好');
   });
   //post請(qǐng)求的響應(yīng)
   app.post('/haha',(req,res) => {
       res.send('這是haha');
   });
   //所有請(qǐng)求
   app.all('/',(req,res) => {
       res.send('你好');
   });
   //支持正則表達(dá)式(內(nèi)部表示參數(shù)區(qū)分)
   app.get(/^\/student\/([\d]{10})$/,(req,res) =>{
       res.send('學(xué)生信息.學(xué)號(hào):'+req.params[0]);
   });
   
   //:xxxx可以自定義參數(shù)通過(guò).req.params.xxxx提取
   app.get('/teacher/:gonghao',(req,res) => {
       var gonghao;
       gonghao = req.params.gonghao;
       res.send('老師信息.工號(hào):'+gonghao);
   });
   
   app.listen(3000,() =>{
       console.log('監(jiān)聽(tīng)成功');
   });
  • 與模板引擎配合

與原生ejs相比、不需要fs讀取文件、轉(zhuǎn)成字符串、再進(jìn)行替換輸出

   const express = require('express');
   
   const app = express();
   //此處就相當(dāng)于引用了ejs
   app.set('view engine','ejs');
   
   app.get('/',(req,res) => {
       var json = {
           'news':['第一個(gè)','第二個(gè)','第三個(gè)']
       }
       //在工程內(nèi)存在ejs框架的情況下、并不需要引用ejs即可使用模板
       //默認(rèn)讀取文件的路徑為./views/xxx。可以直接簡(jiǎn)寫(xiě)成xxx
       //講haha.ejs文件與json模板配合后、返回替換成功的文件。
       res.render('haha',json);
   });
   
   app.listen(3000);
  • RESTful路由設(shè)計(jì)

  • 讓get、add、post、delete響應(yīng)同一個(gè)url的不同http請(qǐng)求方式。節(jié)約url數(shù)量
  • html通常只發(fā)起get、post。app可能會(huì)出現(xiàn)add、delete請(qǐng)求。
 const express = require('express');
 const app = express();
 
 //設(shè)置模板引擎
 app.set('view engine','ejs');
 
 
 app.get('/',(req,res)=>{
     //直接返回form.ejs解析成html后的文件
     res.render('form');
 });
 
 //post和get共用一個(gè)url
 //節(jié)約了一個(gè)url
 app.post('/',(req,res) =>{
     res.send('成功');
 });
 
 app.listen(3000);
  • 中間件

  • get、post、use等、叫做中間件
  • 中間件執(zhí)行的順序。
自上而下、當(dāng)?shù)谝粋€(gè)路徑匹配成功、默認(rèn)不繼續(xù)尋找(即使第一個(gè)中并沒(méi)有send())。
但我們可以通過(guò)調(diào)用第三個(gè)參數(shù)next()、讓app繼續(xù)向下搜索響應(yīng)。需要注意的是next當(dāng)前函數(shù)下不能以再使用send();
 const express = require('express');
 const app = express();
 //正常情況下、'/:Id'已經(jīng)包含了'/100'所以路由搜索到此為止。
 app.get('/:Id',(req,res,next) => {
     console.log('第一個(gè)get');
     //通過(guò)next、讓app繼續(xù)向下搜索
     next();
 });
 
 app.get('/100',(req,res) => {
     console.log('第二個(gè)get');
     res.send()
 });
 
 app.listen(3000);

use

  • use也是一個(gè)中間件。
  • use就是get與post
  • 與get/post不同。他可以匹配目標(biāo)路徑之后所有的子文件夾。

此示例下、admin/aa/xxx/x/x/x/x/x/是可以被檢索的。
但是admin/bb則不行

 const express = require('express');
 const app = express();
 
 app.use('/admin/aa', function(req, res, next) {
   // GET 'http://www.example.com/admin/aa/new'
   console.log(req.originalUrl); // '/admin/aa/new'
   console.log(req.baseUrl); // '/admin/aa'
   console.log(req.path); // '/new'
   next();
 });
 //當(dāng)不實(shí)現(xiàn)具體路徑的時(shí)候、express會(huì)自動(dòng)匹配所有地址
 app.use((req,res) => {
     res.send('你好');
 });

 app.listen(3000);
  • 靜態(tài)文件伺服
     // 靜態(tài)文件伺服
     const express = require('express');
     const app = express();
     //所有請(qǐng)求全部先檢測(cè)靜態(tài)文件
     app.use(express.static('./public'));
     //只有以/wocao開(kāi)頭的采取讀取靜態(tài)文件
     app.use('/wocao',express.static('./wocao'));
    
     app.get('/hahaha',(req,res) => {
        res.send('hahaha')
     });
     
     app.listen(3000);
    
  • 此時(shí)在瀏覽器中輸入127.0.0.1:3000/xxx.html即可

  • 輸入127.0.0.1:3000/wocao/xxx.html也可

  • 輸入127.0.0.1:3000/hahaha 顯示hahaha(static內(nèi)部有next()機(jī)制)

  • 輸入其他顯示cannot get

  • 在讀取靜態(tài)文件的情況下、如果只輸入文件夾名。會(huì)默認(rèn)讀取該文件夾下的index.html文件

404

  • 把通配符放于最后處理。這樣沒(méi)有經(jīng)過(guò)路由的所有頁(yè)面默認(rèn)由 404.html 來(lái)接管。
 // 404
 app.get('*', function(req, res){
     res.render('404.html', {
         title: 'No Found'
     })
 });

內(nèi)容渲染

  • 大多數(shù)情況下、渲染用res.render()。將會(huì)根據(jù)views中的模板文件進(jìn)行渲染。

  • 如果不想使用views文件夾(比如替換成view2文件夾)

    app.set('views','views2');
    //也可以跨路徑指定(比如指定到上級(jí)的views)
    app.set('views','../views');
    
  • 如果想寫(xiě)一個(gè)快速測(cè)試頁(yè)、當(dāng)然可以使用res.send()。這個(gè)函數(shù)將根據(jù)內(nèi)容、自動(dòng)幫我們?cè)O(shè)置Content-Type頭部和200狀態(tài)碼。

  • send同end一樣只能用一次。
    一般send用于返回json等數(shù)據(jù)。

  • 如果想使用不同的狀態(tài)碼,可以

     res.status(404).send('sorry,web caonnot find that!');
    
  • 如果想使用不同的Content-Type,可以

     res.set('Content-Type','text/html');
    

Get請(qǐng)求處理

express會(huì)自動(dòng)幫我們把參數(shù)轉(zhuǎn)換成json以及數(shù)組.通過(guò)req.query得到

 const express = require('express');
 const app = express();
 
 app.get('*',(req,res) =>{
     console.log(req.query);
     res.send(req.query);
 });
 
 app.listen(3000);

Post請(qǐng)求

  • 文檔推薦使用req.body也就是 body-parse來(lái)處理
    const express = require('express');
    const app = express();
    var bodyParser = require('body-parser');
    
    
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json());
    
    app.set('view engine','ejs');
    
    app.set('views','../views');
    
    app.get('*',(req,res) =>{
        res.render('form');
    });
    
    app.post('/',(req,res) => {
        console.log(req.body);
        res.send(req.body);
    });
    
    app.listen(3000);
    
  • 如果涉及文件上傳、依舊需要使用formidable

res.sendFile

  • 如果你想直接返回一個(gè)文件、比如html。但又不想耽誤用render傳輸模板文件、可以使用這個(gè)
     app.get('/test',(req,res) => {
         res.sendFile(__dirname +'/views/index.html');
     });
    

頁(yè)面綁定參數(shù)

  • ejs本身就是替換模板、所以:
     //最后的404中間件
     app.use('*',(req,res) => {
         res.render('err',{'kirito':'kirito111'});
     });
    
    
     <script>
         var kirito ='<%= kirito%>';
         console.log(kirito)
     </script>
    

重定向

  • 定向回上一頁(yè)
     res.redirect('/');
    
  • 定向到其他路由
     res.redirect('/xxx');
    

Cookie

  • HTTP是無(wú)狀態(tài)協(xié)議。也就是說(shuō)當(dāng)你瀏覽了一個(gè)頁(yè)面、然后轉(zhuǎn)到同一個(gè)網(wǎng)站的另一個(gè)頁(yè)面、服務(wù)器無(wú)法認(rèn)識(shí)到、這是同一臺(tái)計(jì)算機(jī)、同一個(gè)瀏覽器。
  • Cookie是一個(gè)簡(jiǎn)單的想法:當(dāng)訪問(wèn)一個(gè)頁(yè)面的時(shí)候、服務(wù)器在下行HTTP報(bào)文中、命令瀏覽器儲(chǔ)存一個(gè)字符串;瀏覽器再訪問(wèn)同一個(gè)域的時(shí)候、將把這個(gè)字符串?dāng)y帶到上行HTTP請(qǐng)求中。
特點(diǎn):
  • 不加密、用戶可以看到
  • 用戶可以刪除、或者禁用
  • cookie可以被篡改
  • cookie可以用于攻擊
  • cookie的存儲(chǔ)量很小。未來(lái)或許要被localstorage(IE9兼容)取代
express中的Cookie
  • res負(fù)責(zé)設(shè)置cookie

     res.cookie(K&V)
    
  • req負(fù)責(zé)識(shí)別cookie

  • 通過(guò)node設(shè)置cookie

    res.cookie.key
    
    const express = require ('express');
    const app = express();
    //使用cookie必須使用cookie-parser中間件
    const cookieParser = require('cookie-parser');
    
    app.use(cookieParser());
    
    app.get('/',(req,res) => {
        //maxAge在express中以毫秒為單位
        res.cookie('xihao','tfboys',{maxAge:900000,httpOnly:true});
        res.send('cookie='+req.cookies.xihao);
    });
    
    app.listen(3000);
    
  • 下行報(bào)文中

WechatIMG60.jpeg
  • 上行報(bào)文中
WechatIMG61.jpeg

Session

  • 保持登錄狀態(tài)

  • Session從頭至尾依賴(lài)cookie、一旦禁用/清除cookie、sessiion也會(huì)失效

  • Session作為亂碼令牌發(fā)還給用戶。服務(wù)器為令牌存儲(chǔ)具體信息

  • 理論上可以存儲(chǔ)無(wú)線大小的數(shù)據(jù)

     const express = require ('express');
     const app = express();
     
     var session = require('express-session');
     
     app.use(session({
         secret: 'keyboard cat',
         resave: false,
         saveUninitialized: true
     }));
     
     app.get('/login',(req,res) => {
         //設(shè)置session
         req.session.login = '1';
         req.session.username = 'kirito';
         res.send('成功登錄');
     });
     
     app.get('/',(req,res) => {
         if (req.session.login == '1'){
             res.send('歡迎'+req.session.username+'您已成功登錄');
         }else {
             res.send('尚未登錄');
         }
     });
     
     
     app.listen(3000);  
    
  • 需要注意的是
  • 若將服務(wù)器重新啟動(dòng)、訪問(wèn)根目錄。會(huì)顯示未登錄狀態(tài)

  • 因?yàn)閘ogin以及username都緩存在服務(wù)器的express-session模塊內(nèi)

MD5加密

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容