Node.js Koa2 MongoDB Redis egg.js

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Node.js Koa2 MongoDB Redis egg.js

基于Chrome V8引擎的JavaScript运行时

  • V8是chrome的js引擎,以速度著称
  • 运行时:代码的运行环境
  • 之前只有浏览器能运行js

    安装node

  • nodejs.cn
  • msi
  • node -v

    npm

  • node package manage nodejs软件包管理工具
  • npmjs.com
  • 会随着nodejs一起被安装
  • npm init 生成package.json其中包括项目所有依赖

    nodemon

  • 当检测到目录中的文件更改时,它会自动重启node应用程序。
  • npm i nodemon --save-dev
  • 使用了nodemon 就可以使用npm run dev ,只有node,使用node xx.js

    common.js ES6模块化

    注意导出用{},导入也要用{}接收
    image.png

image.png

image.png

image.png

const sum =required(./地址)//多个用大括号
module.exports={
   
   sum,text}

区别

image.png

image.png

image.png这个会报错,ES Module必须放在最外层

nodejs debug

image.png

image.png

image.png

image.png

node处理http

image.png

image.png

image.png

image.png

image.png

Get请求

  • 引入queryString
  • queryString.parse(str)产生一个包含键值对的对象

    Post请求体通过流的形式

    Koa2 框架

  • 安装脚手架 npm i -g koa-generator //-g全局安装
  • 查看是否安装成功 koa2 --version
  • cd到文件夹在命令行输入koa2
  • 在命令行输入npm i / npm run start
  • 访问http://localhost:3000/
  • app.use(...)里都是中间件
  • 每个中间件都是async函数

    写一个接口(动态参数)

  • 在routes文件夹下新建js文件
const router = require('koa-router')()
router,prefix('/api')
router.get('/json', async (ctx) => {
   
   
  ctx.body = 'api list'
})
//ctx是res,rep的集合。ctx.query可以获取到queryString/ctx.request.body获取请求体
router.get('/:id',loginCheck,async function (ctx,next){
   
   
const id = ctx.params.id
const address = await getAddressById(id)
ctx.body = new SuccessModel(address)
})
module.exports = router
//数据库里tabs:[all,a,b,c] in里面的内容表示tabs属性要包含all
const list =await Product.find({
   
   shopId,tabs:{
   
   
 $in:all
}}).sort( _id:-1)
//数据库里_id是一个字符串,in里是一个数组,表示_id在这个ids数组中就能被找到
const list =await Product.find({
   
   shopId,_id:{
   
   
 $in:ids
}})
  • 在app.js里引入,注册
const index = require('./routes/index')
app.use(index.routes(), index.allowedMethods())

svg验证码

svg-captcha

 ctx.body = svgCaptcha.create({
   
   
    size:5,
    ignoreChars:'0olil',
    color:true,
    noise:3
  }).data

邮箱nodemailer

npm i nodemailer -S
配置文件

module.exports = {
   
   
    host: 'smtp.qq.com',
    port: 465,
    secure: true,
    auth: {
   
   
      user: '2252647301@qq.com',
      pass: 'aptwbjjnhvlqdjjg'
    }
  };

在route里引入使用

const nodemailer = require('nodemailer');
const config = require('../mailconfig.js');

router.get('/string', async (ctx, next) => {
   
   
  const mailOptions = {
   
   
    from: '2252647301@qq.com',
    to: '2252647301@qq.com',
    subject: 'Test email',
    text: 'This is a test email',
    html: `<title>HTML email</title>`
  };
  const transporter = nodemailer.createTransport(config);
  try {
   
   
    const info = await transporter.sendMail(mailOptions);
    console.log('Email sent: ' + info.response);
    ctx.body = {
   
    success: true };
  } catch (error) {
   
   
    console.log(error);
    ctx.body = {
   
    success: false };
  }
})
后续要封装成方法

密码加密

