其实温习一次的作用实在太大了,真的,自从上次ajax开始其实就开始i有点懵懵懂懂的感觉,始终拖想到了node在去回顾一遍,这一次回去温习,ajax曾经很纯熟了,node之前搞不懂那些原理也顺分明了好多,其实这次温习没有什么须要说的知识点,因为要说的后面都说过了,我来说一下这个做的一个大我的项目吧,这个我的项目真的,应该是我不纯熟的违心那边,就是用express写接口,用postman来测试,三个模块,三个数据库,基本上都在我的代码外面了,写的很具体步骤,用到的技术,基本上是用node的express模块,去写接口,而后中途中到了一些中间件,比方规定语义规定的joi,比方给明码解码加密的bcryptjs,我做了一天才做下来这一个案例

一个我的项目初试化,首先要创建一个独自的我的项目文件夹,而后终端npm init间接装置package.json,api.js接口文件,路由模块创建一个文件夹夹,路由函数又要分为一个模块,再把数据库创建好,根本就能够开始实现性能需要了,用后端node实现增删改查

我的项目文件分类:

1

接口文件

// 1.初始化// 1.1创立我的项目const express = require('express')const app = express()// 1.2配置跨域const cors = require('cors')app.use(cors())// 1.3配置解析表单中间件// 谬误点:记住要有参数app.use(express.urlencoded({extended : false}))// 2.3因为前面处理函数用到了很多res.send所以封装为一个全局中间件,给res绑定一个函数,那前面的中间件路由都能够用到这个函数了app.use((req, res, next) => {    res.cc = function(err, status = 1) {        res.send({            status,            msg : err instanceof Error ? err.message : err        })    }    next()})// 2.4.6配置解析token的中间件const expressJWT = require('express-jwt')const secretKey = require('./secretKey')app.use(expressJWT({secret : secretKey.secretKey, algorithms : ['HS256']}).unless({path : [/^\/api\//]}))// 1.4.4导入路由模块const routerUser = require('./router/user')const Joi = require('joi')const { expressjwt } = require('express-jwt')const { path } = require('express/lib/application')app.use('/api', routerUser)// 3.1.1集体核心路由导入const infoRouter = require('./router/userinfo')app.use('/my', infoRouter)// 4.1.2文章治理导入const article = require('./router/acticle')app.use('/my/article', article)// 5.1.2公布文章路由导入const cates = require('./router/cate')app.use('/my/article', cates)// 2.2.3定义规定joi的谬误级别中间件app.use((err, req, res, next) => {    if (err instanceof Joi.ValidationError) return res.send(err.message)    // 2.4.7减少jwt谬误中间件    if (err.name == 'UnauthorizedError') return res.cc('身份认证失败')    return res.send('其余谬误')})app.listen(80, () => {    console.log('http://127.0.0.1');})

2.

写好接口文件该去给路由创立模块

// 1.4初始化路由相干文件夹 不光要给路由分装一个模块 外面的处理函数也要有一个模块const express = require('express')const { append } = require('express/lib/response')const router = express.Router()// 1.4.2导入路由处理函数const routerHandler = require('../router_handler/user')// 注册// 2.2.2导入joi验证输出进来的是否非法const expressJOI = require('@escook/express-joi')const {schema_user_info} = require('../schema/user')router.post('/reguser',expressJOI(schema_user_info), routerHandler.getReguser)// 2.4登录// 2.4.1增加语法规定,能够间接用注册的router.post('/login',expressJOI(schema_user_info), routerHandler.getLogin)module.exports = router

3.

处理函数模块

