随笔 - 121  文章 - 0  评论 - 5  阅读 - 49347

【Koa】 基于Node.js 的开发框架

1. 初始化项目 npm init -y

1.1  或者使用脚手架  npm install -g koa-generator 全局安装  【使用框架就无需执行其他命令 1/2/3.... 】

  生成项目 koa2 <projectname>    projectname即为项目名

  这里可能需要再 package.json 中 改一下 dev 的 启动命令 反正我 windows不支持 得改一下

2. 安装 npm install koa

3. 使用  因为遵循的是Commonjs 而不是 vue 那样的 ES module 所以不能用 import 而是使用 require

  const koa = require('koa');

  const app = new koa()

3. 洋葱模型
  Koa 的 中间件遇到 next() 向后执行,但当前函数并未执行完,在后续函数执行完后会先执行当前函数的后续代码然后向前倒推
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
app.use((ctx, next) => {
    console.log('1-1')
    next()
    console.log('1-2')
})
 
app.use((ctx, next) => {
    console.log('2-1')
    next()
    console.log('2-2')
})
 
app.use((ctx, next) => {
    console.log('3-1')
    next()
    console.log('3-2')
})

  打印结果

1
2
3
4
5
6
1-1
2-1
3-1
3-2
2-2
1-2

4. 中间件

  app.use() 用于注册中间件

  中间件是处理http请求和响应的函数

  上下文对象 ctx(content) 包含了当前 http 请求相关的所有信息

1
2
3
4
// 添加中间件
app.use(async ctx => {
     ctx.body = 'hellow, world'
})

5. 路由

  安装

    使用 npm i koa-router 兼容koa1 和 koa2 的历史版本

    npm i @koa/router 专门为koa2设计的新版本

  引入

    const Router = require('koa-router'); 或者  const Router = require('@koa/router');

  初始化实例 并且为所有路由添加统一前缀

1
2
3
4
// 添加路由统一前缀
const router = new Router({
    prefix: '/api'
})

  使用

app.use(router.routes()).use(router.allowedMethods())
如果客户端尝试对 /users 发送 DELETE 请求,由于我们没有定义 DELETE 方法的路由,allowedMethods() 会自动返回 405 状态码,并在 Allow 头中指出支持的方法(GET 和 POST)。

  接口

    GET请求

1
2
3
4
5
6
7
8
// query 传参
// http://localhost:3000/api/query?id=2&web=baidu.com
//
router.get('/query', async(ctx) => {
    let id = ctx.query.id
    let web = ctx.query.web
    ctx.body = id + ':' + web
})

 

  

1
2
3
4
5
6
7
8
// params 传参
// http://localhost:3000/api/params/id/web/baidu.com
//
router.get('/params/:id/web/:web', async(ctx) => {
    let id = ctx.params.id
    let web = ctx.params.web
    ctx.body = id + ':' + web
})

  

  POST请求

    使用POST请求需要安装 bodyparser 来解析body信息

    安装  npm i @koa/bodyparser

    使用   

const BodyParser = require('koa-bodyparser'); //body解析中间件
const bodyparser = new BodyParser();
app.use(bodyparser)

  接口

复制代码
router.post('/submitInfo', async (ctx) => {
    let params = ctx.request.body
    if(params) {  
        data.push(params)
        ctx.body = {
            code: 200,
            message: '提交成功'
        }
    } else {
        ctx.body = {
            code: 500,
            message: '提交失败'
        }
    }
})
复制代码

 

  重定向

1
2
// 重定向路由
router.redirect('/test', 'https://www.baidu.com')

  404 处理

1
2
3
4
5
6
7
// 在所有路由之后添加404处理函数
app.use(async ctx => {
    if(!ctx.body) {
        ctx.status = 404
        ctx.body = '404 Not Found'
    }
})

5. 错误处理

  由于洋葱模型 会先执行后面next()里代码 出问题后还会回到catch中

复制代码
// 错误处理中间件
app.use(async (ctx, next) => {
    try {
        await next()
    }
    catch (err) {
        ctx.status = 500
        ctx.body = 'error' + err.message
    }
})
复制代码

  更推荐使用中间件 koa--json-error 

6. 跨域处理

  需要使用 @koa/cors

  使用

复制代码
const cors = require('@koa/cors');

// koa请求跨域配置
app.use(
    cors({
        // 允许跨域请求的来源,返回请求头中的 origin 或空字符串
        origin: (ctx) => {
            return ctx.request.headers.origin || "";
        },
        // 允许携带cookie
        creadentials: true,
        // 设置允许客户端获取的响应头
        exposseHeaders: ["WWW-Authenticate", "Server-Authorization"],
        // 设置允许的HTTP请求
        allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
        // 设置允许的HTTP请求头
        allowHeaders: ["Content-Type", "Authorization", "Accept"]
    })
)
复制代码

7. 上传图片

  需要使用 @koa/multer

  使用  ※ 需要现在对应位置创建上传文件夹