//封装成一个加密方法
const crypto=require('crypto')
module.exports = str=> crypto.createHash('md5').update(str).digest('hex')

  password: {
   
   
        type:String,
        required:true,
        set:value=>md5(value),
        select:false//以后都不会返回密码
    }//这样存入数据库的技术加密后的密码

中间件

app.use(async (ctx, next) => {
   
   
  const start = new Date()
  await next()//只有await执行完之后才能执行之后的代码,next()表示执行下一个中间件
  const ms = new Date() - start
  console.log(`${
     
     ctx.method} ${
     
     ctx.url} - ${
     
     ms}ms`)
})
//多个中间件(p1,p2),按顺序执行next之前的代码,之后回过头来执行p2里next后的方法,p1里的next之后的方法

MongoDB

  • mongodb.com production 社区服务 msi
  • 接受条框后点Custom
  • 不要勾选MongoDB compass
  • 如果失败重新安装
  • 如果弹出错误忽略

image.png

  • 查看安装的MongoDB文件夹是是否有data log文件夹没有就新建,在data里新建db文件夹,在log里新建mongod.log
  • 在bin文件夹下打开控制台输入启动mongo//mongodb.exe可关,mongod.exe不能关

image.png

  • 图形界面,在官网sofeware下载compass 打开点击connect
  • 如果连接失败,把data里的db里的mongod.lock删除,重新启动

    使用compass

    collect约等于表,document约等于表里的一项数据
  • create database
  • create collection
  • 查询

image.png

  • 排序 1正序 -1逆序

image.png

MongoDB连接nodejs

  • 安装npm i mongodb --save
// nodejs 连接 mongodb
// 体会 nodejs 连接 mongodb 的能力,不会真正的用到路由上
// mongoose 对接路由的功能

const MongoClient = require('mongodb').MongoClient

const url = 'mongodb://localhost:27017' // 本地启动的 mongodb 服务
const dbName = 'comment1' // 数据库(留言板项目的数据库 )

MongoClient.connect(url, {
   
   
    useUnifiedTopology: true,
    useNewUrlParser: true
}, (err, client) => {
   
   
    if (err) {
   
   
        console.error('mongodb 连接出错', err)
        return
    }
    console.log('mongodb 连接成功')

    // 切换数据库 database
    const db = client.db(dbName)

    // 切换到指定的集合 collection
    const userCollection = db.collection('users')

    // // 查询数据
    // userCollection.find().sort({ _id: -1 }).toArray((err, result) => {
   
   
    //     if (err) {
   
   
    //         console.error('查询数据出错', err)
    //         return
    //     }
    //     console.log('查询结果', result)
    // })

    // // 新增数据
    // userCollection.insertOne({
   
   
    //     username: 'shuangyue',
    //     password: 'abc',
    //     age: 30,
    //     city: 'beijing'
    // }, (err, result) => {
   
   
    //     if (err) {
   
   
    //         console.error('插入数据出错', err)
    //         return
    //     }
    //     console.log('插入后的返回结果', result.insertedCount, result.insertedId)//插入数量,插入的数据id
    // })

    // // 修改数据
    // userCollection.updateOne(
    //     { username: 'zhangsan' }, // 修改的条件
    //     { $set: { age: 21 , city: 'beijing'} }, // 修改的内容
    //     (err, result) => {
   
   
    //         if (err) {
   
   
    //             console.error('修改数据出错', err)
    //             return
    //         }
    //         console.log('修改后的返回结果', result.modifiedCount)
    //     }
    // )

    // 删除数据
    userCollection.deleteOne({
   
    username: 'wangwu' }, (err, result) => {
   
   
        if (err) {
   
   
            console.error('删除数据出错', err)
            return
        }
        console.log('删除成功')
    })

    // 关闭
    // client.close()
})

规范连接 mongoose

image.png

  • 在文件夹路径上唤出控制台,输入npm i mongoose --save
  • 新建文件夹,新建js文件
  • 一定要先启动mongod.exe