// 1.4.1初始化路由处理函数模块//注册const db = require('../mysql')//导入明码加密解密包const bcrypt = require('bcryptjs')function getReguser(req, res) {    // res.send('这里是注册模块')    // 2.2.4检测用户名是否被占用 导入mysql    let selectUser = 'select * from users where username = ?'    db.query(selectUser, req.body.username, (err, results) => {        // 2.3.1用到咱们后面定义的全局中间件优化res.send        if (err) return res.cc(err)        if (results.length == 1) return res.cc('用户名已被占用')        // 2.2.5如果过了前两关的验证 根本能够验证胜利了 就先对明码进行加密解决装置bcryptjs        req.body.password = bcrypt.hashSync(req.body.password, 10)        // console.log(req.body.password);        // 2.2.6插入新用户        let insertUser = 'insert into users set ?'        // -------------留神一下这里插入数据库的参数怎么写的        db.query(insertUser, [{username : req.body.username, password : req.body.password}], (err, results) => {            if (err) return res.cc(err)            if (results.affectedRows !== 1) return res.cc('注册失败')            res.cc('注册胜利',0)        })    })}//登录// 2.4.4.1导入jwtconst jwt = require('jsonwebtoken')const secretKey = require('../secretKey')const { result } = require('@hapi/joi/lib/base')function getLogin(req, res) {    // res.send('这里是登录模块')    // 2.4.2依据用户名查问用户的数据    let selectLoginuser = 'select * from users where username = ?'    db.query(selectLoginuser, req.body.username, (err, results) => {        if (err) res.cc(err)        if (results.length !== 1) res.cc('未找到该用户')        // 2.4.3有数据就去判断明码是否正确        // console.log(results);        if (!bcrypt.compareSync(req.body.password, results[0].password)) return res.cc('明码谬误')        // 2.4.4用户名有,明码 也对上了阐明登陆胜利,开始jwt身份认证        // 先剔除明码和头像的值        let user = {...results[0], password : '', user_pic: '',algorithms : ['HS256']}        let userToken = jwt.sign(user, secretKey.secretKey, {expiresIn : '1h'})        // 2.4.5向客户端发送token        res.send({            status : 0,             msg : '登录胜利',            token : 'Bearer ' + userToken        })    })}// 获取用户根本信息function getInfo(req,res) {    // res.send('集体核心')    // 3.1.2获取用户根本信息    let selectInfo = 'select id,username,nickname,email,user_pic from users where id = ?'    db.query(selectInfo, req.user.id, (err, results) => {        if (err) return res.cc(err)        if (results.length !== 1) return res.cc('获取信息失败')        res.send({            status : 0,            msg : '获取信息胜利',            data : results[0]        })    })}// 3.2更新用户信息function updateInfo(req, res) {    // res.send('更新用户信息')    // 3.2.4更新用户性能    let updateInfo = 'update users set ? where id = ?'    db.query(updateInfo, [req.body, req.user.id], (err, results) => {        if (err) return res.cc(err)        if (results.affectedRows !== 1) return res.cc('更新信息失败')        res.cc('更新信息胜利', 0)    })}// 3.3重置明码function updatePwd(req, res) {    // res.send('重置明码')    // 3.3.2查问用户是否存在    let selectExist = 'select * from users where id = ?'    db.query(selectExist, req.user.id, (err, results) => {        if (err) return res.cc(err)        if (results.length !== 1) return res.cc('用户不存在')        // 3.3.3后面那一步尽管无所谓但这一步必须的 判断输出的旧明码是否正确        if(!bcrypt.compareSync(req.body.oldPwd, results[0].password)) return res.cc('输出明码谬误')        // 3.3.4对新密码加密后更新到数据库        let password = bcrypt.hashSync(req.body.newPwd)        let updatePwd = 'update users set password =? where id =?'        db.query(updatePwd, [password,req.user.id], (err, results) => {            if (err) return res.cc(err)            if (results.affectedRows !== 1) return res.cc('批改明码失败')            res.cc('更新明码胜利', 0)        })    })}// 3.4更换头像function updateAvatar(req, res) {    // res.send('更换头像')    // 3.4.3    let updateAvatar = 'update users set user_pic = ? where id = ?'    db.query(updateAvatar, [req.body.avatar, req.user.id], (err, results) => {        if (err) return res.cc(err)        if (results.affectedRows !== 1) return res.cc('更新头像失败')        res.cc('更新头像胜利', 0)    })}module.exports = {    getLogin,    getReguser,    getInfo,    updateInfo,    updatePwd,    updateAvatar}

4.

这个时候就能够去api入口文件测试一下了,而后在数据库写好咱们的数据表,创建一个js文件链接数据库

// 2.登录注册// 2.1建好数据库后配置数据库const { result } = require('@hapi/joi/lib/base')const mysql = require('mysql')const db = mysql.createPool({    host : '127.0.0.1',    user : 'root',    password : 'admin123',    database : 'mydb'})// 测试/* db.query('select 1' , (err, results) => {    if(err) return console.log(err.message);    return console.log(results);}) */module.exports = db

5.

没记错的话,在登录接口应该应用jwt认证机制生成token吧

