express 應用創建及app.js詳解


#1 express 應用創建

1、安裝node.js (自行百度)

2、npm install express -g 

3、全局安裝express生成器 express-generator 

  npm install express-generator -g 

4、查看 express 版本,可以檢查生成器 express-generator  是否安裝成功

   express -v 

5、(可選)查看express 所有幫助指令及用法

  express -h

6、cd 進入指定目錄 workspace(任意命名)--------------這是系統cmd指令,不是node指令

7、在指定目錄 workspace(任意命名) 創建項目 nodejs-demo(任意命名)

  express -e nodejs-demo

8、由當前目錄 workspace(任意命名)  進入 項目目錄 nodejs-demo(任意命名)--------------這是系統cmd指令,不是node指令

  cd workspace

9、安裝依賴

  npm install 

10、啟動項目

  npm start

 

 

#2 目錄結構# 接下來,我們詳細看一下Express4項目的結構、配置和使用。

bin, 存放啟動項目的腳本文件

node_modules, 存放所有的項目依賴庫。

public,靜態文件(css,js,img)

routes,路由文件(MVC中的C,controller)

views,頁面文件(Ejs模板)

package.json,項目依賴配置及開發者信息

app.js,應用核心配置文件

輸入圖片說明

#3 package.json項目配置# package.json用於項目依賴配置及開發者信息,scripts屬性是用於定義操作命令的,可以非常方便的增加啟動命令,比如默認的start,用npm start代表執行node ./bin/www命令。查看package.json文件。

{
  "name": "express4-demo", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { "body-parser": "~1.10.2", "cookie-parser": "~1.3.3", "debug": "~2.1.1", "ejs": "~2.2.3", "express": "~4.11.1", "morgan": "~1.5.1", "serve-favicon": "~2.2.0" } } 

#4 app.js核心文件# 從Express3.x升級到Express4.x,主要的變化就在app.js文件中。查看app.js文件,我已經增加注釋說明。

// 加載依賴庫,原來這個類庫都封裝在connect中,現在需地注單獨加載 var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); // 加載路由控制 var routes = require('./routes/index'); //var users = require('./routes/users'); // 創建項目實例 var app = express(); // 定義EJS模板引擎和模板文件位置,也可以使用jade或其他模型引擎 app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); // 定義icon圖標 app.use(favicon(__dirname + '/public/favicon.ico')); // 定義日志和輸出級別 app.use(logger('dev')); // 定義數據解析器 app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); // 定義cookie解析器 app.use(cookieParser()); // 定義靜態文件目錄 app.use(express.static(path.join(__dirname, 'public'))); // 匹配路徑和路由 app.use('/', routes); //app.use('/users', users); // 404錯誤處理 app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // 開發環境,500錯誤處理和錯誤堆棧跟蹤 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 }); }); } // 生產環境,500錯誤處理 app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); // 輸出模型app module.exports = app; 

我們看到在app.js中,原來調用connect庫的部分都被其他的庫所代替,serve-favicon、morgan、cookie-parser、body-parser,默認項目中,只用到了最基本的幾個庫,還沒有其他需要替換的庫,在本文最后有詳細列出。

另外,原來用於項目啟動代碼也被移到./bin/www的文件,www文件也是一個node的腳本,用於分離配置和啟動程序。查看./bin/www文件。

#!/usr/bin/env node /** * 依賴加載 */ var app = require('../app'); var debug = require('debug')('nodejs-demo:server'); var http = require('http'); /** * 定義啟動端口 */ var port = normalizePort(process.env.PORT || '3000'); app.set('port', port); /** * 創建HTTP服務器實例 */ var server = http.createServer(app); /** * 啟動網絡服務監聽端口 */ server.listen(port); server.on('error', onError); server.on('listening', onListening); /** * 端口標准化函數 */ function normalizePort(val) { var port = parseInt(val, 10); if (isNaN(port)) { return val; } if (port >= 0) { return port; } return false; } /** * HTTP異常事件處理函數 */ function onError(error) { if (error.syscall !== 'listen') { throw error; } var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': console.error(bind + ' requires elevated privileges'); process.exit(1); break; case 'EADDRINUSE': console.error(bind + ' is already in use'); process.exit(1); break; default: throw error; } } /** * 事件綁定函數 */ function onListening() { var addr = server.address(); var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; debug('Listening on ' + bind); } 

#5 Bootstrap界面框架# 創建Bootstrap界面框架,直接在index.ejs文件上面做修改。可以手動下載Bootstrap庫放到項目中對應的位置引用,也可以通過bower來管理前端的Javascript庫,參考文章 bower解決js的依賴管理另外還可以直接使用免費的CDN源加載Bootstrap的css和js文件。下面我就直接使用bower來管理前端的JavaScript庫的方式。編輯views/index.ejs文件:

<!DOCTYPE html> <html lang="zh-CN"> <head> <title><%= title %></title> <link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css"> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <div class="well jumbotron"> <h1><%= title %></h1> <p>This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> <script src="/bower_components/jquery/dist/jquery.min.js"></script> <script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script> </body> </html> 

效果如下,已經加入了bootstrap的樣式了。

輸入圖片說明

接下來,我們把index.ejs頁面切分成3個部分:header.ejs, index.ejs, footer.ejs,用於網站頁面的模塊化

header.ejs, 為頁面的頭部區域

index.ejs, 為內容顯示區域

footer.ejs, 為頁面底部區域

編輯header.ejs:

<!DOCTYPE html> <html lang="zh-CN"> <head> <title><%= title %></title> <link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css"> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> 

編輯footer.ejs:

    <script src="/bower_components/jquery/dist/jquery.min.js"></script> <script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script> </body> </html> 

編輯index.ejs:

<% include header.ejs %> <div class="well jumbotron"> <h1><%= title %></h1> <p>This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> <% include footer.ejs %> 

把頁表和頁底的代碼分離后,讓index.ejs頁面的核心代碼更少,更容易維護。

#6 路由功能# 路由功能,是Express4以后全面改版的功能。在應用程序加載隱含路由中間件,不用擔心在中間件被裝載相對於路由器中間件的順序。定義路由的方式是不變的,路由系統中增加2個新的功能。

app.route()函數,創建可鏈接的途徑處理程序的路由路徑。

express.Router類,創建模塊化安裝路徑的處理程序。

app.route方法會返回一個Route實例,它可以繼續使用所有的HTTP方法,包括get,post,all,put,delete,head等。

app.route('/users') .get(function(req, res, next) {}) .post(function(req, res, next) {}) 

express.Router類,則可以幫助我們更好的組織代碼結構。在app.js文件中,定義了app.use(‘/’, routes); routes是指向了routes目錄下的index.js文件,./routes/index.js文件中,express.Router被定義使用,路徑/*處理都會由routes/index.js文件里的Router來處理。如果我們要管理不同的路徑,那么可以直接配置為多個不同的Router。

app.use('/user', require('./routes/user').user); app.use('/admin', require('./routes/admin').admin); app.use('/', require('./routes')); 

#7 Ejs模板使用# 讓ejs模板文件,使用擴展名為html的文件。修改:app.js

app.engine('.html', ejs.__express); app.set('view engine', 'html'); // app.set('view engine', 'ejs'); 

修改后,ejs變量沒有定義,supervisor的程序會一直報錯

ReferenceError: ejs is not defined at Object. (D:\workspace\project\nodejs-demo\app.js:17:21) at Module._compile (module.js:456:26) at Object.Module._extensions..js (module.js:474:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:312:12) at Function.Module.runMain (module.js:497:10) at startup (node.js:119:16) at node.js:901:3 DEBUG: Program node app.js exited with code 8 

在app.js中增加ejs變量:

var express = require('express') , routes = require('./routes') , user = require('./routes/user') , http = require('http') , path = require('path') , ejs = require('ejs'); 

#8 Session使用# session這個問題,其實是涉及到服務器的底層處理方式。像Java的web服務器,是多線程調用模型。每用戶請求會打開一個線程,每個線程在內容中維護着用戶的狀態。

像PHP的web服務器,是交行CGI的程序處理,CGI是無狀態的,所以一般用cookie在客戶的瀏覽器是維護用戶的狀態。但cookie在客戶端維護的信息是不夠的,所以CGI應用要模仿用戶session,就需要在服務器端生成一個session文件存儲起來,讓原本無狀態的CGI應用,通過中間文件的方式,達到session的效果。

Nodejs的web服務器,也是CGI的程序無狀態的,與PHP不同的地方在於,單線程應用,所有請求都是異步響應,通過callback方式返回數據。如果我們想保存session數據,也是需要找到一個存儲,通過文件存儲,redis,Mongdb都可以。

接下來,我將演示如何通過mongodb來保存session,並實現登陸后用戶對象傳遞。

app.js文件:

var express = require('express') , routes = require('./routes') , user = require('./routes/user') , http = require('http') , path = require('path') , ejs = require('ejs') , SessionStore = require("session-mongoose")(express); var store = new SessionStore({ url: "mongodb://localhost/session", interval: 120000 }); .... app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.cookieParser()); app.use(express.cookieSession({secret : 'fens.me'})); app.use(express.session({ secret : 'fens.me', store: store, cookie: { maxAge: 900000 } })); app.use(function(req, res, next){ res.locals.user = req.session.user; next(); }); app.use(app.router); app.use(express.static(path.join(__dirname, 'public'))); 

注:app.js文件有順序要求,一定要注意!!!

安裝session-mongoose依賴庫:

D:\workspace\project\nodejs-demo>npm install session-mongoose D:\workspace\project\nodejs-demo\node_modules\session-mongoose\node_modules\mongoose\node_modules\mongodb\node_modules\bson>node "D:\toolkit\nodejs\node_modules\npm\bin\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.Cpp.InvalidPlatform.Targets(23,7): error MSB8007: 項目“kerberos.vcxproj”的平台無效。平台為“x64”。您會看到此消息的可能原因是,您嘗試在沒有解決方案文件的情況下生成項目,並且為 oose\node_modules\mongoose\node_modules\mongodb\node_modules\bson\build\bson.vcxproj] session-mongoose@0.2.2 node_modules\session-mongoose └── mongoose@3.6.10 (mpath@0.1.1, ms@0.1.0, hooks@0.2.1, sliced@0.0.3, muri@0.3.1, mpromise@0.2.1, mongodb@1.3.3) 

安裝有錯誤但是沒關系。訪問:http://localhost:3000/login,正常

修改routes/index.js文件,exports.doLogin方法:

exports.doLogin = function(req, res){ var user={ username:'admin', password:'admin' } if(req.body.username===user.username && req.body.password===user.password){ req.session.user=user; return res.redirect('/home'); } else { return res.redirect('/login'); } }; 

exports.logout方法:

exports.logout = function(req, res){ req.session.user=null; res.redirect('/'); }; 

exports.home方法:

exports.home = function(req, res){ res.render('home', { title: 'Home'}); }; 

這個時候session已經起作用了,exports.home的user顯示傳值已經被去掉了。 是通過app.js中app.use的res.locals變量,通過框架進行的賦值。

app.use(function(req, res, next){ res.locals.user = req.session.user; next(); }); 

注:這個session是express3.0的寫法,與express2.x是不一樣的。原理是在框架內每次賦值,把我們剛才手動傳值的過程,讓框架去完成了

  


免責聲明!

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



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