Введение в ThinkJS + пример (для реализации основных функций, таких как орган аутентификации)

Node.js база данных MongoDB koa ThinkJS

Это статья о фреймворке ThinkJS, потому что в Интернете очень мало информации о фреймворке, поэтому здесь я объясню свое базовое понимание фреймворка и предоставлю проект для отработки основных функций.

Поскольку это фреймворк на основе Node.js, давайте начнем с небольшого знания Node.js для начинающих.

Коротко о Node.js

Node.js: Проще говоря, Node.js — это JavaScript, работающий на сервере.

Конфигурация установки Node.js(Представьте метод установки Node.js в Windows и Linux)

Node.js Официальные документы

Введение в официальную документацию:

  • Node.js — это среда выполнения JavaScript, основанная на движке Chrome V8.
  • Node.js используетМодель управляемого событиями неблокирующего ввода-вывода, что делает его легким и эффективным.. Управляемый событиями и асинхронный ввод-вывод
  • Node.jsменеджер пакетов нпм, является крупнейшей в мире экосистемой библиотек с открытым исходным кодом.

Знакомьтесь с менеджером пакетов npm(npm уже установлен при установке Node.js)

Когда мы разрабатываем на Node.js, мы используем много кода JavaScript, написанного другими. Если нам нужно использовать пакет, написанный кем-то другим, очень обременительно искать официальную документацию по имени, скачивать код, распаковывать его и использовать снова. Так появился инструмент централизованного управления: каждый упаковал разработанные им модули и выложил их на официальный сайт npm.Если вы хотите их использовать, вы можете установить их прямо через npm и использовать их напрямую.Независимо от того, где существует код, надо скачать откуда.

Что еще более важно, если мы хотим использовать модуль A, а модуль A зависит от модуля B, а модуль B зависит от других модулей, то npm может загружать и управлять всеми зависимыми пакетами в соответствии с зависимостями. В противном случае полагаться на собственное ручное управление определенно будет проблематично и подвержено ошибкам.

Первая Node-программа

Узнайте о компонентах приложения Node.js:

  1. Внедрить необходимые модули: мы можем использовать директиву require для загрузки модулей Node.js.
  2. Создать сервер: сервер может прослушивать запрос клиента, аналогично Apache, Nginx и другим серверам.
  3. Получать запрос и запрос на ответ: сервер легко создать, клиент может использовать браузер или терминал для отправки http-запросов, а сервер возвращает соответствующие данные после получения запроса.

Создайте приложение Node.js:

Шаг 1. Внедрите необходимый модуль

Используйте команду require для загрузки модуля http и назначьте экземпляр HTTP переменной http. Пример выглядит следующим образом:

var http = require('http');

Шаг 2: Создайте сервер

Далее мы используемhttp.createServer()метод для создания сервера и используйте метод прослушивания для привязки порта 8888. проход функцииrequest,responseпараметры для получения и ответа на данные. Примеры следующие:

var http = require('http');  //请求Node.js自带的http模块,并且把它赋值给http变量
http.createServer(function (request, response) {  //调用http模块提供的模块
    // 发送 HTTP 头部 
    // HTTP 状态值: 200 : OK
    // 内容类型: text/plain
    response.writeHead(200, {'Content-Type': 'text/plain'});

    // 发送响应数据 "Hello World"
    response.end('Hello World\n');
}).listen(8888);

// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');

Бэкэнд-фреймворк Node.js

Express и Koa (типовые фреймворки)

Express: легкая и гибкая платформа node.js, которая позволяет быстро создавать приложения и широко используется.Экспресс официальная документация

Koa: созданный первоначальной командой Express, он призван стать меньшим, более выразительным и более надежным краеугольным камнем разработки веб-приложений и API. Используя асинхронные функции, koa помогает вам отказаться от обратных вызовов и значительно улучшить обработку ошибок.Официальная документация Коа

Express и Koa — две самые основные серверные среды для node.js. Поскольку создание приложения по-прежнему требует большого количества вспомогательного кода, поверх них появилось множество других фреймворков, позволяющих сократить объем написания такого кода. (Пример: ThinkJS, egg.js и т. д.)

ThinkJS

