1. 概述

时间跨度有点大,之前就跟大家唠嗑过一些知识点,也开启了一个Node书写一个后台api项目的开始,出于各种原因,迟迟没有更新博文。现在我把这个坑填上,如果你还有阅读过我之前的文章,我建议你先阅读一下

博文地址https://www.cnblogs.com/BM-laoli/p/12708342.html

项目Git地址 https://github.com/BM-laoli/Node-api-Design 所有代码已经分章节的放在了github供需要的朋友参考

在接下来的项目中,我将尽量的以工作时的状态,或者说完全按照公司工作的标准流程,来进行开发,git上分章节,创建分支都是必须学的基本技能,

2. 初始化(github相关)

我们这里假设一种情况,就是你进到一家公司,公司新的项目还没有开始,目前是做的旧的项目,(假设旧的项目在github上),突然你的上司跟你说,你今天做一个对某项目(这里假设旧是我们的design)做一个CRUD接口,然后你上司丢给你一个gihub地址,那你怎么办?蒙圈了???,你这个时候去问人....就有点傻逼了,因为你这都不会,你还来公司干啥?干坐着?

好了毒鸡汤灌输完毕,接下里我们就来开始我们的项目

2.1. 设计架构的更新

  • 首先我们看看我们的之前的设计图,再看看我们现在的总体架构图

2.2 看看我们接下需要做哪些事情,

我们希望写几个接口对两个数据表进行操作这两个表是 article 还有user

  • 关于架构的设计模式还有一些规则,

大佬不要喷我,这里就说一下,我的个人观点,项目的架构,基本上都是MVC,既然是MVC那么这里就得非常的明确的分出来,(如果你学习过后台的语言比如php或者java)那么这个应该能非常好理解,在node中的架构是这样的,

我们站在http发送的报文角度,看看我们的的报文从客户端发到我们node服务器,经历了哪些事情

--> 进入路由 -----> 路由接受到之后做业务处理,这里就是(中间件)业务处理的逻辑就是在中间件做的-------> 假设你的http报文要请求数据库的一些字段,那么久需要用到model层<------数据库的dao层(在node中你可能使用的别人大神给你写好的dao层比如mongoose,或则Knex.js等,总而言之这些东西都是为model服务的) ------>中间件抛出数据next到我们的路由上------->路由通过res.send把数据丢出去,提示:在node中我们最常用的就是把传出去的数据整成json格式,如果你还不会,别着急我们一点点来学

2.3 克隆项目下来

git clone https://github.com/BM-laoli/Node-api-Design.git

3. 进入业务之前的说明

3.1 想清楚再敲代码,别一上来就吧唧敲一顿

我们看看啊,我们的大体的流程,理解整个的流程,丢代码的书写非常的重要,这样你就能清晰的知道自己到底在干嘛了.

还有一点需要说明的是:这里我们遵守这样的一个命名规范:数据模型是大写单数,路由参数是小写复数比如

Article ====> articles

3.2 接口测试工具

我们使用一个vs上的一个插件这个插件是下面的样子,在项目中,我讲一点点的教大家使用它

4. 进入业务

4.1 设计数据库并且完成连接

这里我们主要干的一个事情就是设计两个集合(表),并且拿到他们的操作对象

  1. 新建一个分支init-database,
git checkout -b init-basese

这里我们新建一个分支,并且配置一个忽略项文件

.gitignore

.DS_Store
node_modules
npm-debug.log
package-lock.json

以上的代码表示我们在git上提交东西的时候可以忽略掉node_module,等文件夹/文件

  1. 在molde下设计一个article表(集合),它的规则(schema)如下

/model/Article

const mongoose = require('mongoose')
const schema = new mongoose.Schema({ title:{ type:String },
body:{type:String} }) module.exports = mongoose.model( 'Article',schema )
  1. 提交给git分支,并且合并一下代码待maseter上

git push origin init-basese

4.2 实现丢article表的增删改查(CRUD)

首先我们依然是git出来一个分支,我们在CRUD分支下进行操作

