• EggJS接口开发


    需求

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

    什么是Egg.js

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

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

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

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

    初始化项目

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

    $ mkdir egg-example && cd egg-example
    $ npm init egg --type=simple
    $ npm i 
    

    然后启动项目

    $ 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的逻辑。

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

    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中实现的方法具体可以参考下面的对应关系

    MethodPathRoute NameController.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的插件开发进行了解。

  • 相关阅读:
    如何成为伟大的程序员
    程序员如何增加收入
    一个阿里巴巴码农的六年回眸
    效仿盖茨:PPstream创始人的心路历程
    程序员的工作环境与效率
    软件级负载均衡器(LVS/HAProxy/Nginx)的特点简介和对比
    技术人员创业后就不再适合继续编码了
    互联网行业持续交付的经验
    11 款用于优化、分析源代码的Java工具
    常用 Java 静态代码分析工具的分析与比较
  • 原文地址:https://www.cnblogs.com/dahe1989/p/11246605.html
Copyright © 2020-2023  润新知