Введение: ThinkJS — это ориентированная на будущее среда Node.js, которая объединяет большое количество лучших практик проекта, чтобы сделать разработку на уровне предприятия простой и эффективной. Начиная с версии 3.0 нижний слой фреймворка реализован на основе Koa2.x, который совместим со всеми функциями Koa.

характеристика:

  • Основан на Koa2.x, совместимmiddleware
  • Ядро маленькое и поддерживаетExtend,AdapterИ другие плагины
  • Отличная производительность и высокое покрытие юнит-тестами
  • Встроенная автоматическая компиляция, механизм автоматического обновления, удобная и быстрая разработка
  • используйте более элегантныйasync/awaitОбработка асинхронных проблем, больше не поддерживается*/yieldСпособ

Быстрый старт

С помощью строительных лесов с ThinkJ вы можете быстро создать проект. Чтобы использовать больше функций ES6, для платформы требуются версии Node.js не ниже 6.x, для чего рекомендуется использовать версию LTS.

Установите команду ThinkJS

npm install -g think-cli

После завершения установки в системе появится команда thinkjs (номер версии think-cli можно проверить через thinkjs-v)

Создать проект


thinkjs new demo  //创建名为demo的项目
npm install   //安装依赖
npm start  //运行项目

Структура проекта

Структура проекта, созданная по умолчанию, выглядит следующим образом:

|--- development.js   //开发环境下的入口文件
|--- nginx.conf  //nginx 配置文件
|--- package.json
|--- pm2.json //pm2 配置文件
|--- production.js //生产环境下的入口文件
|--- README.md
|--- src
| |--- bootstrap  //启动自动执行目录 
| | |--- master.js //Master 进程下自动执行
| | |--- worker.js //Worker 进程下自动执行
| |--- config  //配置文件目录
| | |--- adapter.js  // adapter 配置文件 
| | |--- config.js  // 默认配置文件 
| | |--- config.production.js  //生产环境下的默认配置文件,和 config.js 合并 
| | |--- extend.js  //extend 配置文件 
| | |--- middleware.js //middleware 配置文件 
| | |--- router.js //自定义路由配置文件
| |--- controller  //控制器目录 
| | |--- base.js
| | |--- index.js
| |--- logic //logic 目录
| | |--- index.js
| |--- model //模型目录
| | |--- index.js
|--- view  //模板目录
| |--- index_index.html

основные функции

Конфигурация

В реальном проекте определенно требуются различные конфигурации, в том числе: конфигурация, требуемая фреймворком, и конфигурация, настроенная проектом. ThinkJS управляет всеми конфигурациями унифицированным образом, а файлы размещаются в каталоге src/config/ и делятся на разные файлы конфигурации в соответствии с различными функциями.

  • config.jsНекоторые распространенные конфигурации
  • adapter.jsКонфигурация адаптера (конфигурация базы данных)
  • router.jsПользовательская конфигурация маршрутизации
  • middleware.jsконфигурация промежуточного программного обеспечения
  • validator.jsКонфигурация проверки данных
  • extend.jsрасширить конфигурацию

формат конфигурации

// src/config.js

module.exports = {
  port: 1234,
  redis: {
    host: '192.168.1.2',
    port: 2456,
    password: ''
  }
}

Значением конфигурации может быть простая строка или сложный объект Конкретный тип определяется в соответствии с конкретными требованиями.

использовать конфигурацию

Платформа предоставляет различные способы быстрого получения конфигурации в различных средах:

  • В ctx (контексте) это можно сделать с помощьюctx.config(key)чтобы получить конфигурацию
  • В контроллере вы можете передатьcontroller.config(key)чтобы получить конфигурацию
  • В остальных случаях черезthink.config(key)чтобы получить конфигурацию

По факту,ctx.configиcontroller.configоснован наthink.configОбертка для более удобного получения конфигурации.

Адаптер (адаптер)

Адаптер используется для решения нескольких реализаций класса функций, эти реализации предоставляют набор одного и того же интерфейса, аналогичного фабричному шаблону в шаблоне проектирования. как:Поддерживает несколько баз данных, поддерживает несколько шаблонизаторов и т. д. Таким образом, легко переключаться между различными типами. Адаптер обычно используется вместе с Extend.

Платформа по умолчанию предоставляет множество адаптеров, например:View、Model、Cache、Session、Websocket, проект также может быть расширен по мере необходимости или может быть введен сторонний адаптер.

