hocvietcode.com
  • Trang chủ
  • Học lập trình
    • Lập trình C/C++
    • Cấu trúc dữ liệu và giải thuật
    • Lập trình HTML
    • Lập trình Javascript
      • Javascript cơ bản
      • ReactJS framework
      • AngularJS framework
      • Typescript cơ bản
      • Angular
      • NodeJS
    • Lập trình Mobile
      • Lập Trình Dart Cơ Bản
        • Dart Flutter Framework
    • Cơ sở dữ liệu
      • MySQL – MariaDB
      • Micrsoft SQL Server
      • Extensible Markup Language (XML)
      • JSON
      • MongoDB
    • Lập trình PHP
      • Lập trình PHP cơ bản
      • Laravel Framework
    • Lập trình Java
      • Java Cơ bản
    • Lập trình C#
      • Lập Trình C# Cơ Bản
      • ASP.NET Core MVC
    • Machine Learning
    • Git và Github
  • WORDPRESS
    • WordPress cơ bản
    • WordPress nâng cao
    • Chia sẻ WordPress
  • Kiến thức hệ thống
    • Microsoft Azure
    • Docker
    • Linux
  • Chia sẻ IT
    • Tin học văn phòng
      • Microsoft Word
      • Microsoft Excel
    • Marketing
      • Google Adwords
      • Facebook Ads
      • Kiến thức khác
    • Chia sẻ phần mềm
    • Review công nghệ
    • Công cụ – tiện ích
      • Kiểm tra bàn phím online
      • Kiểm tra webcam online
Đăng nhập
  • Đăng nhập / Đăng ký

Please enter key search to display results.

Home
  • NodeJS
Xây dựng ứng dụng quản lý phim với Express, EJS và MongoDB

Xây dựng ứng dụng quản lý phim với Express, EJS và MongoDB

  • 24-07-2026
  • Toanngo92
  • 0 Comments

Ở bài trước, chúng ta đã hoàn thiện các thao tác MongoDB nền tảng. Bài này bắt đầu ghép các mảnh đó thành một ứng dụng web thực tế: Wonderland Widescreen – hệ thống quản lý và đặt ghế xem phim được xây dựng bằng Node.js, Express, EJS và MongoDB.

Mục tiêu của bài là thiết lập dự án, tổ chức thư mục, tạo giao diện, kết nối MongoDB Atlas và xây dựng các route đầu tiên. Phần cập nhật, xóa phim và hoàn thiện luồng nghiệp vụ sẽ tiếp tục ở bài sau.

Mục lục

  • 1. Kiến trúc và chức năng của ứng dụng
  • 2. Quy trình triển khai
  • 3. Khởi tạo dự án Node.js
  • 4. Cấu hình biến môi trường và MongoDB
  • 5. Tạo giao diện danh sách phim bằng EJS
  • 6. Route hiển thị phim
  • 7. Tạo biểu mẫu thêm phim
  • 8. Xử lý lỗi tập trung và tắt ứng dụng an toàn
  • 9. Chạy và kiểm tra ứng dụng
  • 10. Bài tập thực hành
  • Tổng kết

1. Kiến trúc và chức năng của ứng dụng

Ứng dụng có hai nhóm người dùng. Khách có thể đăng nhập, xem phim và đặt ghế. Quản trị viên có thêm quyền thêm phim, xóa phim, cập nhật số ghế và xem thông tin đặt chỗ. Giao diện gửi yêu cầu HTTP đến Express; Express xử lý route, đọc hoặc ghi dữ liệu trong MongoDB rồi trả HTML hoặc JSON về trình duyệt.

Sơ đồ chức năng và các trang của ứng dụng Wonderland Widescreen
Sơ đồ chức năng của ứng dụng trong giáo trình.

Express định tuyến bằng các phương thức tương ứng với HTTP như app.get() và app.post(). Khi đường dẫn và phương thức khớp, hàm xử lý route được gọi. Đây là cơ chế cốt lõi để nối các nút, biểu mẫu và thao tác trên giao diện với logic phía máy chủ.

2. Quy trình triển khai

Ba bước xây dựng ứng dụng Node.js kết nối MongoDB
Ba bước chính: kết nối cơ sở dữ liệu, tạo giao diện và viết mã phía máy chủ.
  1. Kết nối cơ sở dữ liệu: lấy connection string từ MongoDB Atlas và lưu trong biến môi trường.
  2. Tạo phần giao diện: xây dựng các trang EJS, CSS và JavaScript chạy trên trình duyệt.
  3. Tạo phần máy chủ: khởi tạo Express, cấu hình middleware, định nghĩa route và gọi MongoDB.

Không nên đặt tên người dùng, mật khẩu hoặc connection string trực tiếp trong mã nguồn. Hãy dùng tệp .env, thêm tệp này vào .gitignore và chỉ chia sẻ một tệp .env.example không chứa bí mật.

3. Khởi tạo dự án Node.js

mkdir movie-application
cd movie-application
npm init -y
npm install express ejs mongodb dotenv

Giáo trình dùng thêm một số gói như body-parser, passport và express-session. Với phần đầu của ứng dụng, Express hiện đã có sẵn express.json() và express.urlencoded(), vì vậy chưa cần cài body-parser. Chỉ thêm session hoặc Passport khi triển khai đăng nhập thực sự.

movie-application/
├── public/
│   ├── css/
│   └── js/
├── views/
│   ├── movie-list.ejs
│   └── add-movie-form.ejs
├── .env
├── .gitignore
├── package.json
└── server.js
Cấu trúc thư mục dự án Node.js trong giáo trình
Cấu trúc thư mục tham khảo từ giáo trình; bài viết tách thêm thư mục public để quản lý tài nguyên tĩnh.

4. Cấu hình biến môi trường và MongoDB

Tạo tệp .env. Thay giá trị mẫu bằng connection string thật của cụm Atlas và tên cơ sở dữ liệu của bạn.

MONGODB_URI=mongodb+srv://<username>:<password>@<cluster>/?retryWrites=true&w=majority
DB_NAME=MovieCollection
PORT=3000

Mỗi đối tượng MongoClient có sẵn connection pool, vì vậy nên tạo một client dùng chung thay vì mở kết nối mới trong từng request. Ta kết nối một lần trước khi cho máy chủ lắng nghe cổng.

require('dotenv').config();
const express = require('express');
const { MongoClient } = require('mongodb');

const app = express();
const client = new MongoClient(process.env.MONGODB_URI);

app.set('view engine', 'ejs');
app.set('views', './views');
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static('public'));

let movies;

async function start() {
  await client.connect();
  const db = client.db(process.env.DB_NAME);
  movies = db.collection('MovieCollection');

  const port = process.env.PORT || 3000;
  app.listen(port, () => {
    console.log(`Server đang chạy tại http://localhost:${port}`);
  });
}

start().catch((error) => {
  console.error('Không thể khởi động ứng dụng:', error);
  process.exit(1);
});

Middleware có quyền truy cập req, res và hàm next. Nếu middleware không tự kết thúc chu kỳ request-response, nó phải gọi next(); nếu không, yêu cầu sẽ bị treo. Trong đoạn trên, ba middleware lần lượt đọc form, đọc JSON và phục vụ CSS/JavaScript/ảnh từ thư mục public.

5. Tạo giao diện danh sách phim bằng EJS

Template engine cho phép viết tệp giao diện có chỗ dành cho dữ liệu động. Khi gọi res.render(), Express đưa dữ liệu vào template EJS rồi trả về HTML hoàn chỉnh cho trình duyệt.

Giao diện danh sách phim Wonderland Widescreen
Giao diện danh sách phim mẫu của Wonderland Widescreen.
<!-- views/movie-list.ejs -->
<!doctype html>
<html lang="vi">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Wonderland Widescreen</title>
  <link rel="stylesheet" href="/css/style.css">
</head>
<body>
  <main class="container">
    <h1>Danh sách phim</h1>
    <a href="/movies/new">Thêm phim</a>

    <ul>
      <% movies.forEach((movie) => { %>
        <li>
          <strong><%= movie.name %></strong>
          — <%= movie.category %>
          — còn <%= movie.availableSeats %> ghế
        </li>
      <% }) %>
    </ul>
  </main>
</body>
</html>

Dùng thẻ <%= ... %> để xuất giá trị đã được escape. Không nên dùng <%- ... %> với nội dung do người dùng nhập vì có thể tạo lỗ hổng XSS.

6. Route hiển thị phim

app.get('/', (req, res) => {
  res.redirect('/movies');
});

app.get('/movies', async (req, res, next) => {
  try {
    const filter = req.query.category
      ? { category: req.query.category }
      : {};

    const movieList = await movies.find(filter).sort({ name: 1 }).toArray();
    res.render('movie-list', { movies: movieList });
  } catch (error) {
    next(error);
  }
});

app.get('/api/movies/:name', async (req, res, next) => {
  try {
    const movie = await movies.findOne({ name: req.params.name });
    if (!movie) return res.status(404).json({ message: 'Không tìm thấy phim' });
    res.json(movie);
  } catch (error) {
    next(error);
  }
});

Ví dụ trên hỗ trợ lọc bằng URL như /movies?category=Action. API chi tiết dùng route parameter :name. Trong ứng dụng thực tế nên dùng _id hoặc một slug duy nhất thay cho tên, vì hai phim có thể trùng tên.

7. Tạo biểu mẫu thêm phim

Biểu mẫu thêm phim trong giáo trình Node.js
Biểu mẫu thêm phim trong giáo trình.
<!-- views/add-movie-form.ejs -->
<h1>Thêm phim</h1>
<form method="post" action="/movies">
  <label>Tên phim
    <input name="name" required maxlength="120">
  </label>
  <label>Thời lượng (phút)
    <input name="duration" type="number" min="1" required>
  </label>
  <label>Số ghế
    <input name="availableSeats" type="number" min="0" required>
  </label>
  <label>Thể loại
    <select name="category" required>
      <option value="Action">Hành động</option>
      <option value="Comedy">Hài</option>
      <option value="Drama">Chính kịch</option>
    </select>
  </label>
  <button type="submit">Thêm phim</button>
</form>
app.get('/movies/new', (req, res) => {
  res.render('add-movie-form');
});

app.post('/movies', async (req, res, next) => {
  try {
    const movie = {
      name: String(req.body.name || '').trim(),
      duration: Number(req.body.duration),
      availableSeats: Number(req.body.availableSeats),
      category: req.body.category
    };

    if (!movie.name || movie.duration < 1 || movie.availableSeats < 0) {
      return res.status(400).send('Dữ liệu phim không hợp lệ');
    }

    await movies.insertOne(movie);
    res.redirect('/movies');
  } catch (error) {
    next(error);
  }
});

Thuộc tính HTML như required giúp phản hồi nhanh trên trình duyệt nhưng không thay thế kiểm tra phía máy chủ. Mọi giá trị trong req.body đều phải được coi là dữ liệu không đáng tin cậy, cần chuyển kiểu, kiểm tra phạm vi và giới hạn độ dài trước khi ghi vào MongoDB.

8. Xử lý lỗi tập trung và tắt ứng dụng an toàn

app.use((req, res) => {
  res.status(404).send('Không tìm thấy trang');
});

app.use((error, req, res, next) => {
  console.error(error);
  res.status(500).send('Máy chủ gặp lỗi');
});

async function shutdown() {
  await client.close();
  process.exit(0);
}

process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);

Middleware xử lý lỗi của Express phải có đủ bốn tham số (error, req, res, next). Hãy đặt nó sau tất cả route. Trong môi trường sản xuất, không trả stack trace hoặc thông tin kết nối cho người dùng.

9. Chạy và kiểm tra ứng dụng

node server.js

Mở http://localhost:3000. Kiểm tra lần lượt trang danh sách, bộ lọc thể loại, trang thêm phim, thông báo khi dữ liệu sai và trường hợp truy cập một URL không tồn tại.

Kết quả chạy ứng dụng Wonderland Widescreen trên localhost
Kết quả chạy phiên bản đầu tiên của ứng dụng trên localhost.

10. Bài tập thực hành

  1. Thêm ba phim mẫu vào collection và hiển thị theo thứ tự tên.
  2. Tạo ba liên kết lọc Action, Comedy và Drama.
  3. Bổ sung trường diễn viên và mô tả cho biểu mẫu.
  4. Hiển thị thông báo thân thiện khi MongoDB tạm thời mất kết nối.
  5. Tạo ứng dụng quản lý sinh viên gồm tên, tuổi và điểm; có trang danh sách, thêm mới và cập nhật.

Tổng kết

Bạn đã dựng được bộ khung ứng dụng Node.js hoàn chỉnh: Express nhận yêu cầu, EJS tạo HTML động, middleware xử lý dữ liệu đầu vào và MongoDB lưu trữ phim. Bài tiếp theo sẽ hoàn thiện các thao tác cập nhật, xóa, đặt ghế và những trang còn lại của Wonderland Widescreen.

Bài viết liên quan:

Hoàn thiện ứng dụng quản lý phim, xác thực và triển khai Render
Xây dựng website với Express, EJS và MongoDB
Kết nối MongoDB và xây dựng CRUD API
Xây dựng RESTful API với Express và HTTP trong nodejs
Đồng bộ, bất đồng bộ, Promise, async/await và Event Loop
Express.js, Routing, GET/POST và Middleware
Query String, gửi Email, Upload File và Local Modules trong Node.js
Built-in Modules trong Node.js: HTTP Server, URL và EventEmitter
Modules và Packages trong Node.js: CommonJS, ES Modules, npm và File System
Node.js Essentials: kiến trúc, Event Loop, REPL, npm và Global Objects
Node.js là gì? Kiến trúc client-server và cách cài đặt Node.js
Tìm Hiểu Express.js và Lập Trình Đồng Bộ – Bất Đồng Bộ Trong Node.js

THÊM BÌNH LUẬN Cancel reply

Dịch vụ thiết kế Wesbite

NỘI DUNG MỚI CẬP NHẬT

Hoàn thiện ứng dụng quản lý phim, xác thực và triển khai Render

Xây dựng ứng dụng quản lý phim với Express, EJS và MongoDB

Xây dựng website với Express, EJS và MongoDB

Đồng bộ, bất đồng bộ, Promise, async/await và Event Loop

Express.js, Routing, GET/POST và Middleware

Giới thiệu

hocvietcode.com là website chia sẻ và cập nhật tin tức công nghệ, chia sẻ kiến thức, kỹ năng. Chúng tôi rất cảm ơn và mong muốn nhận được nhiều phản hồi để có thể phục vụ quý bạn đọc tốt hơn !

Liên hệ quảng cáo: [email protected]

Kết nối với HỌC VIẾT CODE

© hocvietcode.com - Tech888 Co .Ltd since 2019

Đăng nhập

Trở thành một phần của cộng đồng của chúng tôi!
Registration complete. Please check your email.
Đăng nhập bằng google
Đăng kýBạn quên mật khẩu?

Create an account

Welcome! Register for an account
The user name or email address is not correct.
Registration confirmation will be emailed to you.
Log in Lost your password?

Reset password

Recover your password
Password reset email has been sent.
The email could not be sent. Possible reason: your host may have disabled the mail function.
A password will be e-mailed to you.
Log in Register
×