Трехуровневая архитектура — это шаблон проектирования, который разделяет приложения на веб-уровни (клиентские уровни), уровни приложений и уровни базы данных. Каждый уровень несет определенную ответственность и взаимодействует с другими уровнями через четко определенные интерфейсы. Поскольку это самый простой и популярный дизайн, в этой статье мы рассмотрим трехуровневую архитектуру с простым кодом.
Веб-слой
На веб-уровне мы обычно имеем дело с интерфейсной частью нашего приложения, которая включает в себя клиент (например, веб-браузер) и серверный код, который обрабатывает входящие запросы и отправляет ответы.
const http = require('http'); const hostname = 'localhost'; const port = 3000; const app = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World!'); }); app.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
В приведенном выше коде мы создаем новый HTTP-сервер, используя модуль http
, встроенный в Node.js. Затем мы прослушиваем входящие запросы через порт 3000 и отвечаем на каждый запрос простым текстовым сообщением «Hello World!». Конечно, в реальном приложении вы хотели бы включить более сложную логику для обработки различных типов запросов и отправки соответствующих ответов.
Прикладной уровень
На прикладном уровне мы обычно обрабатываем бизнес-логику нашего приложения. В приложении Node.js мы можем использовать архитектуру MVC, чтобы разделить задачи нашего приложения на разные компоненты. Давайте воспользуемся фреймворком Express Web для реализации простой архитектуры MVC в Node.js.
const express = require('express'); const app = express(); // Model - MySQL Database connection const mysql = require('mysql'); const connection = mysql.createConnection({ host: 'localhost', user: 'username', password: 'password', database: 'mydb' }); // View - using EJS template engine app.set('view engine', 'ejs'); // Controller - using Singleton pattern class UserController { static getInstance() { if (!UserController.instance) { UserController.instance = new UserController(); } return UserController.instance; } getUser(req, res) { // get user data from database connection.query('SELECT * FROM users WHERE id = ?', [req.params.id], (error, results) => { if (error) { console.log(error); res.status(500).send('Error retrieving user data'); } else { res.render('user', { user: results[0] }); } }); } } // Routes const userController = UserController.getInstance(); app.get('/user/:id', userController.getUser); // Start server app.listen(3000, () => { console.log('Server started on port 3000'); });
В приведенном выше коде мы сначала создаем соединение с базой данных MySQL, используя модуль mysql
. Мы также настраиваем наше приложение Express для использования механизма шаблонов EJS для рендеринга представлений.
Затем мы создаем класс UserController
, который следует шаблону Singleton, что позволяет нам совместно использовать один экземпляр контроллера в приложении. В этом примере метод getUser()
отвечает за извлечение пользовательских данных из базы данных и рендеринг представления с помощью EJS.
Наконец, мы определяем маршрут для URL-адреса /user/:id
и сопоставляем его с методом getUser()
нашего UserController
. Когда делается запрос к этому URL, вызывается метод getUser()
контроллера, который извлекает пользовательские данные из базы данных и визуализирует представление с помощью EJS.
Уровень базы данных
На уровне базы данных мы обычно имеем дело с взаимодействием с базой данных.
const mysql = require('mysql'); const connection = mysql.createConnection({ host: 'localhost', user: 'username', password: 'password', database: 'mydb' }); connection.connect((err) => { if (err) throw err; console.log('Connected to MySQL database!'); const createTableQuery = ` CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), email VARCHAR(255) ) `; connection.query(createTableQuery, (err, result) => { if (err) throw err; console.log('User table created successfully!'); }); });
В приведенном выше коде мы создаем соединение с базой данных MySQL, используя модуль mysql
. Затем мы определяем переменную createTableQuery
, содержащую SQL-запрос для создания таблицы users
со столбцами id
, name
и email
.
Наконец, мы используем метод connection.query()
для выполнения запроса SQL, который создает таблицу users
в базе данных. Если запрос выполнен успешно, мы записываем в консоль сообщение о том, что таблица создана успешно.
Реальные приложения могут обрабатывать ошибки и реализовывать более сложные взаимодействия с базой данных. Настройка сложной логики может привести к проблемам с callback hell из-за многочисленных запросов. В качестве альтернативы можно использовать ORM. Мы объясним это более подробно в разделе ORM позже.
Заключение
До сих пор мы просто использовали Express для настройки приложения с трехуровневой архитектурой. На самом деле, если вы добавите плоти к тому, что вы сделали до сих пор, и настроите дополнительную бизнес-логику, одно приложение будет завершено.
Однако до сих пор в содержании есть много недостатков. Вам понадобится больше деталей для использования в реальных проектах.
Мы вернемся с кодом, который применяет несколько шаблонов проектирования к Express в будущем Express.