const express = require('express')const router = express.Router()const routerHandler = require('../router_handler/user')// 3.集体核心// 3.1获取用户根本信息router.get('/userinfo', routerHandler.getInfo)// 3.2.1更新用户信息// 3.2.3增加验证规定const expressJoi = require('@escook/express-joi')const {schema_update_info, schema_update_avatar} = require('../schema/user')router.post('/userinfo',expressJoi(schema_update_info),routerHandler.updateInfo)// 3.3.1重置明码const {schema_update_pwd} = require('../schema/user')router.post('/updatepwd',expressJoi(schema_update_pwd), routerHandler.updatePwd)// 3.4.1更换头像const {schema_updatee_avatar} = require('../schema/user')router.post('/update/avatar',expressJoi(schema_updatee_avatar), routerHandler.updateAvatar)module.exports = router

token的验证规定

module.exports = {    secretKey : 'sdfafsfds'}

下面就是整个user局部的接口了包含登录注册,增加删除批改账号或者明码等,上面是咱们的user的验证规定

// 2.2注册// 2.2.1对表单数据验证,这里就不if else了间接用上joi来验证 joi要下最新版而且间接导入joiconst { number } = require('joi')const joi = require('joi')const username = joi.string().alphanum().min(1).max(10).required()// 谬误点:正则{}外面的量词之间不能以空格隔开const password = joi.string().pattern(/^[\S]{6,12}$/).required()// 3.2.2更新用户信息规定const id = joi.number().integer().min(1).required()const nickname = joi.string().required()const email = joi.string().email().required()// 3.4.2更换头像规定const avatar = joi.string().dataUri().required()module.exports.schema_user_info = {    body : {        username,        password    }}module.exports.schema_update_info = {    body : {        id,        nickname,        email    }}module.exports.schema_update_pwd = {    // 3.3.2重置明码规定    body : {        oldPwd : password,        // --------------谬误点这里就算是变量也要增加引号        newPwd : joi.not(joi.ref('oldPwd')).concat(password)    }}module.exports.schema_updatee_avatar = {    body : {        avatar    }}

6.

这个局部是对文章的名字和别名的增删改查的操作了,这外面的难点在于要去了解那个怎么来判断是否重名哪里

// 4.1.1文章分类列表函数const { result } = require('@hapi/joi/lib/base')const db = require('../mysql')function getArticleList(req, res) {    // res.send('文章分类列表')    // 4.1.3获取文章数据    let selectArticleList = 'select * from article where is_delete = 0'    db.query(selectArticleList, (err, results) => {        if (err) return res.cc(err)        res.send({            status : 0,            msg : '获取文章分类列表胜利',            data : results        })    })}// 4.2.1新增文章分类function addCates(req,res) {    // 4.2.3名字与别名是否重名    let selectDuplicate = 'select * from article where name = ? or alias = ?'    db.query(selectDuplicate, [req.body.name, req.body.alias], (err, results) => {        if(err) return res.cc(err)        if(results.length == 2) return res.cc('文章名字和别名已被占用')        if(results.length == 1 && results[0].name == req.body.name && results[0].alias == req.body.alias) return res.cc('文章名字和别名已被占用')        if(results.length == 1 && results[0].name == req.body.name) return res.cc('文章名字被占用')        if(results.length == 1 && results[0].alias == req.body.alias) return res.cc('文章别名被占用')        // 4.2.4实现文章分类新增        let addArt = 'insert into article set ?'        db.query(addArt, req.body, (err, results) => {            if(err) return res.cc(err)            if (results.affectedRows !== 1) return res.cc('新增文章失败')            res.cc('新增文章分类胜利', 0)        })    })}// 4.3.1依据idshanchuwenzhanfunction deleteCate(req, res) {    // 4.3.3实现删除性能    let deleteId = 'update article set is_delete = 1 where id = ?'    db.query(deleteId, req.params.id, (err, results) => {        if (err) return res.cc(err)        if (results.affectedRows !== 1) return res.cc('删除文章失败')        res.cc('删除文章分类胜利', 0)    })}// 4.4.1依据id获取文章分类function requireArt(req,res) {    // 4.4.2    let selectArt = 'select * from article where id = ?'    db.query(selectArt, req.params.id, (err, results) => {        if (err) return res.cc(err)        if (results.length !== 1 || results[0].is_delete == 1) return res.cc('没有该文章')        res.send({            status : 0,            msg : '获取文章分类数据胜利',            data : results[0]        })    })}// 4.5.1依据id更新文章function updateArt(req, res) {    // 4.5.2查看是否重名    // -----------------这里须要先将本人这一项排除进去    let selectIdDuplicate = 'select * from article where id != ? and (name = ? or alias = ?)'    db.query(selectIdDuplicate, [req.body.id, req.body.name, req.body.alias], (err, results) => {        if (err) return res.cc(err)        if (results.length == 2) return res.cc('文章名称和别名已被占用')        if (results.length == 1 && results[0].name == req.body.name && results[0].alias == req.body.alias) return res.cc('文章名称和别名已被占用')        if (results.length == 1 && results[0].name == req.body.name) return res.cc('文章名称已被占用')        if (results.length == 1 && results[0].alias == req.body.alias) return res.cc('别名已被占用')        let updateIdArt = 'update article set ? where id = ?'        db.query(updateIdArt, [req.body, req.body.id] , (err,results) => {            if (err) return res.cc(err)            if (results.affectedRows !== 1) return res.cc('文章更新失败')            res.cc('更新分类信息胜利', 0)        })    })}module.exports = {    getArticleList,    addCates,    deleteCate,    requireArt,    updateArt}