Конфигурация адаптера

Файл конфигурации адаптераsrc/config/adapter.js, формат следующий:

const nunjucks = require('think-view-nunjucks');
const ejs = require('think-view-ejs');
const path = require('path');

exports.view = {
  type: 'nunjucks', // 默认的模板引擎为 nunjucks
  common: { //通用配置
    viewPath: path.join(think.ROOT_PATH, 'view'),
    sep: '_',
    extname: '.html'
  },
  nunjucks: { // nunjucks 的具体配置
    handle: nunjucks
  },
  ejs: { // ejs 的具体配置
    handle: ejs,
    viewPath: path.join(think.ROOT_PATH, 'view/ejs/'),
  }
}

exports.cache = {
  ...
}

Конфигурация адаптера поддерживает операционную среду, и различные конфигурации могут быть установлены в соответствии с различными операционными средами.Например, базы данных в среде разработки и производственной среде обычно отличаются.adapter.development.jsиadapter.production.jsХраните различные конфигурации.После запуска системы соответствующая конфигурация операционной среды и конфигурация по умолчанию будут прочитаны и объединены.

Анализ конфигурации адаптера

Подробная конфигурация хранилища конфигурации адаптера всех типов, которую необходимо разрешить, используется для выбора соответствующего конкретного использования. Например, приведенный выше файл конфигурации, конфигурацияnunjucksиejsПодробная настройка двух механизмов шаблонов, но в одном сценарии будет использоваться только один механизм шаблонов. Конечно, синтаксический анализ конфигурации не требует от пользователя специального вызова проекта, и обычно он обрабатывается в методе, соответствующем подключаемому модулю.

Использование адаптера

Адаптеры — это разные реализации класса функций, как правило, они не могут использоваться самостоятельно, а используются вместе с соответствующими расширениями. как:view Adapter(think-view-nunjucks、think-view-ejs)Сотрудничатьthink-viewрасширение для использования.

база данных:(model AdapterСотрудничатьthink-mongoРасширения для использования)

model adapter

/**
 * model adapter config
 * @type {Object}
 */
exports.model = {
  type: 'mongo', // 默认使用的类型,调用时可以指定参数切换
  common: { // 通用配置
    logConnect: true, // 是否打印数据库连接信息
    logger: msg => think.logger.info(msg) // 打印信息的 logger
  },
  mongo: {
    host: '127.0.0.1',
    port: 27017,
    user: '',
    password: '',
    database: 'manannan', // 数据库名称
    options: ''
  }
};

extend

const view = require('think-view');
const model = require('think-model');
const cache = require('think-cache');
const session = require('think-session');
const mongo = require('think-mongo');

module.exports = [
  view, // make application support view
  model(think.app),  ////将 think.app 传递给 model 扩展
  mongo(think.app),
  cache,
  session
];

Продлевать

Хотя фреймворк имеет множество встроенных функций, при реальной разработке проекта предоставляемых функций далеко не достаточно. В версии 3.0 был введен механизм расширения, облегчающий расширение фреймворка. Поддерживаемые типы расширений:think,application,context,request,response,controller,logicиservice.

Многие функции, встроенные в фреймворк, также реализуются расширениями, например:Session,Cache.

Контекст (контекст)

Контекст - это обработка целевой пользовательский запрос KOA, запрос на протяжении всего жизненного цикла. В целомmiddleware,controller,logicиспользуется в , именуемый ctx.

Платформа наследует этот объект и расширяет многие полезные свойства и методы с помощью механизма Extend.

Например:

ctx.state

Рекомендуемое пространство имен при передаче информации между промежуточным ПО и отправке информации в шаблоны. Избегайте добавления свойств непосредственно в ctx, что может перезаписать существующие свойства и вызвать странные проблемы.

ctx.state.user = await User.find(id);

Таким образом, в контроллере вы можете пройтиthis.ctx.state.userЧтобы получить соответствующее значение.

module.exports = class extends think.Controller {
  indexAction() {
    const user = this.ctx.state.user;
  }
}

ctx.header

Получить всю информацию заголовка, эквивалентнуюctx.request.header.

const headers = ctx.headers;

ctx.headers

Получить всю информацию заголовка, эквивалентнуюctx.header.

