nodejs + express + mysql + redis 基礎(chǔ)功能實現(xiàn)
nodejs + express + mysql + redis 基礎(chǔ)功能實現(xiàn)
本文大體介紹了nodejs項目的創(chuàng)建、express框架的使用、mysql數(shù)據(jù)庫的連接、以及redis的數(shù)據(jù)交互等方法,并舉例了些簡單的例子進行說明,代碼都是親自重頭跑了一遍的,拿來可用。
一、創(chuàng)建nodejs 項目
1. 創(chuàng)建一個文件夾,以node_demo 為例,運用cmd 進入該文件夾,輸入指令初始化項目
npm init -y
生成package.json 文件
可先安裝以下包,后面會用到
2. nodejs 啟動服務(wù)測試
創(chuàng)建server.js 文件,以hellow word! 為例做測試
本人用的 vscode,敲node 發(fā)現(xiàn)沒代碼提示,敲著有點不得勁。(不過一個個字母敲出來有助于記憶,有閑情的可以試試。)于是先去搞個代碼提示插件。
打開vscode 終端控制臺,安裝 @types
npm i @types/node --save-dev
好了,現(xiàn)在有提示了
直接上代碼
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, {
'Content-Type': 'Text/plain'
});
res.end('hellow word!');
}).listen(3307, () => {
console.log('服務(wù)啟動');
})
瀏覽器中輸入 localhost:3307
出現(xiàn) hellow word! 一個簡單的服務(wù)就寫好了
3. 運用express框架寫接口
以get 接口 /testGet,post接口/testPost 為例,server.js代碼如下
const express = require('express');
const app = express();
app.use(express.json()); // 解析json請求
app.use(express.urlencoded({extended: false})) // 解析URL-encoded請求
app.listen(3307, () => {
console.log('服務(wù)啟動');
})
app.get('/testGet', (req, res) => { // 測試get 請求
returnParams(req.query, res)
})
app.post('/testPost', (req, res) => { // 測試post 請求
returnParams(req.body, res)
})
function returnParams(data, res) {
res.json({ code: 1, status: 'S', data: data, msg: '成功' })
}
打開 postman,調(diào)用接口測試
get 接口測試返回如下,可見testGet 接口拿到參數(shù)且成功返回
post 接口測試返回如下,可見testPost 接口也成功返回
注:post 請求時,json 格式需調(diào)用express.json中間件,表單格式需調(diào)用express.urlencoded 中間件
app.use(express.json()); // 解析json請求
app.use(express.urlencoded({extended: false})) // 解析URL-encoded請求
有時我們在調(diào)用相應(yīng)的接口前需要做相應(yīng)的攔截判斷,此時可使用以下代碼
app.all('*', (req, res, next) => {
// 寫入相應(yīng)的攔截操作
next(); // 要繼續(xù)往下跑記得寫上 next()
})
4. 熱加載 與 跨域
寫到這里你應(yīng)該會發(fā)現(xiàn),每改一次文件,你都需重新node server.js 一次,非常麻煩,于是這里使用hotnode 熱加載,每保存一次,它將自動重新加載服務(wù)。
npm i hotnode --save
然后使用 hotnode server.js 啟動node 即可。
若覺得該命令太長懶得寫,也可在package.json 文件做如下配置
如此一來,使用 npm start 即可,但這樣會有如下報錯
根據(jù)網(wǎng)上查到的方法,print 為打印方法,既然程序沒找到,那么干脆把它改為 console.log 方法。
打開hotloader.js 文件,找到相應(yīng)位置,改為如下代碼
this.process.stdout.on("data", function(data) {
return console.log(data.toString());
// return util.print(data.toString());
});
然后使用 npm start 運行就正常了
跨域問題
A. 可以使用現(xiàn)有輪子
npm i cors --save
const cors = require("cors")
app.use(cors()) // 解決跨域
B. 也可以用如下代碼設(shè)置
//設(shè)置跨域訪問
app.all('*', (req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", ' 3.2.1');
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
5. express router
以上雖然實現(xiàn)了接口的編寫,但為了方便管理接口、區(qū)分功能模塊,我們使用router 來劃分下。
首先創(chuàng)建routes 文件夾,假設(shè)有一個“測試”模塊,那么在routes 文件夾下創(chuàng)建test.js 文件
test.js 文件代碼如下
const express = require('express');
const router = express.Router();
router.get('/testGet', (req, res) => { // 測試get 請求
returnParams(req.query, res)
})
router.post('/testPost', (req, res) => { // 測試post 請求
returnParams(req.body, res)
})
function returnParams(data, res) {
res.json({ code: 1, status: 'S', data: data, msg: '成功' })
}
module.exports = router
則 server.js 文件代碼更改如下
const express = require('express');
const app = express();
const test = require('./routes/test');
app.use(express.json()); // 解析json請求
app.use(express.urlencoded({extended: false})) // 解析URL-encoded請求
app.listen(3307, () => {
console.log('服務(wù)啟動');
})
app.all('*', (req, res, next) => {
// 寫入相應(yīng)的攔截操作
next(); // 要繼續(xù)往下跑記得寫上 next()
})
app.use('/test', test);
二、使用 sequelize 操作mysql 數(shù)據(jù)庫
1. 開發(fā)準備
先下載安裝mysql數(shù)據(jù)庫,然后安裝navicat 操作數(shù)據(jù)庫,這里不過多說明,可自行百度。
以建好的表article 為例
項目中先安裝 mysql、mysql2、sequelize 包
npm i mysql mysql2 sequelize --save
2. 連接數(shù)據(jù)庫,建立模型
新建database 文件夾,在文件夾下新建db.js文件,寫入代碼如下
const Sequelize = require("sequelize");
const db = {}
const sequelize = new Sequelize('my_website', 'root', '123456', {
host: 'localhost',
dialect: 'mysql',
pool: {
max: 5,
min: 0,
acquire: 3000,
idle: 10000,
}
});
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db;
這里可參照官方文檔
然后建立模型
新建文件夾models,在文件夾下新建 Article.js 文件,寫入代碼如下(字段與數(shù)據(jù)庫字段對應(yīng))
const Sequelize = require("sequelize");
const db = require("../database/db");
module.exports = db.sequelize.define('article', {
aid: {
type: Sequelize.INTEGER,
primaryKey: true, // 主鍵
},
title: {
type: Sequelize.STRING,
},
title_map: {
type: Sequelize.STRING,
},
content: {
type: Sequelize.TEXT,
},
create_time: {
type: Sequelize.DATE,
},
agree_num: {
type: Sequelize.INTEGER,
},
disagree_num: {
type: Sequelize.INTEGER,
},
comments_num: {
type: Sequelize.INTEGER,
},
}, {
timestamps: false, // 不自動加上 createdAt 和 updatedAt
freezeTableName: true, // 強制表名稱等于模型名稱,不自動將模型名復(fù)數(shù)并將其用作表名
})
注:nodejs 連接數(shù)據(jù)庫時,可能會報錯,文章最下方“參考資料”中給出了兩個常見問題解決鏈接
3. 查詢文章列表接口
routes 文件夾下建立article.js 文件,代碼如下
const express = require('express');
const router = express.Router();
const Article = require('../models/Article');
router.post('/searchArticle', (req, res) => {
Article.findAll().then(sqlRes => {
res.json({ code: 1, status: 'S', data: sqlRes, msg: '成功' })
}).catch(sqlError => {
res.json({ code: 0, status: 'E', data: sqlError, msg: sqlError })
})
})
module.exports = router;
回到server.js 文件引入article
const article = require('./routes/article');
app.use('/article', article);
啟動服務(wù),用postman做測試,查詢article 表中的數(shù)據(jù)
可見已查詢成功,那么查詢表數(shù)據(jù)就實現(xiàn)了。其他的增、刪、改等操作在此不過多贅述,有興趣的可以去官網(wǎng)看看。
三、nodejs 操作redis
1. 開發(fā)準備
下載安裝redis后,啟動redis,啟動成功界面如下
保留該窗口,另啟一個窗口,redis安裝文件夾目錄下輸入命令
redis-cli -h localhost -p 6379
項目中安裝 redis 包
npm i redis --save
2. 編寫代碼
創(chuàng)建redis 文件夾
新建redisOptions.js 文件,代碼如下
const options = {
host: 'localhost',
port: 6379,
// password: '', // 本人未設(shè)置密碼,所以隱藏,若你設(shè)了密碼,則輸入密碼
detect_buffers: true // 傳入buffer 返回也是buffer 否則會轉(zhuǎn)換成String
}
module.exports = options
新建redisConfig.js 文件,代碼如下(想要用到什么redis 操作,可自行寫入方法)
const redis = require('redis')
const redisOptions = require('./redisOptions')
const options = {
host: redisOptions.host,
port: redisOptions.port,
password: redisOptions.password,
detect_buffers: redisOptions.detect_buffers, // 傳入buffer 返回也是buffer 否則會轉(zhuǎn)換成String
retry_strategy: function (options) {
// 重連機制
if (options.error && options.error.code === "ECONNREFUSED") {
// End reconnecting on a specific error and flush all commands with
// a individual error
return new Error("The server refused the connection");
}
if (options.total_retry_time > 1000 * 60 * 60) {
// End reconnecting after a specific timeout and flush all commands
// with a individual error
return new Error("Retry time exhausted");
}
if (options.attempt > 10) {
// End reconnecting with built in error
return undefined;
}
// reconnect after
return Math.min(options.attempt * 100, 3000);
}
}
// 生成redis的client
const client = redis.createClient(options)
// 存儲值
const setValue = (key, value) => {
if (typeof value === 'string') {
client.set(key, value)
} else if (typeof value === 'object') {
for (let item in value) {
client.hmset(key, item, value[item], redis.print)
}
}
}
// 數(shù)值自增
const incrValue = (key, value) => {
client.incr(key, value)
}
// 獲取string
const getValue = (key) => {
return new Promise((resolve, reject) => {
client.get(key, (err, res) => {
if (err) {
reject(err)
} else {
resolve(res)
}
})
})
}
// 獲取hash
const getHValue = (key) => {
return new Promise((resolve, reject) => {
client.hgetall(key, function (err, value) {
if (err) {
reject(err)
} else {
resolve(value)
}
})
})
}
// 導(dǎo)出
module.exports = {
setValue,
incrValue,
getValue,
getHValue
}
回到 test.js 文件,寫入如下代碼測試
const redis = require('../redis/redisConfig');
redis.setValue('testKey', 'testValue');
在命令行窗口中輸入get testKey,發(fā)現(xiàn)值成功返回
nodejs 獲取redis 值則使用 redis.getValue()
redis.getValue('testKey').then(val => {
console.log('val:', val);
})
到此,nodejs 基本功能差不多算說完了,最終目錄結(jié)構(gòu)如下
##### 廢話star (可跳過)
本文主要是借鑒他人文章整合而成,在此特做說明,借鑒資料出處文后有說明。
寫此文目的有三:
1. 梳理下知識以便更好的記憶;
2. 整合起來方便閱讀,避免東查一點功能、西查一點功能,節(jié)省時間。方便自學(xué)者學(xué)習(xí),也方便本人復(fù)制黏貼;
3. 以往都是復(fù)制別人的代碼,拿別人的知識,現(xiàn)在怎么說也由小白晉級菜鳥了,也輸出下知識做點回饋吧。
另:本人nodejs 用的較少,受限于眼界與項目經(jīng)驗,多有不足之處還望指正,有更優(yōu)的方案或思路也望不吝賜教,感謝。
第一次寫文,啰嗦了點,咳咳,
##### 廢話end

浙公網(wǎng)安備 33010602011771號