环境

架构模式:MVC
架构风格:RESTful
数据库: MongoDB

需求:

实现一个获取用户发帖的列表信息 API, 该 API 列表的内容包含两部分,一部分是从数据库获取的发帖内容,但是这部分只包含用户 ID,另外一部分则是需要通过 ID 批量拉取用户信息。

设计:

设计为一个 GET 接口,根据 RESTful 约束规则设计为:GET /v1/contents;
设计一个独立的服务用来获取用户信息,将接口设计为:GET /v1/userinfos。

热重启

  • nodemon

    1. npx nodemon app.js

    请求方式:

  • 浏览器访问 http://127.0.0.1:3000/v1/userinfos?user_ids=1001,1002

  • 命令行下访问 time curl
    1. time curl https://www.baidu.com/s\?ie\=UTF-8\&wd\=baidu
    2. curl https://www.baidu.com/s\?ie\=UTF-8\&wd\=baidu
    image.png

    实现

    解析请求

    ctx对象参考, 若无法解析, 借助koa-bodyparser
    1. {
    2. request: {
    3. method: 'GET',
    4. url: '/v1/userinfos?user_ids=1001,1002',
    5. header: {
    6. host: '127.0.0.1:3000',
    7. 'user-agent': 'curl/7.64.1',
    8. accept: '*/*'
    9. }
    10. },
    11. response: {
    12. status: 404,
    13. message: 'Not Found',
    14. header: [Object: null prototype] {}
    15. },
    16. app: { subdomainOffset: 2, proxy: false, env: 'development' },
    17. originalUrl: '/v1/userinfos?user_ids=1001,1002',
    18. req: '<original node req>',
    19. res: '<original node res>',
    20. socket: '<original node socket>'
    21. }
    实现 ``` // app.js const Koa = require(‘koa’); const Router = require(‘@koa/router’); const url = require(‘url’); const querystring = require(‘querystring’);

const app = new Koa(); const router = new Router(); // app.use(bodyParser())

app.use(async ctx => { const { pathname, query } = url.parse(ctx.originalUrl); // 解析请求路径 const params = querystring.parse(query); // 解析请求参数 // console.log(pathname, query, params); if (‘/v1/userinfos’ !== pathname) { setResInfo(ctx, -1, ‘path not found’) } if (!params || !params[‘user_ids’]) { setResInfo(ctx, -1, ‘params not found’) } // ctx.body = ‘Hello World’; });

app.use(router.routes()) .use(router.allowedMethods())

app.listen(3000);

function setResInfo(ctx, ret, message, data = {}) { ctx.status = 200; ctx.res.write(JSON.stringify({ ret, message, data })); ctx.res.end(); }

  1. <a name="cVxFx"></a>
  2. #### 连接数据库

// db.js const MongoClient = require(‘mongodb’).MongoClient; const uri = “mongodb+srv://zhaocchen:Zhao123@cluster0.tjac2.mongodb.net/myFirstDatabase?retryWrites=true&w=majority”; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }); client.connect((err, db) => { const collection = client.db(“stu”).collection(“Book”); console.log(‘连接成功了’, err); collection.find({}).toArray((err, docs) => { console.log(err, docs.length); client.close(); }) });

  1. <a name="NCTKQ"></a>
  2. ### 架构模式
  3. - 基础架构: 路由解析、参数解析、路由判断、路由转发、接口相应
  4. - M层: 数据库操作
  5. - C层:业务逻辑
  6. <a name="9XKtR"></a>
  7. #### Model

// model.js

class Model { constructor () { this.db = ‘db_name’; this.baseMongo = ‘baseMongo’; }

  1. async get(collectionName) {
  2. const client = await this.baseMongo();
  3. const collection = client.db("stu").collection("Book");;
  4. return collection;
  5. }

}

class ContentModel extends Model { constructor () { super(); this.collectionName = ‘content’; }

  1. async getList() {
  2. const collection = await this.get(this.collectionName);
  3. const queryArr = await collection.find({}).toArray();
  4. return queryArr;
  5. }

}

  1. <a name="uSK8v"></a>
  2. #### Controller

// controller.js

class Controller { constructor(res, req) { this.res = res; this.req = req; }

  1. resApi(ret, message, dataInfo, httpStatus=200) {
  2. return baseFun.setResInfo(this.res, ret, message, dataInfo, httpStatus);
  3. }

}

class Content extends Controller { constructor(res, req) { this.res = res; this.req = req; }

  1. async list() {
  2. let contentList = await new ContentModel().getList();
  3. // 处理, 比如,依赖其他异步
  4. // constList = contentList
  5. // RESTful规范
  6. return this.resAPI(true, 'success', contentList)
  7. }

} ```

参考:
https://github.com/love-flutter/nodejs-column/tree/master/3