在本教程中,我们将使用 Nodejs、 Express、 Postgres 和 Docker 在 JavaScript 中构建 CRUD Rest API。
下面是我们将要创建的应用程序架构的模式:
5 个基本 CURD 基本操作
将使用以下技术、框架创建应用程序:
mkdir node-curd-api
cd node-curd-api
npm init -y
npm i express sequelize pg
mkdir controllers routes util models
code .
项目结构图如下:
首先在 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))
在根目录下新建 Dockerfile、.dockerignore、docker-compoese.yml 文件,用于创建 Docker 镜像。
.dockerignore 文件写入以下内容
node_modules
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**,表示数据库已经启动成功。
使用 TablePlus 连接数据库,创建数据库表,点击+按钮新建连接
从 docker-compose.yml 文件中获取数据库连接信息
打包镜像
docker compse build
运行镜像
docker compose up node_app
创建 GET 请求
请求 http://localhost:3000/users
创建三个用户 aaa、bbb、ccc
再次请求 http://localhost:3000/users,得到以下结果
请求单个用户 http://localhost:3000/users/2
修改已存在的用户 http://localhost:3000/users/2
删除已存在的用户 http://localhost:3000/users/3
操作完成后同样可以在 TablePlus 中查看数据库表
本文介绍了如何使用 Docker Compose 配置多容器服务,以及如何使用 Postman 测试 Node.js 服务。