git checkout -b CRUD

注意,这里我在原来的基础上做了一些修改,因为使用restClinet的时候有些字段不能读取出来,所有我修改了下面的代码

  • 在main下 我把原来的index接口改掉了,改造成了下面的这样的格式,然后在home.index.js中也稍微做了一下修改

    /main.js
require('./API/home/index')(admin)
实际上这样的写法等价于。
main.use(require('./API/home/index'))

/home/index.js

module.exports = admin => {
const express = require('express')
const router = express.Router({})
const Article = require('../../../../model/Article') //测试路由
router.get('/test',(req,res)=>{
res.send('ok')
}) //这句use一定要加
admin.use('/CRUD',router)
}
  • 在路由验证器的东西上,我改掉了header.token。因为我在发生restClint的时候,不走token,而是加在了Authorization字段中

    /Mideleware/loginPash.js
let token = req.headers.authorization;
  • 测试结果,注意这这里我使用了restClint插件,通过下面的图,你应该可以非常清晰的看到如何使用这个插件。非常方便的做接口测试

接下里就是正式的增删改查业务流程了

特别说明:这里我们编写的接口要求符合REST风格,至于说明是REST风格请去百度,它看起来就是下面的这个样子

更具REST风格来说。PUT表示更新,POST表示增加,DELET表示删除,GET分为带参数还有不带参数的情况,不带参数表示全查,待参数表示查指定内容
@uri = http://localhost:3000/main/CRUD
@toke = eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoiNWU5MTIwMTViOWI0NmYzZmE4Y2MzMjUzIiwiZXhwIjoxNTg5ODU0NTI5LCJpYXQiOjE1ODk4NTI3Mjl9.U0N1bZLUBiy2fmz1NqAF-tTelE7uO8Xld4HHFeBsbq7iY5rSNMByYUyxhC1k8ug9n_8XzChL81ruiFuwxIcOg7DXk_hdrnvpUgwwtjIPjn4kfWWVEsZGm456fo3L5cHfppOTWH5NQAtKEd7xwrhqPrEPsBUwAc7pKEAFDaGuFOc ###
GET http://localhost:3000/main/test ### 进行token校验拿到我们的token,只有拿到token之后才允许进入下面的请求环节 POST http://localhost:3000/main/login
Content-Type: application/json {
"email":"18376621755@163.com",
"password":"123456"
} ### 我们需要携带token才能发起其它的请求
GET {{uri}}/test
Authorization: {{toke}} ### 增
POST {{uri}}/Article/
Content-Type: application/json
Authorization:{{toke}} {
"title":"分类测试3",
"body":"<h1>你好我是标题2</h1>"
} ### 删
DELETE {{uri}}/Article/5ec330fe21d3d97d5054e5bf
Authorization: {{toke}} ### 改
PUT {{uri}}/Article/5ec32f60cd080550a4e2fba8
Content-Type: application/json
Authorization:{{toke}} {
"title":"修改测试--222",
"body":"<h1>你好我是标题2</h1>"
} ### 查
GET {{uri}}/Article
Authorization:{{toke}} ### 查 根据id查
### 特别小心由于你在后台使用了express的动态路由,所以你不必加id=xxx
GET {{uri}}/Article/5ec32f60cd080550a4e2fba8
Content-Type: application/json
Authorization:{{toke}}

/home/index.js

module.exports = admin => {
const express = require('express')
const router = express.Router({
mergeParams: true //合并所有的url,如果你合并那么那个动态的resoulce你是拿不到的
})
const Article = require('../../../../model/Article') //测试路由
router.get('/test',(req,res)=>{
res.send('ok')
}) //增
router.post('/Article', async (req, res) => {
const model = await Article.create(req.body)
res.send(model)
}) //查
router.get('/Article', async(req, res,next) => {
const items = await Article.find().limit(10)
res.send(items)
next()
}) //根据id查
router.get('/Article/:id', async(req, res) => { console.log('asdasdasd');
console.log(req.params.id);
const items = await Article.findById(req.params.id)
res.send(items)
}) //更新(改)
router.put('/Article/:id', async(req, res) => {
const items = await Article.findByIdAndUpdate(req.params.id, req.body)
res.send(items)
}) //根据id参数(删)
router.delete('/Article/:id', async(req, res) => {
await Article.findByIdAndDelete(req.params.id, req.body)
res.send({
sucees: true
})
}) admin.use('/CRUD',router)
}

