Паттерн MVC

Последнее обновление: 19.11.2022

Паттерн MVC является одним из распространенных паттернов, применяемых в веб-приложениях. В том числе он применяется и в приложениях на Node.js.

Паттерн MVC включает ряд компонентов:

  • Модели определяют структуру и логику используемых данных

  • Представления (views) определяет визуальную часть, как данные будут отображаться

  • Контроллеры обрабатывают входящие http-запросы, используя для обработки модели и представления, и отправляет в ответ клиенту некоторый результат обработки, нередко в виде html-кода.

  • Система маршрутизация как дополнительный компонент сопоставляет запросы с маршрутами и выбирает для обработки запросов определенный контроллер.

В общем случае, когда к приложению приходит запрос, система маршрутизации выбирает нужный контроллер для обработки запроса. Контроллер обрабатывает запрос. В процессе обработки он может обращаться к данным через модели и для рендеринга ответа использовать представления. Результат обработки контроллера отправляется в ответ клиенту. Нередко ответ представляет html-страницу, которую пользователь видит в своем браузере.

Паттерн MVC в Node.js

Вкратце рассмотрим, как мы можем применять паттерн MVC в приложениях Node.js.

Контроллеры

Контроллеры в паттерне MVC позволяют связать представления и модели и выполняют некоторую логику по обработке запроса.

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

npm install express --save

В главном файле приложения определим следующий код:

const express = require("express");
const app = express();

// определяем роутеры
const userRouter = express.Router();  // для адресов с "/users"

userRouter.use("/create", function (request, response){
    response.send("Добавление пользователя");
});
userRouter.use("/", function(request, response){
    response.send("Список пользователей");
});
// сопоcтавляем роутер с конечной точкой "/users"
app.use("/users", userRouter);

// общие обработчики
app.get("/about", function (request, response) {
    response.send("О сайте");
});
app.get("/", function (request, response) {
    response.send("Главная страница");
});

// обработка ошибки 404
app.use(function (req, res, next) {
    res.status(404).send("Not Found")
});

app.listen(3000);

В приложении определен роутер , который сопоставляется с адресами на "/users", например, "localhost:3000/users/create", а также два общих адреса: главная страница и адресом "/about".

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

Создание контроллеров

Теперь изменим приложение, вынеся всю логику обработки в контроллеры. Для этого определим в каталоге приложения новую папку, которую назовем controllers. Создадим в этой папке новый файл userController.js со следующим кодом:

exports.addUser = function (request, response){
    response.send("Добавление пользователя");
};
exports.getUsers = function(request, response){
    response.send("Список пользователей");
};

Далее добавим в папку controllers второй файл homeController.js со следующим кодом:

exports.index = function (request, response) {
    response.send("Главная страница");
};
exports.about = function (request, response) {
    response.send("О сайте");
};

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

Теперь используем эти контроллеры в файле приложения:

const express = require("express");
const app = express();
const userController = require("./controllers/userController.js");
const homeController = require("./controllers/homeController.js");

// определяем Router
const userRouter = express.Router();
const homeRouter = express.Router();
 
// определяем маршруты и их обработчики внутри роутера userRouter
userRouter.use("/create", userController.addUser);
userRouter.use("/", userController.getUsers);
app.use("/users", userRouter);

// определяем маршруты и их обработчики внутри роутера homeRouter
homeRouter.get("/about", homeController.about);
homeRouter.get("/", homeController.index);
app.use("/", homeRouter);

app.use(function (req, res, next) {
    res.status(404).send("Not Found")
});

app.listen(3000, ()=>console.log("Сервер запущен и ожидает подключения..."));

Контроллеры подключаются как стандартные модули, и затем функции контроллеров используются для обработки маршрутов. Кроме того, для упрощения логической организации маршруты, которые обрабатываются контроллером homeController, организованы в отдельный роутер - homeRouter.

Вдесь следует отметить, что мы можем добавлять обработку маршрутов с помощью разных методов, так, в примере выше применяются методы use и get:

userRouter.use("/create", userController.addUser);
homeRouter.get("/about", homeController.about);

В данном случае это не принципиально, можно и в первой строке использовать метод get():

userRouter.get("/create", userController.addUser);
homeRouter.get("/about", homeController.about);

Просто надо учитывать тип запросов, который будут обрабатываться по этому маршруту. Так, метод get() ограничивается только get-запросами.

Определение маршрутов

Однако в данном случае опять же стоит отметить, что внутри каждого роутера может быть определено множество маршрутов. В этом случае для упрощения управления маршрутами каждый роутер организуется и подключается в виде отдельного модуля. Для этого добавим в проект новую папку routes. Затем в этой папке создадим новый файл homeRouter.js и определим в нем следующий код:

const express = require("express");
const homeController = require("../controllers/homeController.js");
const homeRouter = express.Router();

homeRouter.get("/about", homeController.about);
homeRouter.get("/", homeController.index);

module.exports = homeRouter;

По сути здесь определен весь связанный с роутером homeRouter код. Также добавим в папку routes новый файл userRouter.js, в который добавим код для второго роутера:

const express = require("express");
const userController = require("../controllers/userController.js");
const userRouter = express.Router();

userRouter.use("/create", userController.addUser);
userRouter.use("/", userController.getUsers);

module.exports = userRouter;

После этого весь проект будет выглядеть следующим образом:

MVC контроллеры в Node.js

Теперь изменим файл приложения:

const express = require("express");
const app = express();
const userRouter = require("./routes/userRouter.js");
const homeRouter = require("./routes/homeRouter.js");

app.use("/users", userRouter);;
app.use("/", homeRouter);

app.use(function (req, res, next) {
    res.status(404).send("Not Found")
});

app.listen(3000, ()=>console.log("Сервер запущен и ожидает подключения..."));

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

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850