使用node.js實(shí)現(xiàn)接口步驟詳細(xì)記錄
1.安裝node環(huán)境,下載地址:下載 | Node.js 中文網(wǎng) 或者點(diǎn)擊這里
2.創(chuàng)建一個(gè)文件夾放node項(xiàng)目,如api_event;
3.項(xiàng)目初始化:在新建的文件夾下執(zhí)行 npm i ,會(huì)自動(dòng)生成package.json文件;
4.安裝express:npm i express@4.17.1
5.在項(xiàng)目中新建文件夾index.js來創(chuàng)建服務(wù)器,如下所示:
// 1.導(dǎo)入express
const express = require('express');
// 2.創(chuàng)建服務(wù)器的實(shí)例對(duì)象
const app = express();
// 3.啟動(dòng)服務(wù)器
app.listen(8088, () => {
console.log('api server running at http:127.0.0.1:8088');
});6.配置cors跨域:npm i cors@2.8.5 下載并導(dǎo)入配置cors中間件;
// 1.1 導(dǎo)入并配置cors中間件
const cors = require('cors');
app.use(cors());
// 1.2 配置解析表單數(shù)據(jù)的中間件, 這個(gè)中間件只能解析 application/x-www-form-urlencoded 格式的表單數(shù)據(jù)
app.use(express.urlencoded({ extended: false }));
// 1.3 只能解析parse application/json 格式
app.use(express.json());注意:客戶端傳參了但是服務(wù)器沒有收到參數(shù)的話,說明你的express版本中的需要body-parser需要手動(dòng)安裝引用。
// 1.導(dǎo)入express
var express = require('express');
// 對(duì)body-parser進(jìn)行配置,獲取前端傳送過來的數(shù)據(jù)
var bodyParser = require('body-parser');
// 2.創(chuàng)建服務(wù)器的實(shí)例對(duì)象
const app = express();
// 1.1 導(dǎo)入并配置cors中間件
const cors = require('cors');
app.use(cors());
// 1.2 配置解析表單數(shù)據(jù)的中間件, 這個(gè)中間件只能解析 application/x-www-form-urlencoded 格式的表單數(shù)據(jù)
app.use(bodyParser.urlencoded({ extended: false }));
// 1.3 只能解析parse application/json 格式
app.use(bodyParser.json());
//雖然請(qǐng)求體的格式不同,但是經(jīng)過node解析后,他們最終得到的都是json格式的對(duì)象。7. 創(chuàng)建路由:在項(xiàng)目根目錄創(chuàng)建兩個(gè)文件夾,
router文件夾:存放路由
router_hander文件夾:存放路由的處理函數(shù)
8.在router文件夾下創(chuàng)建user.js用來創(chuàng)建用戶相關(guān)的路由;
// 1.導(dǎo)入 express 模塊
const express = require('express');
// 2.創(chuàng)建路由對(duì)象
const router = express.Router();
// 5.導(dǎo)入用戶路由處理函數(shù)對(duì)應(yīng)的模塊
const user_handler = require('../router_handler/user')
// 3.掛載路由
// 注冊(cè)新用戶
router.post('/reg', user_handler.reg);
// 登錄
router.post('/login', user_handler.login);
// 4.暴露router模塊
module.exports = router;9.在router_hander文件夾中新建user.js,存放抽離出來的路由模塊的處理函數(shù);
// 注冊(cè)新用戶的處理函數(shù)
exports.reg = (req, res) => {
res.send('reg ok')
}
// 登陸的處理函數(shù)
exports.login = (req, res) => {
res.send('login ok')
}10. 在服務(wù)器中即app.js文件中導(dǎo)入并注冊(cè)路由模塊
// 導(dǎo)入并使用用戶router模塊
const userRouter = require('./router/user');
app.use('/api', userRouter);11.創(chuàng)建數(shù)據(jù)庫(kù)表格:
我使用的mysql數(shù)據(jù)庫(kù)管理工具是navicat,打開創(chuàng)建數(shù)據(jù)庫(kù)my_db,創(chuàng)建數(shù)據(jù)表ev_users,表設(shè)計(jì)如下:

12.安裝并配置mysql模塊連接:npm i mysql@2.18.1
在根目錄下新建的db文件夾下的index.js中導(dǎo)入mysql模塊并創(chuàng)建數(shù)據(jù)庫(kù)連接對(duì)象;
// 1.導(dǎo)入mysql模塊
const mysql = require('mysql')
// 2.創(chuàng)建數(shù)據(jù)庫(kù)連接對(duì)象
const db = mysql.createPool({
host: '127.0.0.1',
user: 'root',
password: '123456',
datebase: 'my_dv'
})
// 3.向外共享 數(shù)據(jù)庫(kù)的連接對(duì)象
module.exports = db13. 代碼優(yōu)化:
(1)在app.js中封裝res.send()的中間件,減少重復(fù)代碼的使用;
// 一定要在路由之前封裝res.cc函數(shù)
app.use((req, res, next) => {
// status 默認(rèn)值為 1,表示失敗的情況
// err的值,可能是錯(cuò)誤對(duì)象,也可能是錯(cuò)誤的描述字符串
res.cc = function (err, status = 1) {
res.send({
status,
message: err instanceof Error ? err.message : err,
});
};
next();
});(2)對(duì)用戶輸入的密碼進(jìn)行加密,防止數(shù)據(jù)庫(kù)數(shù)據(jù)泄漏造成的數(shù)據(jù)威脅;
- 安裝bcryptjs:npm i bcryptjs ,對(duì)用戶密碼加密 ;
- 在router_hander文件夾下的user.js里引入bcryptjs并使用;
// 1.導(dǎo)入加密功能的bcrypt.js
const bcrypt = require('bcryptjs');
//2.在處理函數(shù)中使用
// 注冊(cè)用戶的處理函數(shù),如果用戶名可用,則調(diào)用bcrypt.hashSync() 對(duì)密碼進(jìn)行加密
userinfo.password = bcrypt.hashSync(userinfo.password, 10);
// 登錄用戶的處理函數(shù),判斷密碼是否正確
const compareResult = bcrypt.compareSync(userinfo.password, results[0].password);
if (!compareResult) return res.cc('登陸失??!');(2)使用第三方包來優(yōu)化表單數(shù)據(jù)驗(yàn)證,檢測(cè)輸入的用戶名等是否合法;
- 安裝joi:npm i joi ,為表單中攜帶的數(shù)據(jù)項(xiàng),定義驗(yàn)證規(guī)則;
- 安裝@escook/express-joi中間件:npm i @escook/express-joi ,自動(dòng)對(duì)表單數(shù)據(jù)進(jìn)行驗(yàn)證;
- 在根目錄下創(chuàng)建的scheme文件夾下新建user.js,存放用戶的驗(yàn)證規(guī)則;
// 1. 導(dǎo)入定義驗(yàn)證規(guī)則的包
const joi = require('joi')
// string() 值必須是字符串
// alphanum() 值只能包含a-zA-Z的字符串
// min(1).max(10) 最大長(zhǎng)度, 最小長(zhǎng)度
// required() 值是必填項(xiàng)
// pattern() 值必須符合正則表達(dá)式
// 2. 定義用戶名和密碼的驗(yàn)證規(guī)則
const username = joi.string().alphanum().min(1).max(10).required()
const password = joi.string().pattern(/^[\S]{6,12}/).required()
// 3. 對(duì)外共享定義驗(yàn)證注冊(cè)和登錄表單數(shù)據(jù)的規(guī)則對(duì)象
exports.reg_login_schema = {
body: {
username,
password
}
}
在router文件夾下的user.js中使用驗(yàn)證規(guī)則,導(dǎo)入@escook/express-joi中間件和需要驗(yàn)證規(guī)則的對(duì)象,在路由器中url后插入中間件;
const express = require('express');
const router = express.Router();
// 導(dǎo)入用戶路由處理函數(shù)對(duì)應(yīng)的模塊
const user_handler = require('../router_handler/user')
// 1.導(dǎo)入驗(yàn)證數(shù)據(jù)的中間件
const expressJoi = require('@escook/express-joi')
// 2.導(dǎo)入需要驗(yàn)證的規(guī)則對(duì)象
const { reg_login_schema } = require('../schema/user')
// 注冊(cè)新用戶 3.校驗(yàn)用戶名和密碼是否合法
router.post('/reg', expressJoi(reg_login_schema),user_handler.reg);
// 登錄
router.post('/login', expressJoi(reg_login_schema),user_handler.login);
module.exports = router;在app.js中導(dǎo)入joi模塊,如果驗(yàn)證失敗則調(diào)用錯(cuò)誤中間件:
// 1. 導(dǎo)入 joi 模塊
const joi = require('joi')
// 導(dǎo)入并注冊(cè)路由模塊
const userRouter = require('./router/user')
app.use('/api',userRouter)
//2.定義錯(cuò)誤級(jí)別的中間件
app.use((err, reg, res, next) => {
// 注意 此處一定要加return 終止 不然會(huì)連續(xù)調(diào)用兩次res.send()程序,會(huì)報(bào)錯(cuò)
if(err instanceof joi.ValidationError) return res.cc(err);
// 未知的錯(cuò)誤
res.cc(err);
})14. 開始在router_hander文件夾下的user.js里對(duì)用戶注冊(cè)和登錄進(jìn)行相關(guān)操作
(1) 注冊(cè)用戶的處理函數(shù):
// 注冊(cè)用戶的處理函數(shù)
exports.reg = (req, res) => {
// 1.獲取客戶端提交到服務(wù)器的用戶表單信息
const userinfo = req.body;
// 2.對(duì)表單中的數(shù)據(jù)進(jìn)行合法性的校驗(yàn)
if (!userinfo.username || !userinfo.password) {
// return res.send({ status: 1, message: '用戶名或者密碼不合法!' });
return res.cc('用戶名或者密碼不合法!');
}
// 3.定義sql語(yǔ)句,查詢用戶名是否被占用
const sqlStr = 'select * from ev_users where username=?';
db.query(sqlStr, userinfo.username, (err, results) => {
// 3.1 執(zhí)行sql語(yǔ)句失敗
if (err) return res.cc(err);
// 3.2 判斷用戶名是否被占用
if (results.length > 0) {
return res.cc('用戶名已存在,請(qǐng)更換!');
}
// 3.3 用戶名可用
// 調(diào)用bcrypt.hashSync() 對(duì)密碼進(jìn)行加密
userinfo.password = bcrypt.hashSync(userinfo.password, 10);
// 4. 定義插入新用戶的sql語(yǔ)句
const sql = 'insert into ev_users set ?';
// 4.1 調(diào)用db.query()執(zhí)行sql語(yǔ)句
db.query(sql, { username: userinfo.username, password: userinfo.password }, (err, results) => {
// 4.2 判斷sql語(yǔ)句是否執(zhí)行成功
if (err) return res.cc(err);
// if (err) return res.send({ status: 1, message: err.message });
// 4.3 判斷影響行數(shù)是否為1
if (results.affectedRows !== 1) return res.cc('用戶注冊(cè)失敗,請(qǐng)稍后再試');
// 5.注冊(cè)用戶成功
res.send({ status: 0, message: '注冊(cè)成功' });
});
});
};(2)登錄用戶的處理函數(shù):
- 安裝生成token(JSON Web Token)的包 :npm i jsonwebtoken
- 安裝express-jwt 用來驗(yàn)證token: npm install express-jwt
- 在根目錄下新建一個(gè)全局的配置文件config.js,共享token相關(guān)配置
// 這是一個(gè)全局的配置文件
module.exports = {
// 加密和解密token的密鑰
jwtSecretKey: 'lemon likes web',
// token的有效期
expiresIn: '10h',
};在app.js文件中配置驗(yàn)證token的中間件
// 一定要在路由之前配置解析token的中間件
const expressJWT = require('express-jwt');
const config = require('./config');
app.use(expressJWT({ secret: config.jwtSecretKey }).unless({ path: [/^\/api/] }));
// 1.3 導(dǎo)入并使用用戶router模塊
const userRouter = require('./router/user');回到router_hander文件夾下的user.js里寫登錄的處理函數(shù)
// 1. 導(dǎo)入生成token的包
const jwt = require('jsonwebtoken');
// 2. 登錄用戶的處理函數(shù)
exports.login = (req, res) => {
// 1. 接收表單數(shù)據(jù)
const userinfo = req.body;
// 2. 定義sql語(yǔ)句
const sql = 'select * from ev_users where username=?';
// 3. 執(zhí)行sql語(yǔ)句,根據(jù)用戶名查詢用戶信息
db.query(sql, userinfo.username, (err, results) => {
// 3.1 執(zhí)行sql語(yǔ)句失敗
if (err) return res.cc(err);
console.log(results.length);
// 3.2 執(zhí)行sql語(yǔ)句成功,但是獲取到的數(shù)據(jù)條數(shù)不等于1,則表示沒有該數(shù)據(jù)
if (results.length !== 1) return res.cc('登錄失??!');
// 4. 判斷密碼是否正確
const compareResult = bcrypt.compareSync(userinfo.password, results[0].password);
if (!compareResult) return res.cc('登陸失?。?);
// 5. 在服務(wù)器端生成 Token的字符串
const user = { ...results[0], password: '', user_pic: '' };
// 6. 對(duì)用戶信息進(jìn)行加密,生成Token字符串
const tokenStr = jwt.sign(user, config.jwtSecretKey, { expiresIn: config.expiresIn });
// 7. 調(diào)用res.send()將token響應(yīng)給客戶端
res.send({
status: 0,
message: '登陸成功!',
token: 'Bearer ' + tokenStr,
});
});
};以上是通過nodejs來實(shí)現(xiàn)登錄注冊(cè)的的接口編寫,其他的接口模塊大致上也是相同。
總結(jié)
到此這篇關(guān)于使用node.js實(shí)現(xiàn)接口步驟的文章就介紹到這了,更多相關(guān)node.js實(shí)現(xiàn)接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一會(huì)帶你學(xué)會(huì)用Webpack搭建開發(fā)環(huán)境并打包代碼
這篇文章主要給大家介紹了關(guān)于如何用Webpack搭建開發(fā)環(huán)境并打包的相關(guān)資料,webpack是一個(gè)現(xiàn)代JavaScript應(yīng)用程序的靜態(tài)模塊打包器(module bundler),需要的朋友可以參考下2023-08-08
Express之get,pos請(qǐng)求參數(shù)的獲取
本篇文章主要介紹了Express之get,pos請(qǐng)求參數(shù)的獲取的相關(guān)知識(shí),具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-05-05
node實(shí)現(xiàn)定時(shí)發(fā)送郵件的示例代碼
本篇文章主要介紹了node實(shí)現(xiàn)定時(shí)發(fā)送郵件的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08
Node層模擬實(shí)現(xiàn)multipart表單的文件上傳示例
下面小編就為大家分享一篇Node層模擬實(shí)現(xiàn)multipart表單的文件上傳示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-01-01
淺談Node Inspector 代理實(shí)現(xiàn)
這篇文章主要介紹了淺談Node Inspector 代理實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10
Node.js中利用js-xlsx處理xlsx文件的實(shí)現(xiàn)
js-xlsx庫(kù)是目前Github上star數(shù)量最多的處理Excel的庫(kù),本文介紹用 Node.js中的js-xls庫(kù)來處理Excel文件,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10
詳解nodejs通過響應(yīng)回寫的方式渲染頁(yè)面資源
本篇文章主要介紹了詳解nodejs通過響應(yīng)回寫的方式渲染頁(yè)面資源,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04