ctx.url

Получите адрес запроса.

ПО промежуточного слоя

Промежуточное программное обеспечение называется промежуточным программным обеспечением, что является очень важной концепцией в KOA. Используя промежуточное программное обеспечение, очень удобно обрабатывать запросы пользователей.

Формат промежуточного ПО является функцией более высокого порядка, и внешняя функция получаетoptionsпараметры, чтобы промежуточное ПО могло предоставить некоторую информацию о конфигурации для включения/отключения некоторых функций. Возвращает другую функцию после выполнения, эта функция получаетctx, nextпараметры, гдеctxзаcontextАббревиатура , представляет собой объект текущего жизненного цикла запроса, в котором хранится некоторая релевантная информация о текущем запросе,nextДля вызова последующего ПО промежуточного слоя возвращаемое значение — Promise, что упрощает обработку логики постобработки. (Процесс исполнения — луковая модель)

формат конфигурации

Чтобы упростить управление и использование промежуточного программного обеспечения, платформа использует файл конфигурации для управления промежуточным программным обеспечением.src/config/middleware.js.

const path = require('path')
const isDev = think.env === 'development'

module.exports = [
  {
    handle: 'meta', // 中间件处理函数
    options: {   // 当前中间件需要的配置
      logRequest: isDev,
      sendResponseTime: isDev,
    },
  },
  {
    handle: 'resource',
    enable: isDev, // 是否开启当前中间件
    options: {
      root: path.join(think.ROOT_PATH, 'www'),
      publicPath: /^\/(static|favicon\.ico)/,
    },
  }
]

Элемент конфигурации представляет собой список промежуточного программного обеспечения, которое будет использоваться в проекте, каждый элемент поддерживаетhandle,enable,options,matchи другие свойства.

handle

Функция обработки промежуточного программного обеспечения может быть встроена в системе, импортирована извне, или промежуточное программное обеспечение в проекте.

enable

Включить ли текущее промежуточное ПО.

options

Элемент конфигурации передается промежуточному программному обеспечению, формат является объектом, а конфигурация получается из промежуточного программного обеспечения.

match

После сопоставления определенного правила выполнить промежуточное программное обеспечение, поддерживает два способа, один является путь для соответствия пользовательской функции для совпадения.

Встроенное промежуточное ПО фреймворка

Фреймворк имеет несколько встроенных промежуточных программ, на которые можно напрямую ссылаться в виде строк.

  • metaОтображение некоторой метаинформации. Например: отправка номера версии ThinkJS, время обработки интерфейса и т. д.
  • resourceДля обработки статических ресурсов рекомендуется закрыть производственную среду и использовать веб-сервер для обработки его напрямую.
  • traceПри работе с ошибками среда разработки будет отображать и обрабатывать подробные сообщения об ошибках, и вы также можете настроить отображение страниц ошибок.
  • payloadОбрабатывает отправку форм и загрузку файлов, аналогичноkoa-bodyparserЖдатьmiddleware
  • routerРазбор маршрута, включая разбор пользовательского маршрута
  • logicлогический вызов, проверка данных
  • controllerконтроллер и действие

Пользовательские промежуточные программы проекта

Иногда промежуточное программное обеспечение добавляется в проект в соответствии с какими-то конкретными потребностями, тогда его можно разместить вsrc/middlewareкаталог, а затем вы можете напрямую ссылаться на него по строке.

// middleware/log.js

const defaultOptions = {
  consoleExecTime: true // 是否打印执行时间的配置
}
module.exports = (options = {}) => {
  // 合并传递进来的配置
  options = Object.assign({}, defaultOptions, options);
  return (ctx, next) => {
    if(!options.consoleExecTime) {
      return next(); // 如果不需要打印执行时间,直接调用后续执行逻辑
    }
    const startTime = Date.now();
    let err = null;
    // 调用 next 统计后续执行逻辑的所有时间
    return next().catch(e => {
      err = e; // 这里先将错误保存在一个错误对象上,方便统计出错情况下的执行时间
    }).then(() => {
      const endTime = Date.now();
      console.log(`request exec time: ${endTime - startTime}ms`);
      if(err) return Promise.reject(err); // 如果后续执行逻辑有错误,则将错误返回
    })
  }
}