4.3 使用RESTClinet进行接口测试

  • 测试结果如下:完美通过

4.4 收尾上传分支到git

git push origin CRUD

4.4 抽离成一个通用的CRUD

现在老板又给我吗要求了,我们需要对一个名字叫做product集合(表),进行增删改查,那么问题来了?我们难道又要写一个与上代码类似的接口吗?

答案是非必要的,我们可以把上面的接口改成通用的CRUD,这样我们就能很方便的使用它了,有新的需求来的时候,只需要修改数据模型就好了

  • 首先,我们在路由的地方做一层封装

这里呢,我们就使用到了,之前的命名约定规范,(命名规范非常的重要!!!),我们使用一个第三方插件,实现大小写以及单复数的转换,然后根据转换之后的结果去找对应的 数据模型就好了

module.exports = admin => {
const express = require('express')
const inflection = require('inflection')
const router = express.Router({
mergeParams: true //合并所有的url,如果你合并那么那个动态的resoulce你是拿不到的
})
++++
//起一个到哪个台的资源就好了,注意我们的中间件
admin.use('/CRUD/rest/:resource', async(req, res, next) => { //转化成单数大写的字符串形式
let moldeName = inflection.classify(req.params.resource)
console.log(moldeName); //categorys ===> Category
//注意这里的关联查询populate方法,里面放的就是一个要被关联的字段
req.Model = require(`../../../../model/${moldeName}`)
req.modelNmae = moldeName
next()
}, router) }

设置好一层用来的过滤中间件之后,那么我们的CRUD就变成了一个通用的接口了,后续的操作API只需要变化接口的名字,变化数据库模型就好了,非常的方便,


//增
router.post('/', async (req, res) => {
const model = await req.Model.create(req.body)
res.send(model)
}) //查
router.get('/', async(req, res,next) => {
const items = await req.Model.find().limit(10)
res.send(items)
next()
}) //根据id查
router.get('/:id', async(req, res) => { console.log('asdasdasd');
console.log(req.params.id);
const items = await req.Model.findById(req.params.id)
res.send(items)
}) //更新(改)
router.put('/:id', async(req, res) => {
const items = await req.Model.findByIdAndUpdate(req.params.id, req.body)
res.send(items)
}) //根据id参数(删)
router.delete('/:id', async(req, res) => {
await req.Model.findByIdAndDelete(req.params.id, req.body)
res.send({
sucees: true
})
})

接下来我们新建一个product模型进行测试

/model/Prodcut

const mongoose = require('mongoose')
const schema = new mongoose.Schema({ product_name:{ type:String },
category:{type:String} }) module.exports = mongoose.model( 'Product',schema )

测试结果如下

Node教程——API接口开发(Node版的CRUD通用接口的搭建)(MangoDB+Express_Version2)的更多相关文章

  1. 支付宝WAP支付接口开发(Node/Coffee语言)

    此博客不更新很久了, 更新的文档在这, 有兴趣到这里围观: http://neutra.github.io/2013/%E6%94%AF%E4%BB%98%E5%AE%9DWAP%E6%94%AF%E ...

  2. Node.js 从零开发 web server博客项目[接口]

    web server博客项目 Node.js 从零开发 web server博客项目[项目介绍] Node.js 从零开发 web server博客项目[接口] Node.js 从零开发 web se ...

  3. api 接口开发理论 在php中调用接口以及编写接口

    如: http://localhost/openUser.php?act=get_user_list&type=json 在这里openUser.php相当于一个接口,其中get_user_l ...

  4. Node教程——API接口开发(MangoDB+Express)

    一.大纲 大纲: 关于架构, 首先我们的有一个app.js这个就是根路由起点,用来最初的打入口 它的功能有: 1.1 引入模块创建基础的网站服务器, 1.2 导入bodyPasser,过滤还有处理我们 ...

  5. 【Node.js】2.开发Node.js选择哪个IDE 开发工具呢

    安装完Node.js之后,就要为它选择一个有利的IDE用于开发. 相比较了多个IDE之后,定位在webstrom和sublime上. 有一个简单的比较: webstorm功能很丰富,前端开发工具的集大 ...

  6. 最详细的 paypal 支付接口开发--Java版

    做全球性的支付,选用paypal!为什么选择paypal? 因为paypal是目前全球最大的在线支付工具,就像国内的支付宝一样,是一个基于买卖双方的第三方平台.买家只需知道你的paypal账号,即可在 ...

  7. HTTP接口开发专题四(接收http接口发送过来的请求)

    前面讲了调用http接口的操作,这篇讲下接收http接口的操作.(以Spring MVC为例) 1)如果发送过来的内容类型是application/x-www-form-urlencoded ,则按照 ...

  8. Node.js 从零开发 web server博客项目[express重构博客项目]

    web server博客项目 Node.js 从零开发 web server博客项目[项目介绍] Node.js 从零开发 web server博客项目[接口] Node.js 从零开发 web se ...

  9. Node.js 从零开发 web server博客项目[数据存储]

    web server博客项目 Node.js 从零开发 web server博客项目[项目介绍] Node.js 从零开发 web server博客项目[接口] Node.js 从零开发 web se ...

随机推荐

  1. python 给字典按值排序,同样适合于其他

    sorted_items = sorted(dico.items(),key=lambda x:(-x[1],x[0]))

  2. 14个快捷键让你的idea飞起来(新手向 + 演示)

    本期盘点一下博主在工作中,常用的13个idea快捷键,这些快捷键基本涵盖了大部分的开发场景,希望可以萌新们的idea使用效率,系统为mac系统 上一步 / 下一步撤销 / 反撤销进入一个类生成方法变量 ...

  3. 高级数据结构---赫(哈)夫曼树及java代码实现

    我们经常会用到文件压缩,压缩之后文件会变小,便于传输,使用的时候又将其解压出来.为什么压缩之后会变小,而且压缩和解压也不会出错.赫夫曼编码和赫夫曼树了解一下. 赫夫曼树: 它是一种的叶子结点带有权重的 ...

  4. http_response_code()和header()

    1.http_response_code — 获取/设置响应的 HTTP 状态码向服务器发送成功状态码:http_response_code(200); 返回值如果提供了response_code,将 ...

  5. thinkPHP--empey标签

    直接上代码,这是判断内容是否为null而做出不同的html的选择 <notempey name="welfare_list"> <foreach name=&qu ...

  6. wx.request出现400 bad request的问题

    wx.request({ url: 'test.php', //仅为示例,并非真实的接口地址 data: { x: '' , y: '' }, header: { 'content-type': 'a ...

  7. application/x-www-form-urlencoded ,multipart/form-data, text/plain

    APPLICATION/X-WWW-FORM-URLENCODED MULTIPART/FORM-DATA TEXT/PLAIN 后台返回的数据响应的格式类型 application/x-www-fo ...

  8. SpringBoot内置生命周期事件详解 SpringBoot源码(十)

    SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringBoot事件监听 ...

  9. 数学--数论---P4718 Pollard-Rho算法 大数分解

    P4718 [模板]Pollard-Rho算法 题目描述 MillerRabin算法是一种高效的质数判断方法.虽然是一种不确定的质数判断法,但是在选择多种底数的情况下,正确率是可以接受的.Pollar ...

  10. 图论--2-SAT--HDOJ/HDU 1824 Let's go home

    Problem Description 小时候,乡愁是一枚小小的邮票,我在这头,母亲在那头.                         -- 余光中 集训是辛苦的,道路是坎坷的,休息还是必须的. ...