当前位置: 首页 > article >正文

基于 NodeJs 一个后端接口的创建过程及其规范 -- 【elpis全栈项目】

基于 NodeJs 一个后端接口的创建过程及其规范


一个接口的诞生:

router schema:参数规则
router:接口
controller:业务逻辑
service:处理数据

流程简述:

  1. 首先通过router-schema定义接口入参规则;
  2. 然后在 router 中定义接口;
  3. 调用接口, 会经过一个 controller 中间层处理业务逻辑,业务逻辑中的数据则是通过调用 service 来获取所需的数据;
  4. service 则负责对数据的处理,中会封装一些对数据库增删改查的方法。

一、 router-schema: 请求规则


router-schema 中配置了每个接口所需的字段、类型、是否必填等信息。可以有效的规避掉客户端的一些无效请求,比如,下面这个接口中入参没有 ‘proj_key’ 的话,就无法通过校验会直接返回参数不合法的提示,节省了服务器资源。

'/api/project': {
    get: {
      query: {
        type: 'object',
        properties: { proj_key: { type: 'string' }, ...},
        required: ['proj_key']
        ....
      }
    }
  }

他的配置需要遵循JSON schama 的规范;
而校验的是否符合规范的过程是由中间件去实现,本项目中通过 elpis-core 去实现,大概的思路就是:

  1. router-schema 中的配置会被挂载到全局的 app 实例上,可以通过app.routerSchema['/api/project'] 去访问到每个接口的 schema 规则对象;
  2. 然后借助一个中间件去实现校验:(如下是主要思路)
 const Ajv = require('ajv'); // 需要安转ajv检验器
 const ajv = new Ajv();
 
 const $schema = "http://json-schema.org/draft-07/schema#" // 告知校验器(ajv),用什么规则去校验 
 const schema = app.routerSchema[path]
 schema.headers.$schema = $schema;
 let validate = ajv.compile(schema.query) // 读取path接口的schema,及其query的配置
 let valid = validate(query) // 校验数据

schema 配置文件示例:

--| router-schema
	--| project.js

// 遵循 JSON schema 规范
module.exports = {
  '/api/project': {
    get: {
      query: {
        type: 'object',
        properties: {
          proj_key: {
            type: 'string'
          }
        },
        required: ['proj_key']
      }
    }
  },
  '/api/project/model_list': {
    get: {}
  }
}

JSON Schema 中文文档

二、 定义路由


使用koa-router 定义接口名称, 并传入一个 controller 中间件处理业务逻辑。

module.exports = (app, router) => {
  const { project: projectController } = app.controller
  router.get('/api/project/list', projectController.getList.bind(projectController))
  router.get('/api/project/model_list', projectController.getModelList.bind(projectController))
}

三、 处理业务逻辑


对数据处理无非就是增删改查,而对数据库增删改查的方法是不变,而且是会被反复用到的。每个接口只是对增删改查的不同组合,所以为了保留这些方法的原子性。特地从接口和数据之间抽出一个中间层,用来处理不同接口的业务逻辑。由此 controller 中间层应孕而生。

可以在其中处理入参,构造响应数据等操作:

module.exports = (app) => {
  const BaseController = require('./base')(app)
  return class ProjectController extends BaseController {

    /**
     * 获取当前 projectKey 对应模型下的项目列表 (如果无 projectKey, 全量获取)
     */
    async getList(ctx) {
      const { proj_key: projKey } = ctx.request.query;
      const { project: projectService } = app.service;
      const projectList = projectService.getList({ projKey })
      // 构造关键数据 list
      const dtoProjectList = projectList.map(item => {
        // console.log('item', item)
        const { modelKey, key, name, desc, homePage } = item;
        return { modelKey, key, name, desc, homePage }
      });
      this.success(ctx, dtoProjectList)
    }
  }
}

四、 处理数据


目前还没有接入数据库,暂时引入本地 js文件模拟。

module.exports = (app) => {
  const BaseService = require('./base')(app)
  const modelList = require('../../model/index.js')(app)
  
  return class ProjectService extends BaseService {
    /**
     *  获取统一模型下的项目列表 (如果无 projkey, 取全量 )
     */
    getList({ projKey }) {
      return modelList.reduce((preList, modelItem) => {
        const { project } = modelItem;
        // 如果存在 projectList 则只去当前同模型下的项目, 不传的情况下则取全量.
        if (projKey && !project[projKey]) {
          return preList
        };
        for (const pKey in project) {
          preList.push(project[pKey])
        }
        return preList;
      }, [])
    }
    async getModelList() {
      return modelList
    }
  }
}

全文特别鸣谢: 抖音“哲玄前端”,《全栈实践课》


http://www.kler.cn/a/523828.html

相关文章:

  • 【电工基础】2.低压带电作业定义,范围,工作要求,电工基本工具
  • 乌兰巴托的夜---音乐里的故事
  • Hive:日志,hql运行方式,Array,行列转换
  • Java面试题2025-并发编程进阶(线程池和并发容器类)
  • 文献阅读 250128-Tropical forests are approaching critical temperature thresholds
  • DeepSeek-R1 蒸馏模型及如何用 Ollama 在本地运行DeepSeek-R1
  • oracle比较一下统计信息差异吧
  • Vue 响应式渲染 - 列表布局和v-html
  • 【2024年华为OD机试】(C卷,200分)- 推荐多样性 (JavaScriptJava PythonC/C++)
  • kaggle-ISIC 2024 - 使用 3D-TBP 检测皮肤癌-学习笔记
  • go 循环处理无限极数据
  • 【llm对话系统】大模型 RAG 之回答生成:融合检索信息,生成精准答案
  • HTML表单深度解析:GET 和 POST 提交方法
  • linux监控脚本+自动触发邮件发送
  • 【AI】【本地部署】OpenWebUI的升级并移植旧有用户信息
  • 面向对象编程 vs 面向过程编程
  • React第二十七章(Suspense)
  • mysql 学习5 mysql图形化界面DataGrip下载 安装 使用
  • MIMIC-IV数据部署(博主较忙,缓慢更新)
  • 装机爱好者的纯净工具箱
  • 算法- Z字形变换
  • Java实现FIFO缓存策略实战
  • 为什么应用程序是特定于操作系统的?[计算机原理]
  • MFC 创建Ribbon样式窗口
  • NLP模型大对比:Transformer(Bert) > RNN > n-gram
  • Linux 常用命令——系统设置篇(保姆级说明)