Express是一個極簡的Node.js Web框架。Express官網(wǎng)
學習了express之后,簡單實現(xiàn)了一個CRUD demo,整理了一些核心點和第三方中間件的使用。
- 引入express,啟動一個服務(wù)
const express = require('express');
const app = express();
app.listen(3000, () => {
console.log('runing...')
})
- 托管靜態(tài)文件
對于諸如image、css、js等靜態(tài)資源,Express內(nèi)置了一個 express.static 中間件函數(shù)。
express.static(root, options);
/**
* 1. 參數(shù)1:靜態(tài)文件根目錄
* 2. 參數(shù)2:可選配置項 具體參考 http://www.expressjs.com.cn/4x/api.html#express.static
* /
比如通過這行代碼就可以訪問static目錄下的靜態(tài)文件
app.use(express.static('static'));
http://127.0.0.1:3000/image/dog.png
http://127.0.0.1:3000/css/common.css
...
如果使用多個靜態(tài)資源目錄,則多次調(diào)用即可。
如果為express.static函數(shù)所托管的文件創(chuàng)建虛擬路徑前綴(這個路徑前綴實際上在文件系統(tǒng)中不存在),請指定靜態(tài)目錄的掛載路徑,如下:
app.use('/static', express.static('static'))
就可以通過帶有static前綴的路徑來訪問static靜態(tài)目錄中的資源了。如:
http://127.0.0.1:3000/static/image/dog.png
http://127.0.0.1:3000/static/css/common.css
...
- 路由的使用
app.METHOD(path, callback);
如:
app.get('/', (req, res) => {})
app.post('/user', (req, res) => {})
實際開發(fā)中不會把路由全部掛載在app上,不但不易于維護,而且違背了模塊化開發(fā)的思想。Express提供了一個Router函數(shù),用于創(chuàng)建路由實例(容器),作為一個中間件函數(shù),掛載到app上。
// 創(chuàng)建路由容器
const router = express.Router();
roouter.get('/', (req, res) => {})
router.post('/user', (req, res) => {})
// 亦可以鏈式調(diào)用
app.use(router)
-
body-parser第三方庫用于獲取客戶端post提交的數(shù)據(jù)
npm i body-parser- 配置
const bodyParser = require('body-parser'); // body-parser配置 // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: false })) // parse application/json app.use(bodyParser.json())- 獲取post提交的數(shù)據(jù)
req.body -
模板引擎使用art-template
- 安裝
npm install --save art-template npm install --save express-art-template- 配置
// 模板引擎配置 默認去views目錄下查找 app.engine('html', require('express-art-template')); // 參數(shù)1:模板的后綴 app.set('view options', { debug: process.env.NODE_ENV !== 'production' });- 使用
res.render(view [, locals] [, callback]) /* 1. view 模板名 * 2. 模板需要的數(shù)據(jù) * 3. 回調(diào),兩個參數(shù), err 和 html(渲染好的字符串) * /例:
router.get('/user', (req, res) => { res.render('index.html', { userInfo: { name: 'Jack', age: 12 } }, (err, html) => { if (err) thorw err; }) }) -
md5加密
使用md5對用戶注冊和登錄的密碼進行加密npm i md5const md5 = require('md5'); // 采用二次加密,生產(chǎn)中一般會在第一次加密后拼接sign以提高安全性 password = md5(md5(password) + 'userManage'); -
保存登錄和注冊狀態(tài)
用戶注冊和登錄后均跳轉(zhuǎn)到首頁,并保存登錄狀態(tài),使用 express-session是針對express的一個中間件npm i express-session- session 配置
app.use(session({ // 配置加密字符串,會在原有加密的基礎(chǔ)上,拼接起來再次加密;目的是防止客戶端惡意篡改,提高安全性 secret: 'keyboard cat', resave: false, // 無論是否需要 session,默認給客戶端分配session,如果設(shè)置成false,只有服務(wù)端設(shè)置了session的時候才會給客戶端分配session saveUninitialized: true, cookie: { // 設(shè)置cookie的過期時間 maxAge: 1000 * 10 } }))通過req.session.xxx來獲取設(shè)設(shè)置session;
注意:
session默認存儲在內(nèi)存,服務(wù)器一旦重啟就會丟失,真正在生產(chǎn)環(huán)境session采用持久化存儲。
- 清除session:
req.session.XXX = null; -
統(tǒng)一處理404和500
處理404的中間件在 app.use(router) 之后,因為只有router上掛載的所有路由都匹配不到的時候才會執(zhí)行404中間件。app.use((req, res) => { res.render('error/404.html') })基本上每個接口都會考慮500的情況,而且每次的處理邏輯都是一樣的,所以通過中間件統(tǒng)一處理。全局處理錯誤中間件,在需要的地方調(diào)用
next()傳入 err 對象,則會默認查找具有四個參數(shù)的中間件,并執(zhí)行相應(yīng)的回調(diào)app.use((err, req, res, next) => { res.status(500).json({ code: 500, msg: err.msg }) }) -
數(shù)據(jù)庫
數(shù)據(jù)庫使用第三方庫 mongoosenpm i mongoose使用:
- 加載模塊
const mongoose = require('mongoose');- 連接數(shù)據(jù)庫
沒有userManage 數(shù)據(jù)庫的話會自動創(chuàng)建,并且如果沒有數(shù)據(jù) 執(zhí)行show dbs的時候不會顯示該數(shù)據(jù)庫,當有了數(shù)據(jù)后就會顯示
mongoose.connect('mongodb://localhost/userManage');- 設(shè)計表結(jié)構(gòu)
MongoDB 是動態(tài)的,通過代碼來設(shè)計數(shù)據(jù)庫表結(jié)構(gòu),靈活性還是很強的
const UserManageSchema = new Schema({ userName: { type: String, required: true, default: '' }, age: { type: Number, required: true }, gender: { type: Number, required: true, enum: [0, 1] }, birthday: { type: String }, job: { type: String }, describe: { type: String } })- 創(chuàng)建構(gòu)造器模型 即集合
比如: 創(chuàng)建用戶表
const UserManage = mongoose.model('userManage', UserManageSchema); // 參數(shù)1 為集合名,會轉(zhuǎn)換成小寫復(fù)數(shù)的形式,即usermanages MangOOSE自動尋找模型名稱的復(fù)數(shù)版本 // 參數(shù)2為集合的架構(gòu)- 新增數(shù)據(jù)
新增數(shù)據(jù)需要創(chuàng)建集合的實例,傳入要新增的數(shù)據(jù)對象,調(diào)用save方法。
new UserManage(DATA).save((err, data) => {}) // data為插入后的數(shù)據(jù),帶數(shù)據(jù)庫生成的主鍵 _id- 查、改、刪通過集合直接調(diào)用對應(yīng)的方法即可
以查為例:以郵箱或者昵稱為條件
UserManage.findOne({ $or: [ {email}, {nickName} ] }, (err, data) => { if (err) return res.status(500).send('server error'); return res.send(data); })
服務(wù)端重定向只針對同步請求,對異步請求無效。
項目demo移步這里 github