环境
架构模式:MVC
架构风格:RESTful
数据库: MongoDB
需求:
实现一个获取用户发帖的列表信息 API, 该 API 列表的内容包含两部分,一部分是从数据库获取的发帖内容,但是这部分只包含用户 ID,另外一部分则是需要通过 ID 批量拉取用户信息。
设计:
设计为一个 GET 接口,根据 RESTful 约束规则设计为:GET /v1/contents;
设计一个独立的服务用来获取用户信息,将接口设计为:GET /v1/userinfos。
热重启
nodemon
npx nodemon app.js
请求方式:
- 命令行下访问 time curl
time curl https://www.baidu.com/s\?ie\=UTF-8\&wd\=baidu
curl https://www.baidu.com/s\?ie\=UTF-8\&wd\=baidu
实现
解析请求
ctx对象参考, 若无法解析, 借助koa-bodyparser
实现 ``` // app.js const Koa = require(‘koa’); const Router = require(‘@koa/router’); const url = require(‘url’); const querystring = require(‘querystring’);{
request: {
method: 'GET',
url: '/v1/userinfos?user_ids=1001,1002',
header: {
host: '127.0.0.1:3000',
'user-agent': 'curl/7.64.1',
accept: '*/*'
}
},
response: {
status: 404,
message: 'Not Found',
header: [Object: null prototype] {}
},
app: { subdomainOffset: 2, proxy: false, env: 'development' },
originalUrl: '/v1/userinfos?user_ids=1001,1002',
req: '<original node req>',
res: '<original node res>',
socket: '<original node socket>'
}
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(); }
<a name="cVxFx"></a>
#### 连接数据库
// 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(); }) });
<a name="NCTKQ"></a>
### 架构模式
- 基础架构: 路由解析、参数解析、路由判断、路由转发、接口相应
- M层: 数据库操作
- C层:业务逻辑
<a name="9XKtR"></a>
#### Model
// model.js
class Model { constructor () { this.db = ‘db_name’; this.baseMongo = ‘baseMongo’; }
async get(collectionName) {
const client = await this.baseMongo();
const collection = client.db("stu").collection("Book");;
return collection;
}
}
class ContentModel extends Model { constructor () { super(); this.collectionName = ‘content’; }
async getList() {
const collection = await this.get(this.collectionName);
const queryArr = await collection.find({}).toArray();
return queryArr;
}
}
<a name="uSK8v"></a>
#### Controller
// controller.js
class Controller { constructor(res, req) { this.res = res; this.req = req; }
resApi(ret, message, dataInfo, httpStatus=200) {
return baseFun.setResInfo(this.res, ret, message, dataInfo, httpStatus);
}
}
class Content extends Controller { constructor(res, req) { this.res = res; this.req = req; }
async list() {
let contentList = await new ContentModel().getList();
// 处理, 比如,依赖其他异步
// constList = contentList
// RESTful规范
return this.resAPI(true, 'success', contentList)
}
} ```
参考:
https://github.com/love-flutter/nodejs-column/tree/master/3