这是路由模块,下面是路由的处理函数

// 4.文章类别治理const express = require('express')const router = express.Router()const routerhanlder = require('../router_handler/article')// 4.1获取文章分类列表router.get('/cates',routerhanlder.getArticleList)// 4.2新增文章分类const expressJoi = require('@escook/express-joi')const {add_article_list, update_id_cate} =require('../schema/article')router.post('/addcates',expressJoi(add_article_list),routerhanlder.addCates)// 4.3依据id删除文章const {delete_id_cate} = require('../schema/article')router.get('/deletecate/:id',expressJoi(delete_id_cate),routerhanlder.deleteCate)// 4.4依据id获取文章分类数据router.get('/cates/:id',expressJoi(delete_id_cate), routerhanlder.requireArt)// 4.5依据id更新文章分类数据const {update_id_Art} = require('../schema/article')router.post('/updatecate',expressJoi(update_id_Art) ,routerhanlder.updateArt)module.exports = router

而后咱们的规定

const joi = require('joi')// 4.2.2新增文章规定const name = joi.string().required()const alias = joi.string().alphanum().required()// 4.3.2依据id删除文章 留神这个id是动静的而且是get申请,所以不再是body数据const id = joi.number().integer().min(1).required()module.exports.add_article_list = {    body : {        name,        alias    }}module.exports.delete_id_cate = {    params : {        id    }}module.exports.update_id_Art = {    body : {        id : id,        name : name,        alias : alias    }}

7.

最初是咱们的增加文章这个性能,就是往每一个方才创立好的文章外面,增加新文章,间接看逻辑的实现吧

// 5.1.1公布文章函数const path = require('path')const db = require('../mysql')function addCate(req, res) {    // 5.1.5因为上传表单无奈用joi所以要独自规定    if (!req.file || req.file.fieldname !== 'cover_img') return res.cc('请上传图片')    // 5.1.6当时公布文章性能    const cateObj = {        ...req.body,        cover_img : path.join('/uploads', req.file.filename),        pub_date : new Date(),        author_id : req.user.id    }    let addInsert = 'insert into articles set ?'    db.query(addInsert,  cateObj, (err, results) => {        if (err) return res.cc(err)        if (results.affectedRows !== 1) return res.cc('公布文章失败')        res.cc('公布文章胜利', 0)    })    }module.exports = {    addCate}
// 1.4初始化路由相干文件夹 不光要给路由分装一个模块 外面的处理函数也要有一个模块const express = require('express')const { append } = require('express/lib/response')const router = express.Router()// 1.4.2导入路由处理函数const routerHandler = require('../router_handler/user')// 注册// 2.2.2导入joi验证输出进来的是否非法const expressJOI = require('@escook/express-joi')const {schema_user_info} = require('../schema/user')router.post('/reguser',expressJOI(schema_user_info), routerHandler.getReguser)// 2.4登录// 2.4.1增加语法规定,能够间接用注册的router.post('/login',expressJOI(schema_user_info), routerHandler.getLogin)module.exports = router