前端模拟数据,我们也可以通过接口来实现啦,马上就能实现简单、高效的CURD,下面将通过node.js+koa完成接口的增删改查
技术选型及环境搭建
- node
- koa(基于node服务端框架)
- mongoDB(数据库)
- apifox(调试工具)
依赖安装
- dotenv(可以读取我们根目录下的.env文件 配置动态参数/环境变量)
- koa
- koa-body(可以解析我们post请求的body传参)
- mongoose(用于操作mongodb数据库)
- nodemon(保存自动运行脚本)
文档url
- mongoose: www.npmjs.com/package/mon…
- nodeAPI:www.nodejs.com.cn/api/documen…
- npm官网:www.npmjs.com/
模块划分
- src
-
- app 把服务端框架抽离
-
- config 环境变量归类
-
- app.js 文件入口/执行文件
-
- routre 路由层:根据路径,执行不同的控制器
-
- controller 控制器:用于数据/逻辑处理
-
- service 服务层:负责写入数据库
-
- model 模型层:字段定义,数据库表的映射
模块之间的逻辑顺序
- 这里只是简单的介绍模型之间的流程 方便理解
- 内部还有一个核心的东西去串联,那就是
中间件-洋葱模型
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"
}
}
目录结构
总结
- 本文只是简单的实现的CURD
- 相当于一个模板,还有很多还需要补充
- 后续会继续补充,完善文档,目前只是记录学习阶段,有何错误的地方,欢迎指正
- 作者也会继续探索,输出更加的优质的文章,谢谢阅读