modeJS 深了解(1): Node.js + Express 構建網站預備知識


轉載:http://www.cnblogs.com/zhongweiv/p/nodejs_express_webapp1.html

目錄

前言

 經過學習Node.js,基本可以開始動手構建一個網站應用了,先用這一篇了解一些構建網站的知識!

 主要是些基礎的東西,這里我們說下 express 項目分析...

 先從app.js看起

  • app.set(name,value)

  把名字為name的項的值設為value,用於設置參數

  app.set('views', path.join(__dirname, 'views'));   設置了模版文件夾的路徑;主要清楚__dirname的意思就可以了,它是node.js中的全局變量,表示取當前執行文件的路徑

  app.set('view engine', 'ejs');  設置使用的模版引擎,我們使用的ejs

  • app.use([path], function)

     用這個方法來使用中間件,因為express依賴於connect,有大量的中間件,可以通過app.use來使用;path參數可以不填,默認為'/'  (項目中用到的就不分別解釋了,用到的時候自已查一API的中間件部分)

  app.use(express.static(path.join(__dirname, 'public'))); 這一句中可能要注意一下,express.static( )是處理靜態請求的,設置了public文件,public下所有文件都會以靜態資料文件形式返回(如樣式、腳本、圖片素材等文件)

var routes = require('./routes/index');
var users = require('./routes/users');

app.use('/', routes);
app.use('/users', users);

  上面代碼表示當用戶使用/訪問時,調用routes,即routes目錄下的index.js文件,其中.js后綴省略,用/users訪問時,調用routes目錄下users.js文件

  這就是為什么,我們示例中用http://localhost:8100/訪問是,修改的index.js里的文件代碼可以執行(當然index.js文件中也要寫對應的代碼,才能是我們最終看到的效果)

  • app.get(name)

  獲取名為name的項的值

復制代碼
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}
復制代碼

  表示如果是開發環境,處理error時會輸出堆棧信息

  • 路由文件index.js

  主要看下面這段代碼

復制代碼
router.get('/', function(req, res) {
  res.render('index', { title: '<h1>Express</h1>'
                          ,users:[{username: 'Wilson'},
                                {username: 'Wilson Zhong'},
                                {username: 'Zhong Wei'}] 
            });
});
復制代碼

  這段表示,router.get表示通過get請求/時,響應后面的function處理,兩個參數分別是request、response;

  res.render表示調用模版引擎,解析名字index的模板,傳並傳入了title和users兩個對象做為參數;

  為什么它會知道解板views目錄下的index.ejs?而不是其它目錄下的文件,或者后其它后綴名的文件?

  原因就是app.js中的設置

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

  而這兩個參數在index.ejs中可以使用,那么加上ejs的部分,就會返回最終生成的頁面展現!

 

  如何去創建路由規則、如何去提交表單並接收表單項的值、如何去給密碼加密、如何去提取頁面公共部分(相當於用戶控件和母版頁)等等...

  下面就一步步開始吧^_^!...

新建express項目並自定義路由規則

  • 首先用命令行express+ejs創建一個項目sampleEjsPre
cd 工作目錄
express -e sampleEjsPre
cd sampleEjsPre && npm install
  • 默認會有routes目錄下會有index.js和users.js文件,這里為了不產生其它示例外的困擾,刪除user.js文件
  • 打開app.js文件刪除下面兩行代碼
var users = require('./routes/users');

...