Использование: в/src/config/middleware.js

module.exports = [
  {
    handle: 'log', // 中间件处理函数
    options: {   // 当前中间件需要的配置
      consoleExecTime: true,
    },
  }
]

Внедрить внешнее промежуточное ПО

Внедрить внешнее промежуточное ПО очень просто, просто нужноrequireПросто заходи.

const cors = require('koa2-cors');
module.exports = [
  ...,
  {
    handle: cors,
    option: {
      origin: '*'
    }
  },
  ...
]

Контроллер

Модель MVC, обрабатывающая логический контроллер, является частью запроса пользователя. Например: связанные с пользователем операции вuser.jsКаждая операция в нем является действием.

создать контроллер

Контроллер в проекте должен наследоватьthink.Controllerкласс, чтобы можно было использовать некоторые встроенные методы. Конечно, в проекте могут быть созданы некоторые общие базовые классы, а затем фактические контроллеры наследуются от этого базового класса.

При создании проекта создается файл с именемbase.jsБазовый класс, другоеcontrollerНаследовать этот класс.

Выполнение действия

Выполнение действия через промежуточное ПОthink-controllerсделаноctx.actionЗначение находит имя метода xxxAction в контроллере и вызывает его, а также вызывает соответствующий магический метод в определенном порядке:

  • Создайте экземпляр класса Controller, передайтеctxобъект

  • Если метод __Before существует, позвоните, если возвращаемое значениеfalse, затем остановите и продолжите выполнение

  • если методxxxActionСуществование выполняется, если возвращаемое значениеfalse, затем остановите и продолжите выполнение

  • если методxxxActionне существует, но метод __call существует, __call вызывается, если возвращаемое значениеfalse, затем остановите и продолжите выполнение

  • Если метод __after существует, выполнить предоперацию __before

  • Выполнить, если метод __after существует

До операции __до

В проекте иногда необходимо делать какие-то операции в унифицированном месте, такие как: судя по тому, авторизовались ли вы, если вы не авторизовались, вы не можете продолжать последующее поведение. В этом случае встроенный__beforeреализовать.

__beforeОн вызывается до того, как вызывается бетонное действие, так что в нем может быть сделана некоторая обработка.

Если вам нужно позвонить в класс, наследует родителей__beforeметод, черезsuper.__beforeЧто нужно сделать.

После операции __после

После операции__afterи__beforeСоответственно, он выполняется только после выполнения определенного действия, если выполнение конкретного действия возвращаетfalse,Так__afterбольше не выполняется.

Logic

При обработке запроса пользователя в Action часто необходимо сначала получить данные, отправленные пользователем, а затем проверить их, при правильности проверки можно выполнять последующие операции, когда проверка параметра завершена, иногда необходимо выполнить оценку разрешений и т. д. Только после того, как эти оценки будут правильными, можно будет проводить реальную логическую обработку. Если эти коды помещаются в действие, код действия обязательно будет очень сложным и многословным.

Чтобы решить эту проблему, ThinkJS добавляет слой логики перед контроллером.Действия в логике соответствуют действиям в контроллере один к одному.Система автоматически вызывает действия в логике перед вызовом действий в контроллере.

Маршрутизатор

Когда пользователь получает доступ к адресу, должна быть соответствующая логика для его обработки. При традиционном методе обработки файл, соответствующий запросу, например доступ,/user/about.php, то в каталоге, соответствующем проекту, появится/user/about.phpэтот файл сущности. Хотя этот метод может решить проблему, он приведет к большому количеству файлов, и в то же время многие функции файловой логики могут быть относительно простыми.

В текущей модели разработки MVC обычно для решения этой проблемы используется маршрутизация. Решение: в первую очередь запрашивающая запись пользователя сопоставляется с документом (например:index.php), затем платформа анализирует адрес текущего запроса, анализирует соответствующую функцию, которая должна быть выполнена в соответствии с конфигурацией или соглашением, и, наконец, вызывает и отвечает на запрос пользователя.

Поскольку Node.js запускает службу HTTP(S) самостоятельно, запрос пользователя был объединен в файл записи, что упрощает обработку сопоставления маршрутов.

В Thinkjs, когда пользователь обращается к URL и, наконец, контроллером в ответ на конкретное действие. Поэтому нам нужно анализировать соответствующий контроллер и действий URL-адреса, этот анализ проводится черезthink-routerмодуль для достижения.

конфигурация маршрутизации

think-routerЭто промежуточное программное обеспечение, оно было добавлено в файл конфигурации по умолчанию при создании проекта.src/config/middleware.jsПереулок.

Предварительная обработка пути

Когда пользователи получают доступ к сервису черезctx.urlсвойства, вы можете получить начальныйpathname, а для удобства последующегоpathnameЧтобы разобрать контроллер и действие, необходимо предварительно обработать путь. Например, удалить URL.htmlсуффикс и другие операции, и, наконец, получить фактический последующий синтаксический анализpathname. Правила разрешения маршрута по умолчанию/controller/action.

Для контроллера в ThinkJS можно настроить роутер без написания файла router.

pathname Контроллер подмножества controller action Примечание
/ никто index index контроллер, действие является значением конфигурации по умолчанию
/user никто user index действие является значением конфигурации по умолчанию
/user/login никто user login
/console/user/login имеют console/user login Иметь подмножество консоли/пользователя контроллера
/console/user/login/aaa/b имеют console/user login Остальные aaa/b не анализируются

настраиваемые правила маршрутизации

Хотя метод анализа маршрута по умолчанию может соответствовать требованиям, иногда URL-адрес не выглядит элегантно. Мы предпочитаем, чтобы URL-адрес был короче, что будет более удобно для запоминания и распространения. Платформа предоставляет настраиваемую маршрутизацию для удовлетворения этой потребности.

Файл конфигурации пользовательского правила маршрутизацииsrc/config/router.jsправило маршрутизации представляет собой двумерный массив.

Асинхронная обработка

Node.js использует модель неблокирующего ввода-вывода, управляемую событиями, и многие интерфейсы являются асинхронными, например операции с файлами, сетевые запросы. Хотя синхронные интерфейсы для файловых операций предоставляются, эти интерфейсы являются блокирующими и не должны использоваться, за исключением особых случаев.

Для асинхронных интерфейсов официальным API являетсяcallbackФорма, но этот метод легко появляется после того, как бизнес-логика сложнаcallback hellПроблема, чтобы решить эту проблему, возникла одна за другойevent,Promise,Generator function,Async functionи другие решения, Thinkjs используетasync functionРешения для решения асинхронной проблемы.

Async functions

АСИНХРОНИЧЕСКИЕ ФУНКЦИИasync/awaitФункции определения синтаксиса, такие как:

async function fn() {
  const value = await getFromApi();
  doSomethimgWithValue();
}
  • имеютawaitДолжен иметьasync, но сasyncне обязательно иметьawait
  • Async functionsМожет быть нормальной функцией илиArrow functionsПуть
  • awaitнужно подключить позжеPromise,если неPromise, он не будет ждать обработки
  • Возвращаемое значение должно бытьPromise

возвращаемое значение иawaitСледующие выраженияPromise, то естьAsync functionsотPromiseОснова. еслиawaitВозвращаемое значение следующего выражения неPromise, то его нужно как-то обернутьPromise.

Модель/база данных

Реляционная база данных (MYSQL)

При разработке проекта часто необходимо работать с базой данных (например, добавлять, удалять, изменять, запрашивать и т. д.), очень сложно писать операторы SQL вручную, и в то же время обращать внимание на такие вопросы безопасности, как SQL-инъекция. Эта структура предоставляет функцию модели для облегчения работы с базой данных.

Модель расширяемости

Фреймворк не предоставляет функцию модели по умолчанию, и для ее поддержки необходимо загрузить соответствующее расширение.think-model. Изменить расширенный файл конфигурацииsrc/config/extend.js, добавьте следующую конфигурацию:

const model = require('think-model');
module.exports = [
  model(think.app) // 让框架支持模型的功能
];

база данных конфигурации

Поскольку модель должна поддерживать несколько баз данных, формат файла конфигурации — «Адаптер», а путь к файлу —src/config/adapter.js

Mysql

Адаптер Mysqlthink-model-mysql, нижний слой реализован на основе библиотеки mysql, а для подключения к БД используется пул соединений, количество соединений по умолчанию равно 1.

const mysql = require('think-model-mysql');
exports.model = {
  type: 'mysql',
  mysql: {
    handle: mysql, // Adapter handle
    user: 'root', // 用户名
    password: '', // 密码
    database: '', // 数据库
    host: '127.0.0.1', // host
    port: 3306, // 端口
    connectionLimit: 1, // 连接池的连接个数,默认为 1
    prefix: '', // 数据表前缀,如果一个数据库里有多个项目,那项目之间的数据表可以通过前缀来区分
  }

Создать файл модели

файл модели вsrc/model/В каталоге наследуйте базовый класс моделиthink.Model, формат файла:

// src/model/user.js
module.exports = class extends think.Model {
  getList() {
    return this.field('name').select();
  }
}

конкретизированная модель

Когда проект запускается, все файлы модели в проекте будут отсканированы, а после сканирования все классы моделей будут сохранены вthink.app.modelsНа объекте он будет искать из этого объекта, когда он будет искать, и если он не найден, модель базового класса Model.Model будет создан.

CRUD-операции

think.ModelБазовый класс предоставляет расширенные методы для операций CRUD, которые будут представлены один за другим ниже.

думаю is.org/this-cai/doc/3…

MongoDB

Иногда реляционные базы данных не соответствуют потребностям проекта и для хранения данных требуется MongoDB. структура обеспечиваетthink-mongoРасширенный для поддержки MongoDB, этот модуль основан наmongodbосуществленный.

Настроить базу данных MongoDB

MongoDB 的数据库配置复用了关系数据库模型的配置,为 adapter 配置,放在 model 下。文件路径为 `src/config/adapter.js`

exports.model = {
  type: 'mongo', // 默认使用的类型,调用时可以指定参数切换
  common: { // 通用配置
    logConnect: true, // 是否打印数据库连接信息
    logger: msg => think.logger.info(msg) // 打印信息的 logger
  },
  mongo: {
    host: '127.0.0.1',
    port: 27017,
    user: '',
    password: '',
    database: '', // 数据库名称
    options: {
      replicaSet: 'mgset-3074013',
      authSource: 'admin'
    }
  }
}

Расширение функциональности MongoDB

Изменить расширенный файл конфигурацииsrc/config/extend.js, добавьте следующую конфигурацию:

const mongo = require('think-mongo');

module.exports = [
  mongo(think.app) // 让框架支持模型的功能
]

После добавления расширения оно будет внедреноthink.Mongo,think.mongo,ctx.mongoиcontroller.mongoМетод, гдеthink.MongoЭто файл базового класса модели Mongo, а другой — метод создания экземпляра модели Mongo.ctx.mongoиcontroller.mongoдаthink.mongoМетоды упаковки.

Создать файл модели

файл модели вsrc/model/В каталоге наследуйте базовый класс моделиthink.Mongo, формат файла:

// src/model/user.js
module.exports = class extends think.Mongo {
  getList() {
    return this.field('name').select();
  }
}

конкретизированная модель

Когда проект запустится, все файлы модели в проекте будут отсканированы (каталогsrc/model/), после сканирования все классы моделей будут сохранены вthink.app.modelsНа объекте он будет искаться из этого объекта при создании экземпляра, и если он не будет найден, будет создан экземпляр базового класса модели.think.Mongo.

API

думаю is.org/this-cai/doc/3…

думаю объект

Встроенная рамкаthinkГлобальный объект, удобный для использования в любом месте проекта.

API

думаю is.org/this-cai/doc/3…

Начать пользовательский

Проходятnpm startилиnode production.jsКогда вы запускаете проект, хотя вы можете добавить дополнительный логический код в эти входные файлы, он не рекомендуется. Система дает другие запускающие порталы.

bootstrap

будет загружаться при запуске системыsrc/boostrap/Файлы в каталоге, в частности:

  • Загружается, когда главный процесс не работаетsrc/bootstrap/master.js
  • Загружается, когда рабочий процесс не работаетsrc/bootstrap/worker.js

Поэтому некоторая логика, которая должна выполняться при старте системы, может выполняться в соответствующем файле.

Сервис / Услуги

Служебные файлы хранятся вsrc/service/В каталоге формат содержимого файла следующий:

//  src/service/user.js
module.exports = class extends think.Service {
  find(id){
     return {username:'123',id:id} 
  }
}

ServiceНаследоватьthink.Serviceбазовый класс, но этот базовый класс не предоставляет никаких методов, которые могут бытьExtendрасширять.

Создайте экземпляр класса службы

в состоянии пройтиthink.serviceсоздание экземпляра методаServiceclass, в контроллере и ctx также есть соответствующие сервисные методы, такие как:ctx.service,controller.serviceЭти методыthink.serviceярлык.

//controller

think.service('user').find(111)

Когда проект запустится, он просканирует всеservicesфайл и сохраните его вthink.app.servicesПод объектом будет выполняться поиск соответствующего файла класса из объекта при создании экземпляра, и если он не будет найден, будет сообщено об ошибке.

Вышеизложенное является базовым пониманием фреймворка.Если вы новичок в фреймворке, вы должны понимать базовую конфигурацию в src, в том числе, как добавить адаптер для базы данных и расширить модель, а затем управлять базой данных на уровне модели. , Функция интерфейса (API) может быть реализована посредством внешнего и внутреннего взаимодействия уровня контроллера, и требуется дальнейшее углубленное изучение.

Исходный код проекта:GitHub.com/Пожалуйста, подумай просто…

Примечание. В этом проекте используется база данных mongoDB. Знакомство с основными функциями проекта:

1. Получите заголовок внешнего запроса (токен) для реализации аутентификации пользователя.

//   controller/base.js
const jwt = require('jsonwebtoken');
const Token = require('../logic/token');

module.exports = class extends think.Controller {
    async __before() {
        if (this.ctx.config('allowUrls').indexOf(this.ctx.url) === -1) {
            if (!this.ctx.request.header.authorization) {
                this.fail(401, '没有认证');
                return false;
            } else {
                let payload = null;
                const authorization = this.ctx.request.header.authorization;
                const secret = this.ctx.config('secret');
                try {
                    payload = jwt.verify(authorization, secret); 
                     // 该验证函数在logic/token
                    await Token.verify(authorization);
                    this.ctx.state.user_id = payload._id;
                } catch (error) {
                    this.fail(error.code, error.message);
                    return false;
                }
            }
        }
    }
};

2. Установите токен, сохраните его в Redis и установите время истечения срока действия.

//controller/user.js
 // 用户登录
    async loginUserAction() {
        const user = await this.mongo('user').loginUser(this.post('account'), this.post('password'));
        if (think.isEmpty(user)) {
            this.fail(403, '登陆失败,用户名或密码错误');
        } else {
            let payload = {_id: user._id, account: user.account, password: user.password};
            let token = jwt.sign(payload, think.config('secret'), {expiresIn: 60 * 60 * 24 * 30});
            redis.set(token, payload._id.toString());
            redis.expire(token, token_expire);
            return this.success({token}, '用户登陆成功');
        }
    }

3. Push-сообщения в режиме реального времени от wamp

//controller/wamp.js
const autobahn = require('autobahn');
const wampConfig = require('../config/config').wamp;
const options = wampConfig.options;

module.exports = {
    roomInfo: (args) => {
        const connection = new autobahn.Connection(options);
        console.log("连接信息",connection);
        connection.onopen = function (session) {
            session.publish(wampConfig.definedTopic, [args]);
            console.log("wamp发布的主题是:" + wampConfig.definedTopic);
            console.log(args);
        };
        console.log("end======");
        connection.open();
    }
};
 //使用
    /**
     * @param {any} user
     * @returns
     * 添加房屋信息后推送wamp确认消息
     */
    async addRoomWamp(roomInfo) {
        let sum = 0;
        const rooms = await this.model('room').add(roomInfo);
        if(!(think.isEmpty(rooms))){
            const data = {sum: "lalal"};
            wamp.roomInfo(data);
        }
    }

4. Аутентификация

  //获取所有房源信息
    async getAllRoomsAction() {
        const userInfo = await this.mongo('user').findUserDetailInfo(this.ctx.state.user_id);
        console.log("userInfo", userInfo);
        if (!(think.isEmpty(userInfo)) && userInfo.role === 'admin') {
            this.success(await this.mongo('room').getAllRooms());
        } else {
            this.fail("没有权限访问");
        }

    }

(Реализация заключается в определении роли поступления от пользователя, можно использовать acl, тогда проект будет обновляться)