复制代码
const Multer = require('@koa/multer')
const path = require('path')

// 配置磁盘存储引擎
const storage = Multer.diskStorage({
    // 指定文件保存路径
    destination: (req, file, cb) => {
        // 当前文件夹下的uploads文件夹
        cb(null, './uploads')
    },
    // 设置文件名
    filename: (req, file, cb) => {
        cb(null, Date.now() + path.extname(file.originalname))
    }
})

// 实例化multer
const multer = Multer({
    storage
})
复制代码

  接口

router.post('/upload', multer.single('file'), async ctx => {
    // 获取上传的文件信息
    const file = ctx.request.file
    if(file) {
        console.log(file)
        ctx.body = '上传成功'
    }
})

8. Cookie

  在服务器端返回时并设置cookie

复制代码
// cookie
router.get('/cookie', async (ctx) => {
    // 基本设置cookie 中文需要转码
    ctx.cookies.set('name', encodeURIComponent('张三'));
    // 设置cookie 并配置配置项
    ctx.cookies.set("web", "www.baidu.com", {
         // cookie有效时长
        maxAge: 1000 * 60 * 60 * 24 * 7,
        // cookie失效时间
        expires: new Date('2019-08-12'),
        // 是否只用于http请求中获取
        httpOnly: false,
        // 是否允许重写
        overwrite: false,
    })
    ctx.body = 'cookie设置成功'
})
复制代码

9. Session

10. JWT (Json Web Token)

  JWT 由三部分组成 Header (头部) Payload (负载) Signatrue (签名) 

  是一种基于令牌(Token)的认证和授权机制

  使用需安装插件 jsonwebtoken

    npm i jsonwebtoken

  使用

    const JTW = require('jsonwebtoken')

  编写 生成 token  和解析token 的方法

复制代码
// 生成token
let generateToken = (key) => {
    // 用户唯一id
    let id = 1 
    // 当前时间戳 单位秒
    let now = Math.floor(Date.now() / 1000)
    let expire = 24 * 60 * 60

    // 负载
    let payload = {
        // Subject 主题(用户唯一id)
        sub: id,
        // 发行者
        iss: 'benfeng',
        // 发行时间
        iat: now,
        // 生效时间
        nbf: now,
        // 过期时间
        exp: now + expire,
        // 
        aud: [''],
        // 自定义数据
        data: {
            name: '贲风',
            gender: '男'
        }
    }
    // 使用负载、秘钥和指定的签名算法(HS256)生成token
    let token = JTW.sign(payload, key, {
        algorithm: 'HS256'
    })
    return token
}
复制代码
// 解析token
let parseToken = (token, key) => {
    let payload = JTW.verify(token, key, {
        algorithm: 'HS256'
    })
    console.log('解析的payload', payload)
}

  请求时传key 就可以换取token

// JWT接口
router.get('/token', async ctx => {
    let key = 'koaTest'
    let token = generateToken(key)
    ctx.body = token
})

11.连接数据库( mongoDB)

  安装插件 mongoose

    npm i mongoose --save

  先单独创建一个js 文件

复制代码
const mongoose = require('mongoose');

module.exports = () => {
  // mongodb数据库地址 mongoose.connect(
'mongodb://localhost:27017/backgroundDatas', { }).then(() => { console.log('数据库连接成功'); }).catch(err => { console.log('数据库连接失败', err); }) }
复制代码

  在app.js 即入口文件中引入并使用

const MongoConnect = require('./db')

// 连接数据库
MongoConnect()

  设计用户模块的schema 【这里我对后端的具体说法不太懂  学习中...】

复制代码
const mongoose = require('mongoose');

// 数据表名称
// const schema = new mongoose.Schema({
//     // 定义字段 以及字段类型
//     p1: String,
//     p2: String
// })
// 创建模型对象
// const obj = mongoose.model('obj', schema)

const userSchema = new mongoose.Schema({
    username: String,
    password: String
})

const User = mongoose.model('User', userSchema)

module.exports = {
    User
}
复制代码

  mongodb 操作数据库增删改查 【应该不全 目前只记录我用了的】

  

复制代码
// 引入模型对象
const { User } = require('../models/index')

// 增  create
User.create({
    username,
    password
})

// 删  findOneAndDelete
User.findOneAndDelete({ id })

// 改  updateOne  
// 两个参数 第一个是识别标志  第二个是要覆盖哪些参数        
User.updateOne(
    { _id: params._id },
    {
        username: params.username,
        password: params.password 
    }
)

//
// 查单个 findOne
// 查所有 find
User.findOne({ _id: ctx.params.id })
复制代码

12. 监听端口  示例为 3000 端口 成功启动就会执行回调函数

1
2
3
4
5
6
7
const hostname = '127.0.0.1';
const port = 3000;
 
// 监听端口
app.listen(port, hostname, () => {
    console.log(`服务器启动成功: http://${hostname}:${port}`)
});

  

posted on   贲风  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示