image.png

image.png
db.js

// 连接数据库(mongodb 的服务端)

const mongoose = require('mongoose')

const url = 'mongodb://localhost:27017'
const dbName = 'comment2'

mongoose.set('useCreateIndex', true)
mongoose.set('useFindAndModify', true)

// 开始连接
mongoose.connect(`${
     
     url}/${
     
     dbName}`, {
   
   
    useNewUrlParser: true,
    useUnifiedTopology: true
})

const conn = mongoose.connection

conn.on('error', err => {
   
   
    console.error('mongoose 连接出错', err)
})

module.exports = mongoose

创建schema,定义了model会自动创建collection加一个s
model.js

// 数据模型(规范数据格式)

const mongoose = require('./db')

// 定义 User Schema (数据规范)
const UserSchema = mongoose.Schema({
   
   
    username: {
   
   
        type: String,
        required: true, // 必需
        unique: true // 唯一,不重复
    },
    password: String,
    age: Number,
    city: String,
    // 性别
    gender: {
   
   
        type: Number,
        default: 0 // 0 - 保密,1 男,2 女
    }
}, {
   
   
    timestamps: true // 时间戳,自动添加文档的创建时间、更新时间
})

// 定义 User Model
const User = mongoose.model('user', UserSchema)

// 定义 Comment Schema
const CommentSchema = mongoose.Schema({
   
   
    content: {
   
   
        type: String,
        required: true // 必需
    },
    username: String // 用户名
}, {
   
    timestamps: true })

// 定义 Comment Model
const Comment = mongoose.model('comment', CommentSchema)

module.exports = {
   
   
    User,
    Comment
}

新建文件夹查询新增

// 使用 model 操作数据

const {
   
    User } = require('./model')

// 定义一个 async 的匿名函数,并执行。为了里面能用 await
!(async () => {
   
   
    // // 新增数据 - 1
    // const zhangsan = new User({
   
   
    //     username: 'zhangsan',
    //     password: 'abc',
    //     age: 20,
    //     city: 'beijing',
    //     gender: 1
    // })
    // zhangsan.save()

    // // 新增数据 - 2
    // const lisi = await User.create({
   
   
    //     username: 'lisi',
    //     password: '123',
    //     age: 23,
    //     city: 'shanghai'
    // })
    // console.log('lisi 创建完成', lisi)

    // // 查询列表数据,返回的是数组
    // const userList = await User.find({ username: 'zhangsan' })
    // const userList = await User.find().sort({ _id: -1 })
    // console.log('userList 查询结果', userList)

    // 查询单条数据,返回的对象
    const user = await User.findOne({
   
    username: 'zhang' })
    console.log('user 查询结果', user)
})()

新建文件夹更新删除

// 使用 model 操作数据

const {
   
    User } = require('./model')

// 定义一个 async 的匿名函数,并执行。为了里面能用 await
!(async () => {
   
   
    // // 更新
    // const updateResult = await User.findOneAndUpdate(
    //     { username: 'zhangsan' }, // 条件
    //     { age: 30 }, // 更新的内容
    //     {
   
   
    //         new: true // 返回更新后的数据
    //     }
    // )
    // console.log('更新的返回结果', updateResult)

    // // 删除
    // const removeResult = await User.remove({ username: 'lisi' })
    // console.log('删除的返回结果', removeResult)
})()

session cookie

cookie

image.png
在koa2使用cookie

image.png
session是在服务端存储的用户信息

image.png

image.png
image.png

koa2使用session,解决跨域

  • npm i koa-generic-session --save// npm i koa2-cors --save
  • 通过ctx.session使用session
  • 在appjs写
const session = require('koa-generic-session')
const cors = require('koa2-cors')
//cors配置
app.use(cors({
   
   
    origin: 'http://localhost:8080',//前端origin
    credentials:true //允许跨域带cookie
}))
//session配置
app.keys = ['wertwe^&&*UUI123123'] // 秘钥
    // 自定配置了 cookie 和 session