app.use('/users', users);

 

  • 在routes目錄下添加subform.js、usesession.js、usecookies.js、usecrypto.js文件,並在對應的js文件中添加如下代碼
    var express = require('express');
    var router = express.Router();
    
    /* GET home page. */
    router.get('/', function(req, res) {
      res.render('subform', { title: '提交表單及接收參數示例' });
    });
    
    module.exports = router;
    
    subform.js 代碼
    subform.js
    var express = require('express');
    var router = express.Router();
    
    /* GET home page. */
    router.get('/', function(req, res) {
      res.render('usesession', { title: '使用session示例' });
    });
    
    module.exports = router;
    
    usesession.js 代碼
    usesession.js
    var express = require('express');
    var router = express.Router();
    
    router.get('/', function(req, res) {
      res.render('usecookies', { title: '使用cookies示例' });
    });
    
    module.exports = router;
    
    usecookies.js 代碼
    usecookies.js
    var express = require('express');
    var router = express.Router();
    
    router.get('/', function(req, res) {
      res.render('usecrypto', { title: '加密字符串示例' });
    });
    
    module.exports = router;
    
    usecrypto.js 代碼
    usecrypto.js
  • 在views目錄下添加subform.ejs、usesession.ejs、usecookies.ejs、usecrypto.ejs文件,並在views目錄下除了error.ejs外所有ejs文件中添加如下代碼
復制代碼
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>     
    <a href="/">首頁</a>     
    <a href="/subform">如何提交表單並接收參數?</a>
    <a href="/usesession">如何使用session?</a>
    <a href="/usecookies">如何使用cookies?</a>
    <a href="/usecrypto">如何字符串加密?</a>
  </body>
</html>
復制代碼
  • 在app.js文件中添加如下代碼
  • 復制代碼
    var subform = require('./routes/subform');
    var usesession = require('./routes/usesession');
    var usecookies = require('./routes/usecookies');
    var usecrypto = require('./routes/usecrypto');            
    
    ...
    
    app.use('/subform', subform);
    app.use('/usesession', usesession);
    app.use('/usecookies', usecookies);
    app.use('/usecrypto', usecrypto);
    復制代碼

    通過URL訪問后,根據路由規則先到哪個文件,這里再說明下(app.js中有如下內容):

 

app.use([path], function)

  用這個方法來使用中間件,因為express依賴於connect,有大量的中間件,可以通過app.use來使用;path參數可以不填,默認為'/' (項目中用到的就不分別解釋了,用到的時候自已查一API的中間件部分)

  app.use(express.static(path.join(__dirname, 'public'))); 這一句中可能要注意一下,express.static( )是處理靜態請求的,設置了public文件,public下所有文件都會以靜態資料文件形式返回(如樣式、腳本、圖片素材等文件)

 

var routes = require('./routes/index');
var users = require('./routes/users');

app.use('/', routes);
app.use('/users', users);

上面代碼表示當用戶使用/訪問時,調用自定義變量routes,即 routes 目錄下的 index.js 文件,其中.js后綴省略;

      /users訪問時,調用自定義變量uses,即 routes 目錄下 users.js 文件

  這就是為什么,我們示例中用http://localhost:8100/訪問是,修改的index.js里的文件代碼可以執行(當然index.js文件中也要寫對應的代碼,才能是我們最終看到的效果)

  • 在app.js中添加8000端口監聽並運行
...
app.listen(8000);
...

   運行界面如下:

      

  點擊各鏈接都能正常跳轉到對應的頁面!這樣第一步的目錄就算達到了!

 

如何提取頁面中的公共部分?

  在上一步創建的網站中每個頁面都幾乎一樣,現在都只有導航部分?每個頁都要寫?當然不是,我們可以提取出來

  • 在views目錄下新建一個nav.ejs文件,並添加如下代碼
<a href="/">首頁</a>     
<a href="/subform">如何提交表單並接收參數?</a>
<a href="/usesession">如何使用session?</a>
<a href="/usecookies">如何使用cookies?</a>
<a href="/usecrypto">如何字符串加密?</a>
  • 把views目錄下index.ejs、subform.ejs、usesession.ejs、usecookies.ejs、usecrypto.ejs修改成如下代碼
復制代碼
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>     
      <% include nav %>       # 若改為了其他引擎,例如 nav.html, 此處則需寫成 <% include nav.html %>
  </body>
</html>
復制代碼

  運行頁面,發現和上次運行時沒有作何區別,有了這樣的辦法更有利於減少重復代碼、也更有利於統一布局!

<% include 文件名 %> express提供include來嵌入其它頁,這和html嵌入其它頁類似

 

如果用過express2.0版本的會發現當時沒有這個include,用的是一個模版文件layout.ejs來布局!

 

