初尝node+koa+mongodb开发接口-1.0版本

214 阅读4分钟

前端模拟数据,我们也可以通过接口来实现啦,马上就能实现简单、高效的CURD,下面将通过node.js+koa完成接口的增删改查

技术选型及环境搭建

  • node
  • koa(基于node服务端框架)
  • mongoDB(数据库)
  • apifox(调试工具)

依赖安装

  • dotenv(可以读取我们根目录下的.env文件 配置动态参数/环境变量)
  • koa
  • koa-body(可以解析我们post请求的body传参)
  • mongoose(用于操作mongodb数据库)
  • nodemon(保存自动运行脚本)

文档url

模块划分

  • src
    • app 把服务端框架抽离
    • config 环境变量归类
    • app.js 文件入口/执行文件
    • routre 路由层:根据路径,执行不同的控制器
    • controller 控制器:用于数据/逻辑处理
    • service 服务层:负责写入数据库
    • model 模型层:字段定义,数据库表的映射

57_]FT)NT}(%I}R$UVEL5.png

模块之间的逻辑顺序

  • 这里只是简单的介绍模型之间的流程 方便理解
  • 内部还有一个核心的东西去串联,那就是
  • 中间件-洋葱模型
graph TD
app.js文件执行 --> 根据路由找到对应控制器 --> 控制器处理前端数据 --> 数据处理完毕调用服务层 --> 服务层拿到模型进行具体操作

app文件-服务端抽离

// koa框架
const Koa = require('koa')
const mongoose = require('mongoose') // 操作mongodb数据库

// 获取路由
const UserRouter = require('../router/use_route')
// 解析通过post请求传来的数据
const { koaBody } = require('koa-body')


// 拿到koa实例
const app = new Koa()

// 数据库连接 在中间件之前
mongoose.connect('mongodb://127.0.0.1:27017/shop')
  .then(() => console.log('数据库连接成功!'))
  .catch((e)=>console.log('数据库连接失败',e))
  
  
// 在所有中间件处理之前 使用koaBody 不然获取不到 body请求体
app.use(koaBody());

// 中间件注册路由 app.use() 只能接收函数; router.routes() 就是返回一个函数
app.use(UserRouter.routes())


// 导出koa实例
module.exports  = app

app.js-文件入口

// 获取koa实例
const app = require('./app/index')
// 动态配置参数 引入
const { APP_PORT } = require('./config/config.default')

// 监听服务端连接是否成功
app.listen(APP_PORT, () => {
  console.log(`sever in running localhost:/${APP_PORT}`);
})

config 文件

- src/config/default.js
// dotenv 读取根目录下的 .env环境变量
const dotenv = require('dotenv')
dotenv.config()

module.exports = process.env

.env 文件

APP_PORT = 3999

router文件

采用restful风格API完成接口

- src/router/user_route.js
// 引入路由
const Router = require('koa-router')
// 引入控制器
const {register,login,update,del,delQuery,getAllUser,getUser} = require('../controller/user.controller')
// 路由实例化 prefix: '/normal' 统一的路由前缀
const router = new Router({prefix: '/user'})

// prefix 会自动拼接写入的path

// 注册
router.post('/register', register)

// 登录
router.post('/login', login)

// 更新
router.put('/update', update)

// 删除
// params 形式传参
router.del('/del/:id',del)
// query 形式传参
router.del('/del', delQuery)

// 根据条件获取
router.get('/getUser',getUser)
// 获取全部
router.get('/getAllUser',getAllUser)

// 导出路由 并且在 app.js入口文件注册
module.exports = router

controller 文件

- sec/controller/user.controller.js

// 作用:控制器处理不同的业务 
// 引入服务层
const {createUser,updateUser,deleteUser,deleteQueryUser,getAllUser,getSingleUser} = require('../service/user.service')

// 创建控制器 以class方式 new一下 直接拿多香
class UserController {

  // 操作数据库是异步 需要加上 async
  // ctx 请求的上下文
  async register(ctx, next) {
    // 书写ctx.body 是返回给客户端的数据信息
    ctx.body = {
      data: [],
      msg: 'user register'
      code: 200
    }
  }

  async login(ctx, next) {
    // ctx.request.body 拿到客户端请求的请求体信息
    const {name,age} = ctx.request.body
    // 调用我们服务层对应的方法
    const res = await createUser(name,age)
    ctx.body = {
      data: [{
        req: res
      }],
      msg: 'user login'
    }
  }