app.use(session({
   
   
    // 配置 cookie
    cookie: {
   
   
        path: '/', // cookie 在根目录下有效
        httpOnly: true, // cookie 只允许服务端来操作
        maxAge: 24 * 60 * 60 * 1000 // cookie 的过期时间
    }
}))
  • 在controller层设置session ctx.session.userInfo={username}
  • 使用session的数据 const username = ctx.session.userInfo.username

    开发流程

    数据库

  • mongodb创建数据库和集合
  • 使用mongoose定义schema和model

    规范目录

    新建文件夹
    image.png
    image.png
  • 移动之后在bin-www修改app require('../src/app')

    统一返回类

    成功
    class SuccessModel{
         
         
     constructor(data){
         
         
     this.errno = 0
     if(data!=null){
         
         
     this.data=data
     }
    }
    }
    module.exports = SuccessModel
    
    失败
    class ErrorModel{
         
         
     constructor(errno=-1,message='error'){
         
         
     this.errno = errno
     this.message=message
    }
    }
    module.exports = ErrorModel
    
    如何使用
ctx.body = new SuccessModel(data)
ctx.body = new ErrorModel(10001,`注册失败 - ${
     
     ex.message}`)

登录验证中间件

image.png

router.get('/:id',loginCheck,async function (ctx,next)//loginCheck是中间件,使用前需要require。如果没登陆,不允许访问

Redis

发布订阅
subscribe zhang fang 监听多个管道
publish zhang "hello" 发送信息

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
NoSQL 前端开发 JavaScript
Node.js 连接 MongoDB
10月更文挑战第20天
37 0
|
2月前
|
NoSQL 前端开发 JavaScript
Node.js 连接 MongoDB
10月更文挑战第9天
52 0
|
2月前
|
JavaScript NoSQL 前端开发
使用 Node.js 和 MongoDB 构建实时聊天应用
【10月更文挑战第2天】使用 Node.js 和 MongoDB 构建实时聊天应用
|
4月前
|
JavaScript NoSQL 前端开发
|
5月前
|
存储 开发框架 JavaScript
Node中的AsyncLocalStorage 使用问题之egg.js 和 midwayjs 与 Koa.js 有什么关系
Node中的AsyncLocalStorage 使用问题之egg.js 和 midwayjs 与 Koa.js 有什么关系
|
5月前
|
前端开发 NoSQL 数据库
部署常用的流程,可以用后端,连接宝塔,将IP地址修改好,本地只要连接好了,在本地上前后端跑起来,前端能够跑起来,改好了config.js资料,后端修改好数据库和连接redis,本地上跑成功了,再改
部署常用的流程,可以用后端,连接宝塔,将IP地址修改好,本地只要连接好了,在本地上前后端跑起来,前端能够跑起来,改好了config.js资料,后端修改好数据库和连接redis,本地上跑成功了,再改
|
5月前
|
NoSQL JavaScript 前端开发
JavaScript与数据库MongoDB的联动
JavaScript和MongoDB结合,构建Web应用的关键技术。MongoDB,作为NoSQL数据库,以其灵活性和高性能深受开发者喜爱。本文探讨两者的基本概念,如JavaScript在前端交互和后端数据处理的作用,MongoDB的文档存储和查询特性。通过Node.js和mongoose库,展示了连接数据库、定义数据模型及增删改查操作的代码示例。强调了性能优化(如索引、批量操作)和安全措施(如权限控制、数据加密)的重要性。最后,提供了一个简单的CRUD应用示例,涵盖Express和前端API调用。
55 0
|
20天前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
20 1
JavaScript中的原型 保姆级文章一文搞懂
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
101 2
|
16天前
JS+CSS3文章内容背景黑白切换源码
JS+CSS3文章内容背景黑白切换源码是一款基于JS+CSS3制作的简单网页文章文字内容背景颜色黑白切换效果。
15 0