如何提交表單並接收參數?

  如果要做一個網站應用,不可避免的會遇到表單的提交及獲取參數的值,下面我們來看看用node.js + express怎么做

先來構建一個表單簡單模擬登錄GET方式提交數據

  • 打開subform.ejs文件,修改文件代碼為如下:

      

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>     
      <% include nav %>
      
      <form>
          用戶名:<input type="text" id="txtUserName" name="txtUserName" />
          密碼:<input type="password" id="txtUserPwd" name="txtUserPwd" />
          <input type="submit" value="提交">
      </form>
    
  </body>
</html>

subform.ejs 示例代碼
subform.ejs 示例代碼

 

  • 打開subform.js我們試着接收參數值並輸出到控制台

     

var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
  var 
  userName = req.query.txtUserName,
  userPwd = req.query.txtUserPwd,
  userName2 = req.param('txtUserName'),
  userPwd2 = req.param('txtUserPwd');

  console.log('req.query用戶名:'+userName);
  console.log('req.query密碼:'+userPwd);
  console.log('req.param用戶名:'+userName2);
  console.log('req.param密碼:'+userPwd2);

  res.render('subform', { title: '提交表單及接收參數示例' });
});

module.exports = router;

subform.js get方式源碼
subform.js get方式源碼

 

  • 運行,並提交表單 在瀏覽器中運行:http://localhost:8000/subform,輸入表單項並提交,可以發現url發生了變化

  

  可以發現url中出現了我表單中輸入並要提交的值!

  我們再看看控制台的輸出

  

   我們完成了GET方式提交表單並接收到了值,不錯^_^!(稍后在后面再去講得到值的方式和區別)

 

  再來在上面的代碼基礎上去修改一下表單的method簡單模擬登錄POST方式提交數據

  • 首先修改一下subform.ejs文件中的form標簽,修改為如下:
<form method="post">
...
</form>
  • 再在subform.js中添加代碼,接收post提交、接收參數並輸出到控制台
復制代碼
...

router.post('/',function(req, res){
  var 
  userName = req.body.txtUserName,
  userPwd = req.body.txtUserPwd,
  userName2 = req.param('txtUserName'),
  userPwd2 = req.param('txtUserPwd');

  console.log('req.body用戶名:'+userName);
  console.log('req.body密碼:'+userPwd);
  console.log('req.param用戶名:'+userName2);
  console.log('req.param密碼:'+userPwd2);

 res.render('subform', { title: '提交表單及接收參數示例' }); }); ...
復制代碼
  • 運行,並提交表單 在瀏覽器中運行:http://localhost:8000/subform,輸入表單項並提交,可以發現url不會發生變化

  

  改為post方式后,會發現不會跟get方式提交一樣在url中出現了表單中輸入並要提交的值!

  我們再看看控制台的輸出

  

  OK,我們完成了POST提交表單並接收參數!

 

  再回過頭看看GET和POST方式接收值,從直接效果上來看 

req.query:我用來接收GET方式提交參數

req.body:我用來接收POST提交的參數

req.params:兩種都能接收到

 

   

大家自行看看Express的Request部分的API: http://expressjs.com/api.html#req.params

這里着重解釋一下req.body,Express處理這個post請求是通過中間件bodyParser,你可以看到app.js中有一塊代碼

復制代碼
...

var bodyParser = require('body-parser');

...

app.use(bodyParser.json());
app.use(bodyParser.urlencoded());

...
復制代碼

  沒有這個中間件Express就不知道怎么處理這個請求,通過bodyParser中間件分析 application/x-www-form-urlencoded和application/json請求,並把變量存入req.body,這種我們才能夠獲取到!

 

如何字符串加密?

  當我們提交表單后,比如密碼這些敏感信息,不做個加密處理那也太不把用戶私密信息當回事了,Node.js提供了一個加密模塊 Crypto http://nodejs.org/api/crypto.html

  下面我們用個示例使用一下

  • 打開usecrypto.js,修改代碼為如下:
復制代碼
var express = require('express');
var router = express.Router();
var crypto = require('crypto');

/* GET home page. */
router.get('/', function(req, res) {
  
  res.render('usecrypto', { title: '加密字符串示例' });
 
});

router.post('/',function(req, res){
  var 
  userName = req.body.txtUserName,
  userPwd = req.body.txtUserPwd;

  //生成口令的散列值
  var md5 = crypto.createHash('md5');   //crypto模塊功能是加密並生成各種散列
  var en_upwd = md5.update(userPwd).digest('hex');

  console.log('加密后的密碼:'+en_upwd);
  
  res.render('usecrypto', { title: '加密字符串示例' });
});

module.exports = router;
復制代碼
  • 打開usecrypto.ejs,修改代碼為如下
復制代碼
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>     
      <% include nav %>

      <form method="post">
          用戶名:<input type="text" id="txtUserName" name="txtUserName" />
          密碼:<input type="password" id="txtUserPwd" name="txtUserPwd" />
          <input type="submit" value="提交">
      </form>
  </body>
</html>
復制代碼
  • 運行,輸入並提交表單,查看控件台輸出

  

  成功MD5方式加密!

  其中用到了createHash(algorithm)方法 ,這是利用給定的算法生成hash對象 

  Node.js提供的加密模塊功能非常強大,Hash算法就提供了MD5、sha1、sha256等,根據需要去使用

  update(data, [input_encoding])方法,可以通過指定的input_encoding和傳入的data數據更新hash對象,input_encoding為可選參數,沒有傳入則作為buffer處理 (input_encoding可為'utf-8'、'ascii'等)

  digest([encoding])方法,計算數據的hash摘要值,encoding是可選參數,不傳則返回buffer (encoding可為 'hex'、'base64'等);當調用digest方法后hash對象將不可用;

如何使用session?

  Internet通訊協議分為stateful和stateless兩類,對Web開發有一定了解的應該知道,http是stateless協議,客戶端發送請求到服務端建立一個連接,請求得得到響應后連接即中斷,服務器端不會記錄狀態,因此服務器端想

  要確定是哪個客戶端提交過來的請求,那就必須要借助一些東西去完成,就是session和cookies,現在我們先說說session,以及在nodejs下使用session !

  session存在於服務器端,需要cookies的協助才能完成;服務器端和客戶端通過session id來建立聯系(具體session和cookies怎么協作的,可以自已去補充點相關知識,這里只簡單提一下,不展開了,要不然這篇文章就更雜了^_^!)

 

  express中可以用中間件來使用session,express-session(https://github.com/expressjs/session ) 可以存在內存中,也可以存在mongodb、redis等中...

  更多中間件:https://github.com/senchalabs/connect#middleware

 

  下面我們通過示例看看怎么使用session  (內存方式)

  示例設計思路:使用兩個頁面,一個登錄,兩個頁都判斷是否有這個session,如果有,顯示已登錄,沒有則顯示一個登錄按鈕,點此按鈕,記錄session

  • 首先通過npm安裝這個中間件,打開package.json文件,在dependencies節點下添加一個鍵值對  "express-session" : "latest" 
  "dependencies": {
    ...,
    "express-session" : "latest" 
  }

  lateset:最新的

  • cd到項目根目錄下,執行npm install

  

  • 打開app.js,添加如下代碼
復制代碼
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');

...      

//這里傳入了一個密鑰加session id
app.use(cookieParser('Wilson'));
//使用靠就這個中間件 app.use(session({ secret: 'wilson'})); ...
復制代碼

  這些options就不解釋了,通過上面中間件的鏈接,自已看一下

  • 我這里使用 usesession 和 usecookies 作示例,修改 js 和 ejs 如下

  

  

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>     
      <% include nav %>

      <% if(locals.islogin){ %>
         用戶已登錄
    <% } else { %>
         <form method="post">          
              <input type="submit" value="登錄">
          </form>
    <% } %>
  </body>
</html>

usesession.ejs 和 usecookies.ejs
usesession.ejs 和 usecookies.ejs
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
  
  if(req.session.islogin)
  {
       console.log('usesession:' + req.session.islogin);
     res.locals.islogin = req.session.islogin;      
  }

  res.render('usesession', { title: '使用session示例' });
});