  async update(ctx, next) {
    const {name,id} = ctx.request.body
    const res = await updateUser(name,id)
    ctx.body = {
      data: [{
        req: res
      }],
      msg: 'user update'
    }
  }

  async del(ctx, next) {
    // 获取客户端以params形式的传参
    const { id } = ctx.params
    const res = await deleteUser(id)

    ctx.body = {
      data: [{
        req: res
      }],
      msg: 'user delete'
    }
  }
  
  async delQuery(ctx, next) {
    // 获取客户端以query形式的传参
    const { id } = ctx.query
    const res = await deleteQueryUser(id)
    ctx.body = {
      data: [{
        req: res
      }],
      msg: 'user delete Query'
    }
  }

  async getUser(ctx, next) {
    const { id } = ctx.query
    console.log(id,'query');
    const res = await getSingleUser(id)
    ctx.body = {
      data: [{
        req: res
      }],
      msg: 'user get Query'
    }
  }

  async getAllUser(ctx, next) {
    const res = await getAllUser()
    console.log('res',res);
    ctx.body = {
      data: [{
        req: res
      }],
      msg: 'user get Query'
    }
  }
}

// 导出我们的控制层 需要new 一下嗷
module.exports = new UserController()

service 文件

- src/service/user.service.js

// 引入我们的模型
const userModel = require('../model/Shop.model')

// service 操作数据库
// 这里当然也是面向对象嗷
class UserService { 
  // 创建用户
  async createUser(name, age) {
    // 这里需要 new 我们创建的模型 因为要把数据传进去(个人觉得)
    const UserModel = new userModel({name,age})
    
    // 模型构建好以后 调用 `.save` 方法保存
    UserModel.save()
      .then(() => console.log('创建用户success'))
      .catch((e)=>console.log('创建失败',e))
  }

  async updateUser(name, id) {
    // 这里无需创建模型 只需要把我们引入的模型 调用一下 `findByIdAndUpdate`
    // 这个API应该很好已经吧 通过id查找 并且更新数据
    userModel.findByIdAndUpdate(id,{name: name})
      .then(() => console.log('修改入库success'))
      .catch((e)=>console.log('修改失败',e))
  }

  async deleteUser(id) {
    // 这里无需创建模型 只需要把我们引入的模型 调用一下 `findByIdAndDelete`
    // 这个API应该很好已经吧 通过id查找 并且删除数据
    userModel.findByIdAndDelete(id)
      .then(() => console.log('删除入库success'))
      .catch((e)=>console.log('删除失败',e))
  }
  
  // 以query形式传参删除
  async deleteQueryUser(id) {
    userModel.findByIdAndDelete(id)
      .then(() => console.log('删除入库success'))
      .catch((e)=>console.log('删除失败',e))

  }

  async getAllUser() {
    // 这里无需创建模型 只需要把我们引入的模型 调用一下 `find`
    // 这个API应该很好已经吧 通过查找所有
    const res = await userModel.find()
    return res

  }

  async getSingleUser(id) {
    // 这里无需创建模型 只需要把我们引入的模型 调用一下 `findById`
    // 这个API应该很好已经吧 通过id查找
    const res = userModel.findById(id)
    return res
  }
}

// 导出服务层 new 一下嗷
module.exports = new UserService()

model文件

- src/model/Shop.model.js
const mongoose = require('mongoose')
const Schema = mongoose.Schema // 通过Schema来创建模型


const User = new Schema({
  name: { type: String, default: 'hahaha' },
  age: { type: Number, min: 18, index: true }
});

// 导出模型
module.exports = mongoose.model('UserModel',User)

package.json

{
  "name": "api",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon ./src/app.js" // 保存自动运行配置
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "dotenv": "^16.3.1",
    "koa": "^2.14.2",
    "koa-body": "^6.0.1",
    "koa-router": "^12.0.0",
    "mongoose": "^7.4.3",
    "sequelize": "^6.32.1"
  },
  "devDependencies": {
    "nodemon": "^3.0.1"
  }
}

目录结构

image.png

总结

  • 本文只是简单的实现的CURD
  • 相当于一个模板,还有很多还需要补充
  • 后续会继续补充,完善文档,目前只是记录学习阶段,有何错误的地方,欢迎指正
  • 作者也会继续探索,输出更加的优质的文章,谢谢阅读