node.js基础学习-mongoose+MongoDB的MVC(Model-View-Controller)(十三)

发布于:2024-12-06 ⋅ 阅读:(26) ⋅ 点赞:(0)

一、前言

MVC(Model-View-Controller)是一种软件设计模式,用于将应用程序的逻辑、数据和界面进行分离,使得各个部分职责明确、便于开发、维护以及扩展。

以下是一个在 Node.js 中使用 Mongoose、MVC 架构并额外添加了services层来实现对书籍资源进行增、删、改、查操作的示例,同样以返回 JSON 数据的方式来处理请求与响应,基于 Express 框架搭建:

二、项目结构

book-app/
├── models
│   └── book.js
├── services
│   └── bookService.js
├── controllers
│   └── bookController.js
└── app.js

1. 模型(Model)定义(models/book.js

const mongoose = require('mongoose');

const bookSchema = new mongoose.Schema({
    title: {
        type: String,
        required: true
    },
    author: {
        type: String,
        required: true
    },
    publicationYear: {
        type: Number
    }
});

const Book = mongoose.model('Book', bookSchema);

module.exports = Book;

2. 服务(Service)层定义(services/bookService.js

服务层主要用于封装对数据库的具体操作逻辑,使得业务逻辑更加清晰,便于复用和维护。

const Book = require('../models/book');

// 获取所有书籍的服务函数
const getAllBooks = async () => {
    try {
        return await Book.find();
    } catch (error) {
        throw new Error('Internal Server Error');
    }
};

// 创建新书的服务函数
const createBook = async (bookData) => {
    try {
        const newBook = new Book(bookData);
        return await newBook.save();
    } catch (error) {
        throw new Error('Bad Request');
    }
};

// 更新书籍的服务函数
const updateBook = async (bookId, updatedData) => {
    try {
        const updatedBook = await Book.findByIdAndUpdate(bookId, updatedData, {
            new: true
        });
        if (!updatedBook) {
            throw new Error('Book not found');
        }
        return updatedBook;
    } catch (error) {
        throw new Error('Internal Server Error');
    }
};

// 删除书籍的服务函数
const deleteBook = async (bookId) => {
    try {
        const deletedBook = await Book.findByIdAndDelete(bookId);
        if (!deletedBook) {
            throw new Error('Book not found');
        }
        return { message: 'Book deleted successfully' };
    } catch (error) {
        throw new Error('Internal Server Error');
    }
};

module.exports = {
    getAllBooks,
    createBook,
    updateBook,
    deleteBook
};

3. 控制器(Controller)定义(controllers/bookController.js

控制器层负责接收来自路由的请求,调用服务层的相应函数来处理业务逻辑,并将处理结果返回给客户端。

const bookService = require('../services/bookService');

// 获取所有书籍的控制器函数
const getBooks = async (req, res) => {
    try {
        const books = await bookService.getAllBooks();
        res.status(200).json(books);
    } catch (error) {
        console.error(error);
        res.status(500).json({ error: error.message });
    }
};

// 创建新书的控制器函数
const createBook = async (req, res) => {
        try {
            const newBook = await bookService.createBook(req.body);
            res.status(201).json(newBook);
        } catch (error) {
            console.error(error);
            res.status(400).json({ error: error.message });
        }
};

// 更新书籍的控制器函数
const updateBook = async (req, res) => {
    try {
        const { id } = req.params;
        const updatedBook = await bookService.updateBook(id, req.body);
        res.status(200).json(updatedBook);
    } catch (error) {
        console.error(error);
        res.status(500).json({ error: error.message });
    }
};

// 删除书籍的控制器函数
const deleteBook = async (req, res) => {
    try {
        const { id } = req.params;
        const result = await bookService.deleteBook(id);
        res.status(200).json(result);
    } catch (error) {
        console.error(error);
        res.status(500).json({ error: error.message });
    }
};

module.exports = {
    getBooks,
    createBook,
    updateBook,
    deleteBook
};

4. 应用程序入口及路由配置(app.js

const express = require('express');
const app = express();
const bookController = require('./controllers/bookController');

// 配置中间件,用于解析POST请求中的JSON数据
app.use(express.json());

// 定义路由
// 获取所有书籍的路由
app.get('/books', bookController.getBooks);
// 创建新书的路由
app.post('/books', bookController.createBook);
// 更新书籍的路由,注意这里接收书籍的id作为路由参数
app.put('/books/:id', bookController.updateBook);
// 删除书籍的路由,同样接收书籍的id作为路由参数
app.delete('/books/:id', bookController.deleteBook);

const port = 3000;
app.listen(port, () => {
    console.log(`Server started on port ${port}`);
});

5. 使用示例

  • 查询所有书籍:发送 GET 请求到 http://localhost:3000/books,服务器会返回状态码为 200 的包含所有书籍信息的 JSON 数组。
  • 创建新书:发送 POST 请求到 http://localhost:3000/books,在请求体中以 JSON 格式传递书籍的相关信息(如 { "title": "New Book", "author": "Author Name", "publicationYear": 2024 }),成功后服务器返回状态码 201 以及新创建书籍的信息(以 JSON 格式)。
  • 更新书籍:发送 PUT 请求到 http://localhost:3000/books/[book_id](其中 [book_id] 是要更新书籍的实际 MongoDB 文档 _id),同时在请求体中以 JSON 格式传递要更新的书籍信息,若更新成功,服务器返回状态码 200 及更新后的书籍信息(以 JSON 格式),若找不到对应书籍则返回状态码 404 及相应错误提示信息(以 JSON 格式)。
  • 删除书籍:发送 DELETE 请求到 http://localhost:3000/books/[book_id](其中 [book_id] 是要删除书籍的实际 MongoDB 文档 _id),若删除成功,服务器返回状态码 200 及表示成功删除的消息(以 JSON 格式),若找不到对应书籍则返回状态码 404 及相应错误提示信息(以 JSON 格式)。

三、注意

要运行这个示例,首先要确保已经安装了 Node.js、Express、Mongoose(可以通过 npm install express mongoose 命令安装),然后在项目根目录下使用 node app.js 命令启动服务器,即可按照上述使用示例进行相应的操作。

这样的分层架构使得代码结构更加清晰,不同层专注于不同的职责,便于后续的扩展和维护。例如,如果后续需要更改数据库操作逻辑或者添加更多复杂的业务逻辑,只需要在对应的服务层或者控制器层进行修改,而不会对其他层造成太大影响。


网站公告

今日签到

点亮在社区的每一天
去签到