router.post('/', function(req, res) {
  
  req.session.islogin = 'success';
  res.locals.islogin = req.session.islogin;

  res.render('usesession', { title: '使用session示例' });
});

module.exports = router;
usession.js
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {

  if(req.session.islogin)
  {
      console.log('usecookies:' + req.session.islogin);
    res.locals.islogin = req.session.islogin;      
  }

  res.render('usecookies', { title: '使用cookies示例' });
});

router.post('/', function(req, res) {
  
  req.session.islogin = 'success';
  res.locals.islogin = req.session.islogin;

  res.render('usecookies', { title: '使用cookies示例' });
});

module.exports = router;

usecookies.js 示例代碼
usecookies.js
  • 運行並查看

  第一次運行時,查看兩個頁,效果如下:

  

  

  • 點擊登錄按鈕后,再查看這兩個頁

  

  

  • 關閉瀏覽器,再打開查看這兩個頁,如第5步截圖效果

  

  session的使用成功!

  

  官方示例:https://github.com/visionmedia/express/blob/master/examples/session/index.js

 

如何使用cookies?

  如果是登錄,那常見就是“記錄密碼”或“自動登錄”功能,這個一般用 cookies來完成

  cookies存在客戶端,安全性較低,一般要存入加密后的信息;建議要設置使用過期時間或不使用時刪除掉

 

  express也同樣可以用中間件來使用:https://github.com/expressjs/cookie-parser

  

      老套路,通過一個示例了解一下

   示例設計思路:在上面session示例的基礎上,在usecookies部分登錄同時記錄cookies,來自動登錄

  • 在上面session示例的基礎上修改一下usecookies.js
復制代碼
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
   
  if(req.cookies.islogin)
  { 
       console.log('usecookies-cookies:' + req.cookies.islogin);
       req.session.islogin = req.cookies.islogin;
  }  
  
  if(req.session.islogin)
  {
      console.log('usecookies:' + req.session.islogin);
    res.locals.islogin = req.session.islogin;      
  }

  res.render('usecookies', { title: '使用cookies示例' });
});

router.post('/', function(req, res) {
  
  req.session.islogin = 'success';
  res.locals.islogin = req.session.islogin;

  res.cookie('islogin', 'sucess', { maxAge: 60000 });

  res.render('usecookies', { title: '使用cookies示例' });
});

module.exports = router;
復制代碼
  • 運行訪問 http://localhost:8000/usecookies,點擊登錄按鈕登錄成功並記錄cookies

         maxAge為過期時長,毫秒為單位,我設置一分鍾

  • 關閉瀏覽器,再次訪問http://localhost:8000/usecookies ,頁面顯示已登錄
  • 再次關閉瀏覽器,過一分鍾再訪問http://localhost:8000/usecookies,頁面不再是已登錄,而是顯示登錄按鈕,表示cookies過期,不會自動登錄

 

  cookies的使用到此也成功!

 

  官方示例:https://github.com/visionmedia/express/blob/master/examples/cookies/app.js   

 

如何清除session和cookies?

  清除非常簡單,就不用示例說明了,有興趣自已定義個路由規則,試試

//清除cookies
res.clearCookie('islogin');
  
//清除session
req.session.destroy();

寫在之后

  最近比較忙,更新距上了篇時間較長了,本篇東西講的比較雜,講到的也比較有限,主要是為了后來會寫的一個示例打基礎;

 

  本篇內容講到的一些知識點,其實都可以單獨拿一整篇去講,本篇基本原則是為了看了之后能使用;

 

  要想弄清楚原理或者更多的相關知識,自已可以花點時間去了解,或者找點資料去豐富一下,當然也可以留言,在我覺得我沒亂說的情況下我會盡量解答^_^!

 

Next: modeJS(2)深了解: nodeJS 項目架構詳解(app.js + Express + Http)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM