EggJS接口开发

需求

随着Nodejs的普及,前端开发的开发场景基本能够贯穿界面交互到数据存储,无缝实现全栈开发。最近在实现一个内部项目管理工具的时候,就尝试了一把接口和数据库开发。javascript

什么是Egg.js

Egg.js是阿里开源的一套Nodejs开发框架。Egg.js官网的介绍是:前端

Egg.js 为企业级框架和应用而生,咱们但愿由 Egg.js 孕育出更多上层框架,帮助开发团队和开发人员下降开发和维护成本。java

为何选择了Egg.js,而不是Koa,Express呢,其实仍是为了快速开发,减小搭建项目的时间,Egg.js已经为开发者设计了几乎最经常使用的目录结构,一切倾向于配置化,隐藏一些业务无关的技术细节。开发者能够更加着重考虑业务逻辑,而后在Egg.js和相关插件的支持下,开发功能便可。mongodb

Egg.js还提倡『约定优于配置』,这一点我也是很赞同,一致的约定可以减小没必要要的失误,同时保证了一致的开发体验,能够方便的维护不一样的项目。数据库

初始化项目

Egg.js提供了脚手架快速初始化项目,可是要求npm >=6.1.0,这基本不是问题。npm

$ mkdir egg-example && cd egg-example
$ npm init egg --type=simple
$ npm i
复制代码

而后启动项目api

$ npm run dev
$ open http://localhost:7001
复制代码

目录设计

由于Egg.js已经作了太多事情,我只须要关注app和config。跨域

├── app
|   ├── router.js
│   ├── controller
│   |   └── home.js
│   ├── service
│   |   └── user.js     
│   ├── model
│   |   └── user.js     
├── config
|   ├── plugin.js 
|   └── config.default.js
复制代码

app/router.js 用于配置URL路由规则,也就是你访问的接口地址,对应的是哪一个controller的逻辑。bash

app/controller/** 用于解析用户的输入,处理后返回相应的结果,这里其实能够写service和model的逻辑,可是按照单一职责的原则,咱们会在controller主要放置参数解析和返回值,以及非数据库操做的逻辑。app

app/service/** 用于编写业务逻辑层,可选,建议使用,你能够理解成对数据库操做的封装。

app/model/** 用于定义mongodb的schema,这部分很神奇的是Egg.js已经封装mongodb连接数据库,并将model绑定到了ctx上,方便调用。

config/config.default.js 用于编写配置文件,能够配置不一样的开发环境,不一样的变量,可是由于业务比较单一,内部使用,因此只使用了默认设置。个人项目中配置了跨域、mongoose、csrf,等等。

config.mongoose = {
    url: "mongodb://127.0.0.1/*****",
    options: {}
};

config.cors = {
    origin: '*',  
    allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'
}

config.security = {
    csrf: {
        enable: false,
    },
};
复制代码

config/plugin.js 用于配置须要加载的插件,好比egg-mongoose,egg-cors。

module.exports = { 
    mongoose: {
        enable: true,
        package: "egg-mongoose"
    },
    cors: {
        enable: true,
        package: "egg-cors"
    }
};
复制代码

这里须要注意的是,不少博客提供的代码都是ES6的代码,在我初始化的模板中是不可行的,以下:

exports.cors = {
  enable: true,
  package: 'egg-cors',
}
复制代码

开发项目

基础搭建好了,开发就变得很简单了,我遵循的逻辑是:Model-->路由-->Contoller-->Service,先设计数据库Schema,而后增长新的路由,支持对应的Controller,而后在Service中完成数据库操做。

router.js

router.get("/api/task", controller.task.index);
router.post("/api/task", controller.task.create);
router.put("/api/task/:id", controller.task.update);
router.delete("/api/task/:id", controller.task.destroy );

// 也能够简写为 
router.resources('topics', '/api/task', controller.task);
复制代码

controller中实现的方法具体能够参考下面的对应关系

Method Path Route Name Controller.Action
GET /posts posts app.controllers.posts.index
GET /posts/new new_post app.controllers.posts.new
GET /posts/:id post app.controllers.posts.show
GET /posts/:id/edit edit_post app.controllers.posts.edit
POST /posts posts app.controllers.posts.create
PUT /posts/:id post app.controllers.posts.update
DELETE /posts/:id post app.controllers.posts.destroy

controller/task.js

exports.index = function*() {
    // ...
    const result = yield this.service.task.index(this.params); 
    this.body = result;
};

exports.create = function*() { 
    // ...
    const result = yield this.service.task.create(this.request.body);
    this.body = result;
};

exports.update = function*() { 
    // ...
    const result = yield this.service.task.update(this.params.id, this.request.body); 
    this.body = result; 
};

exports.destroy = function*() {
    // ...
    const result = yield this.service.task.destroy(this.params); 
    this.body = result; 
};
复制代码

service/task.js

module.exports = app => {
    class TaskService extends app.Service {
        *index(params) {
            let tasks = yield this.ctx.model.Task.find(params);
            let result = {};
            result.data = tasks;
            return result;
        }

        *create(request) {  
        }

        *update(id, request) { 
        }

        *destroy(params) { 
        }
    }
    return TaskService;
};
复制代码

model/task.js

module.exports = app => {
    const mongoose = app.mongoose;
    const Schema = mongoose.Schema;
    const TaskSchema = new Schema({
        id: {type: Number},
        text: {type: String},
        type: {type: String},
        progress: {type: Number},
        open: {type: Boolean},
        start_date: {type: String},
        owner_id: [{type: String}],
        duration: {type: Number},
        parent: {type: Number}
    });
    return mongoose.model("Task", TaskSchema);
};
复制代码

部署

Egg.js 框架内置了 egg-cluster 来启动 Master 进程,Master 有足够的稳定性,再也不须要使用 pm2 等进程守护模块。只须要两个命令便可:

# 启动服务
npm start
# 关闭服务
npm run stop
复制代码

结语

站在巨人的肩膀上,让咱们的开发效率倍增,可是仍是建议你们先从Koa2学起,对而后对比Egg.js,你就会了解它到底封装了哪些东西,为咱们节省了多少工做量,后面还要继续对Egg.js的插件开发进行了解。

相关文章
相关标签/搜索