Published 2023-02-13

使用 Nodejs、 Express、 Postgres 和 Docker 在 JavaScript 中构建 CRUD Rest API

在本教程中,我们将使用 Nodejs、 Express、 Postgres 和 Docker 在 JavaScript 中构建 CRUD Rest API。

介绍

下面是我们将要创建的应用程序架构的模式:

gBFaRK

5 个基本 CURD 基本操作

将使用以下技术、框架创建应用程序:

项目结构

mkdir node-curd-api
cd node-curd-api
npm init -y
npm i express sequelize pg
mkdir controllers routes util models
code .

项目结构图如下:

RQuES3

创建、连接数据库

首先在 util 文件夹下新建 database.js 文件,用于连接数据库。这个文件将包含允许 Node.js 应用程序和运行的 Postgres 实例之间连接的内部配置。

const Sequelize = require('sequelize')
const sequelize = new Sequelize(
  process.env.PG_DB,
  process.env.PG_USER,
  process.env.PG_PASSWORD,
  {
    host: process.env.PG_HOST,
    dialect: 'postgres'
  }
)
module.exports = sequelize

创建模型

在 models 文件夹下新建 user.js 文件,用于创建模型。这个文件将包含模型,在本例中是一个具有自动递增 id、name 和 email 的用户。

const Sequelize = require('sequelize')
const db = require('../util/database')

const User = db.define('user', {
  id: {
    type: Sequelize.INTEGER,
    autoIncrement: true,
    allowNull: false,
    primaryKey: true
  },
  name: Sequelize.STRING,
  email: Sequelize.STRING
})
module.exports = User

创建控制器

在 controllers 文件夹下新建 user.js 文件,用于创建控制器。这个文件将包含控制器,用于处理请求。

const User = require('../models/user')

// CRUD Controllers

//get all users
exports.getUsers = (req, res, next) => {
  User.findAll()
    .then((users) => {
      res.status(200).json({users: users})
    })
    .catch((err) => console.log(err))
}

//get user by id
exports.getUser = (req, res, next) => {
  const userId = req.params.userId
  User.findByPk(userId)
    .then((user) => {
      if (!user) {
        return res.status(404).json({message: 'User not found!'})
      }
      res.status(200).json({user: user})
    })
    .catch((err) => console.log(err))
}

//create user
exports.createUser = (req, res, next) => {
  const name = req.body.name
  const email = req.body.email
  User.create({
    name: name,
    email: email
  })
    .then((result) => {
      console.log('Created User')
      res.status(201).json({
        message: 'User created successfully!',
        user: result
      })
    })
    .catch((err) => {
      console.log(err)
    })
}

//update user
exports.updateUser = (req, res, next) => {
  const userId = req.params.userId
  const updatedName = req.body.name
  const updatedEmail = req.body.email
  User.findByPk(userId)
    .then((user) => {
      if (!user) {
        return res.status(404).json({message: 'User not found!'})
      }
      user.name = updatedName
      user.email = updatedEmail
      return user.save()
    })
    .then((result) => {
      res.status(200).json({message: 'User updated!', user: result})
    })
    .catch((err) => console.log(err))
}

//delete user
exports.deleteUser = (req, res, next) => {
  const userId = req.params.userId
  User.findByPk(userId)
    .then((user) => {
      if (!user) {
        return res.status(404).json({message: 'User not found!'})
      }
      return User.destroy({
        where: {
          id: userId
        }
      })
    })
    .then((result) => {
      res.status(200).json({message: 'User deleted!'})
    })
    .catch((err) => console.log(err))
}

创建路由

在 routes 文件夹下新建 user.js 文件,用于创建路由。这个文件将包含路由,用于处理请求。

const controller = require('../controllers/users')
const router = require('express').Router()

// CRUD Routes /users
router.get('/', controller.getUsers) // /users
router.get('/:userId', controller.getUser) // /users/:userId
router.post('/', controller.createUser) // /users
router.put('/:userId', controller.updateUser) // /users/:userId
router.delete('/:userId', controller.deleteUser) // /users/:userId

module.exports = router

创建应用

在根目录下新建 index.js 文件,用于创建应用。这个文件将包含应用的主要配置。

const express = require('express')
const bodyparser = require('body-parser')
const sequelize = require('./util/database')
const User = require('./models/user')

const app = express()

app.use(bodyparser.json())
app.use(bodyparser.urlencoded({extended: false}))

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*')
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
  next()
})

//test route
app.get('/', (req, res, next) => {
  res.send('Hello World')
})

//CRUD routes
app.use('/users', require('./routes/users'))

//error handling
app.use((error, req, res, next) => {
  console.log(error)
  const status = error.statusCode || 500
  const message = error.message
  res.status(status).json({message: message})
})

//sync database
sequelize
  .sync()
  .then((result) => {
    console.log('Database connected')
    app.listen(3000)
  })
  .catch((err) => console.log(err))

Docker 不分

在根目录下新建 Dockerfile、.dockerignore、docker-compoese.yml 文件,用于创建 Docker 镜像。

ntgsxk

.dockerignore 文件写入以下内容

node_modules

EzUpqv

Dockerfile 文件写入以下内容

FROM node:14

# Create app directory
WORKDIR /app

COPY package*.json ./

RUN npm install

# Bundle app source
COPY . .

EXPOSE 3000

CMD [ "node", "index.js" ]

docker-compose.yaml,用于启动多容器服务

version: '3.9'

services:
  node_app:
    container_name: node_app
    build: .
    image: francescoxx/node_live_app
    ports:
      - '3000:3000'
    environment:
      - PG_DB=node_live_db
      - PG_USER=francesco
      - PG_PASSWORD=12345
      - PG_HOST=node_db
    depends_on:
      - node_db

  node_db:
    container_name: node_db
    image: postgres:12
    ports:
      - '5432:5432'
    environment:
      - POSTGRES_DB=node_live_db
      - POSTGRES_USER=francesco
      - POSTGRES_PASSWORD=12345
    volumes:
      - node_db_data:/var/lib/postgresql/data

volumes:
  node_db_data: {}

打包镜像、运行服务

在根目录下打开终端,运行以下命令

docker-compose up --build node_db

查询日志:

docker-compose logs -f node_db

得到以下内容,如输出**database system is ready to accept connections**,表示数据库已经启动成功。

wlzr48

使用 TablePlus 连接数据库,创建数据库表,点击+按钮新建连接

zxe2HJ

从 docker-compose.yml 文件中获取数据库连接信息

3rUiJH

打包镜像

docker compse build

SqOJnk

运行镜像

docker compose up node_app

rlgrrW

使用 Postman 测试

创建 GET 请求

vgNVHB

请求 http://localhost:3000/users

vy6QR0

创建三个用户 aaa、bbb、ccc

xhGZ8W

hIXblX

7mfRmn

再次请求 http://localhost:3000/users,得到以下结果

IWZroo

请求单个用户 http://localhost:3000/users/2

TuscvA

修改已存在的用户 http://localhost:3000/users/2

dmVeir

删除已存在的用户 http://localhost:3000/users/3

50TtFw

操作完成后同样可以在 TablePlus 中查看数据库表

KWjZdE

总结

本文介绍了如何使用 Docker Compose 配置多容器服务,以及如何使用 Postman 测试 Node.js 服务。

源码地址:https://github.com/FrancescoXX/crud-node-live