• node开发项目


    1.初始化

    1.1创建项目

    1.新建api_server文件夹作为项目根目录,并在项目根目录中运行如下的命令,初始化包管理配置文件

    npm init -y
    
    • 1

    2.运行如下的命令,安装特定版本的express:

    npm i express@4.17.1
    
    • 1

    3.在项目根目录中新建app.js,作为整个项目的入口文件,并初始化如下代码:

    //导入express
    const express = require('express')
    //创建服务器的实例对象
    const app = express()
    
    //启动服务器
    app.listen(80, ()=> {
        console.log('api server runing at http://127.0.0.1');
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    效果如下:
    在这里插入图片描述

    1.2配置cors跨域

    1.运行如下命令,安装 cors 中间件:

    npm i cors@2.0.5
    
    • 1

    2.在app.js中导入并配置cors中间件:

    //导入cors中间件
    const cors = require('cors')
    //将cors注册为全局中间件
    app.use(cors())
    
    • 1
    • 2
    • 3
    • 4

    1.3配置解析表单数据的中间件

    配置解析表单数据的中间件,注意:这个中间件,只能解析application/x-www-form-urlencoded 格式的表单数据

    app.use(express.urlencoded({extended:false}))
    
    • 1

    1.4初始化路由相关的文件夹

    1.在项目根目录中,新建router文件夹,用来存放所有的路由模块

    	路由模块中,只存放客户端的请求与处理函数之间的映射关系
    
    • 1

    2.在项目根目录中,新建router_handler文件夹,用来存放所有的路由处理函数模块

    	路由处理函数模块中,专门负责存放每个路由对应的处理函数
    
    • 1

    1.5初始化用户路由模块

    1.在router文件夹中,新建user.js文件,作为用户的路由模块,并初始化代码:

    const express = require('express')
    //创建路由对象
    const router = express.Router()
    
    //注册新用户
    router.post('/reguser',(req,res) => {
        res.send('reguser OK')
    } )
    
    router.post('/login',(req,res) => {
        res.send('login OK')
    } )
    
    //将路由对象共享出去
    module.exports = router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.在app.js中,导入 并使用用户路由模块:

    //导入并使用路由模块
    const userRouter = require('./router/user')
    app.use(userRouter)
    
    • 1
    • 2
    • 3

    1.6抽离用户路由模块中的处理函数

    目的:为了保证路由模块的纯粹些,所有的路由处理函数,必须抽离到对应的路由处理函数模块中
    1.在/router_handler/user.js中,使用exports对象,分别向外共享如下两个路由处理函数:

    exports.regUser = (req,res) => {
        res.send('reguser ok')
    }
    
    exports.login = (req,res) => {
        res.send('login ok')
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.引入/router_handler/user.js,将/router/user.js中的代码修改为如下:从而使用/router_handler/user.js下的函数

    //导入用户路由处理函数对应的模块
    const user_handler = require('../router_handler/user')
    
    //注册新用户
    router.post('/reguser',user_handler.regUser )
    
    router.post('/login',user_handler.login )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.登录注册

    2.1新建ev_users表

    在新建表前,我们需要去下载mysql,然后去新建自己的数据库,自动生成mysql workbenc这个可视化界面,通过mysql workbench来新建表

    1.在my_db_01数据库中,新建ev_users表如下:
    在这里插入图片描述
    点击apply创建该表:
    在这里插入图片描述

    2.2安装并配置mysql模块

    在api接口项目中,需要安装并配置mysql这个第三方模块,来链接和操作mysql数据库

    1.运行如下命令,安装mysql模块:

    npm i mysql@2.18.1
    
    • 1

    2.在项目根目录中新建/db/index.js文件,在此自定义模块中创建数据库的连接对象:

    //导入mysql模块
    const mysql = require('mysql')
    
    //创建数据库连接对象
    const db = mysql.createPool({
        host:'127.0.0.1',
        user:'root',
        password:'你创建数据库时的密码',
        database:'my_db_01'
    })
    
    //向外暴露
    module.exports = db
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    2.3注册

    2.3.1检测表单数据是否合法

    1.判断用户名和密码是否为空

        const userinfo =req.body
        //对表单的数据进行合法性校验
        if (!userinfo.username || !userinfo.password) {
            return res.send({
                status:1,
                message:'用户名或密码不合法'
            })
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    我们可以用postman做接口测试该效果是否生效、

    ###2.3.2检测用户名是否被占用
    1.导入数据库操作模块

    const db =require('mysql')
    
    • 1

    2.定义sql语句:

    const sqlStr = 'select * from ev_users where username=?'
    
    • 1

    3.执行sql语句结果判断用户名是否被占用:

    db.query(sqlStr,userinfo.username,(err,results) => {
            //执行sql语句失败
            if (err) {
                return res.send({
                    status:1,
                    message:err.message
                })
            }
            //判断用户名是否被占用
            if (results.length > 0) {
                return res.send({
                    status:1,
                    message:'用户名被占用,请更换其他用户名!'
                })
            }
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.3.3对密码进行加密

    为了保证密码的安全性,不建议在数据库以明文形式保存用户密码,推荐对密码进行加密存储
    在当前项目中,使用 bcryptjs 对用户密码进行加密,优点:
    1.加密之后的密码,无法被逆向破解
    2.同一明文密码多次加密,得到的加密结果各不相同,保证安全性

    1.运行如下命令,安装指定版本的bcryptjs:

    npm i bcryptjs@2.4.3
    
    • 1

    2.在/router_handler/user.js中,导入bcryptjs:

    //导入bcryptjs包加密
    const bcrypt = require('bcryptjs')
    
    • 1
    • 2

    3.在注册用户的处理函数中,确认用户名可用之后,调用bcryptjs.hashSync(明文密码,随机盐的长度)方法,对用户的密码进行加密处理:

          //调用bcrypt.hashSync(),对密码进行加密
            userinfo.password = bcrypt.hashSync(userinfo.password,10)
    
    • 1
    • 2

    2.3.4插入新用户

    1.定义插入用户的sql语句:

    const sql = 'insert into ev_users set ?'
    
    • 1

    2.调用db.query()执行sql语句,插入新用户:

    db.query(sql,{username:userinfo.username,password:userinfo.password},(err,results) => {
                //判断sql语句是否执行成功
                if(err) return res.send({status:1,message:err.message})
                //判断影响行数是否为1,否则错误
                if (results.affectedRows !==1) {
                    return res.send({status:1,message:'注册用户失败,请稍后再试'})
                }
                res.send({
                    status:0,
                    message:'注册成功哈!'
                })
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.4优化代码

    1.在app.js中,所有路由之前,声明一个全局中间件,为res对象挂载一个res.cc()函数:

    //一定要在路由之前封装res.cc函数
    app.use((req,res,next) => {
        //err的值,可能是一个错误对象,也可能是一个错误的表述字符串
        res.cc = (err,status = 1) => {
            res.send({
                status,
                message:err instanceof Error ? err.message : err
            })
        }
        next()
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.5登录

    2.5.0实现步骤

    1.根据用户名查询数据库是否有该用户

    //接收表单数据
        const userinfo = req.body
        //定义sql语句
        const sql = 'select * from ev_users where username=?'
        //执行sql语句,根据用户名查询用户信息
        db.query(sql,userinfo.username,(err,results) => {
            //执行语句失败
            if(err) return res.cc(err)
            //执行sql语句成功,但是获取到的数据条数不等于1
            if (results.length !== 1) {
                return res.cc('登录失败!')
            }
            //判断密码是否正确
            
            res.send('登录成功')
    
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.判断输入密码是否正确
    调用bcrypt.compareSybc(用户提交的密码,数据库中的秘钥)方法比较用户输入的密码和数据库该用户密码是否一致,返回值是布尔值(true一致,false不一致)

    results返回的是匹配到数据库的数据条数,是数组的形式匹配行

    //判断密码是否正确
            const compareResult = bcrypt.compareSync(userinfo.password,results[0].password)
            if (!compareResult) {
                return res.cc('登录失败')
            }
            res.send('登录成功')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.生成jwt的token字符串
    注意点:在生成token字符串的时候,一定要剔除 密码 和 头像 的值
    1.通过es6的高级语法,快速剔除 密码 和 头像 的值:

    const user = {...results[0],password:'',user_pic:''}
    
    • 1

    2.运行命令,安装生成token字符串的包:

    npm i jsonwebtoken@8.5.1
    
    • 1

    3.在/router_hander/user.js模块的头部,导入jsonwebtoken包:

    //导入生成Token的包
    const jwt = require('jsonwebtoken')
    
    • 1
    • 2

    4.创建config.js文件,并向外共享 加密 和 还原 token的 jwtSecretKey字符串:

    module.exports = {
        //加密和解密token的秘钥
        jwtSecretKey:'itheima no1',
        //token有效期
        expiresIn:'10h'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5.将用户信息对象加密成token字符串:

    //导入配置文件
    const config = require('./../config')
    //对用户的信息进行加密,生成token字符串
    const tokenStr = jwt.sign(user,config.jwtSecretKey,{expiresIn:config.expiresIn})
    
    • 1
    • 2
    • 3
    • 4

    6.将生成的token字符串响应给客户端:

     //调用res.send()将token响应给客户端
            res.send({
                status:0,
                message:'登录成功',
                token:'Bearer'+ tokenStr,
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.6 配置解析token的中间件

    1.运行命令,安装token中间件:

    npm i express-jwt@5.3.3
    
    • 1

    2.在app.js中注册路由之前,配置解析token的中间件:

    //一定要在路由之前配置token的中间件
    const expressJWT = require('express-jwt')
    const config = require('./config')
    
    app.use(expressJWT({
        secret:config.jwtSecretKey,
        algorithms:['HS256']
    }).unless({path:[/^\/api\//]}))//unless设置api接口开头的过滤认证
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.在app.js中的 错误级别中间件 里面,捕获并处理token认证失败后的错误:

    //定义错误级别的中间件
    app.use((err,req,res,next) => {
        //验证失败后导致错误
        if (err instanceof Joi.ValidationError) {
            return res.cc(err)
        }   
        //身份认证失败后错误
        if (err.name == 'UnauthorizedError') {
            return res.cc('身份认证失败')
        }
        //未知错误
        res.cc(err)
       })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.个人中心

    3.1获取用户的基本信息

    3.1.0实现步骤

    1.初始化 路由 模块
    2.初始化 路由处理函数 模块
    3.获取用户的基本信息
    
    • 1
    • 2
    • 3

    3.1.1初始化路由模块

    1.创建 /router/userinfo.js路由模块,并初始化如下的代码结构:

    const express = require('express')
    
    const router = express.Router()
    
    //挂载路由
    router.get('/userinfo',(req,res) => {
        res.send('ok')
    })
    
    //共享模块
    module.exports = router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.在app.js中导入并使用个人中心的路由模块:

    //导入并使用用户信息的路由模块
    const userinfoRouter = require('./router/userInfo')
    app.use('/my',userinfoRouter)
    
    • 1
    • 2
    • 3

    3.1.2初始化路由处理函数模块

    1.创建/router_handler/userinfo.js路由处理函数模块,并初始化如下的代码结构:

    exports.getUserInfo = (req,res) => {
        res.send('ok')
    }
    
    • 1
    • 2
    • 3

    2.修改/router/userinfo.js中的代码如下:

    const express = require('express')
    
    const router = express.Router()
    
    //导入路由处理模块
    const userinfo_handler = require('./../router_handler/userinfo')
    
    //挂载路由
    router.get('/userinfo',userinfo_handler.getUserInfo)
    
    //共享模块
    module.exports = router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.1.3 获取用户的基本信息

    1.在/router_handler/userinfo.js头部导入数据库操作模块:

    //导入数据库操作模块
    const db = require('../db/index')
    
    • 1
    • 2

    2.定义sql语句:

        //定义查询用户信息的sql语句
        const sql = `select id,username,nickname,email,user_pic from ev_users where id=?`
    
    • 1
    • 2

    3.调用db.query()执行sql语句:

    //调用db.query()执行sql语句
        db.query(sql,req.user.id,(err,results) => {
            //执行sql语句失败
            if(err) return res.cc(err)
            //执行sql语句成功,但是查询结果可能为空
            if (results.length !== 1) {
                return res.cc('获取用户信息失败!')
            }
            //获取用户信息成功
            res.send({
                status:0,
                message:'获取用户信息成功',
                data: results[0]
    
            })
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.2更新用户的基本信息

    3.2.0实现步骤

    1.定义路由和处理函数
    2.实现更新用户基本信息的功能
    
    • 1
    • 2

    3.2.1定义路由和处理函数

    1.在/router/userinfo.js模块中,新增 更新用户基本信息 的路由:

    在这里插入代码片
    
    • 1

    2.在/routrer_handler/userinfo.js模块中,定义并向外共享 更新用户基本信息 的路由处理函数:

    //更新用户信息的处理函数
    exports.updateUserInfo = (req,res) => {
      res.send('ok')
    }
    
    • 1
    • 2
    • 3
    • 4

    3.2.2实现更新用户基本信息的功能

    1.定义执行的sql语句:

    const sql = `update ev_users set? where id=?`
    
    • 1

    2.调用db.query()执行sql并传参:

     db.query(sql,[req.body,req.body.id],(err,results) => {
          //执行sql语句失败
          if(err) return res.cc(err)
          //执行sql语句成功,但是影响函数不为1
          if (results.affectedRows !== 1) {
              return res.cc('修改用户信息失败!')
          }
          //修改用户信息成功
          return res.cc('修改用户基本信息成功',0)
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.3更新用户头像

    3.3.0实现步骤

    1.定义路由和处理函数
    2.实现更新用户头像的功能
    
    • 1
    • 2

    3.3.1实现更新用户头像的功能

    1.定义更新用户头像的sql语句:

    const sql = `update ev_users set user_pic=? where id=?`
    
    • 1

    2.调用db.query()执行sql语句,更新对应用户的头像(这里接口传的avatar可以是图片base64的格式):

       //调用
        db.query(sql, [req.body.avatar, req.user.id], (res, results) => {
            //执行sql语句失败
            if (err) return res.cc(err)
            //执行sql语句成功,但是影响函数不为1
            if (results.affectedRows !== 1) {
                return res.cc('更换头像失败!')
            }
            //修改用户头像成功
            return res.cc('更换头像成功', 0)
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    感谢观看,有帮助的话点点赞点点关注谢谢哈。

  • 相关阅读:
    Flink处理函数(一)
    Docker 搭建Redis 踩坑
    app小程序手机端Python爬虫实战09通过U2实现移动设备九宫格解锁
    Vue3 源码解读系列(十一)——插槽 slot
    详细Ubuntu16~20TLS安装NVIDIA驱动教程
    [附源码]JAVA毕业设计论文管理系统(系统+LW)
    Chapter13 : Ultrahigh Throughput Protein-Ligand Docking with Deep Learning
    负载均衡(DR)
    解决LicheeRV 86 Panel在tina2.0配置lcd GPIO引脚及colorbar闪屏的问题
    CSPM考试时间是什么时候?好考吗?
  • 原文地址:https://blog.csdn.net/weixin_44161385/article/details/127421021