当前位置: 首页 > news >正文

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

让我们在 JavaScript 中创建一个 CRUD rest API,使用:

  • 节点.js

  • 表达

  • 续集

  • Postgres

  • 码头工人

  • 码头工人组成


介绍

这是我们将要创建的应用程序架构的架构:

我们将为基本的 CRUD 操作创建 5 个端点:

  • 创造

  • 阅读全部

  • 读一个

  • 更新

  • 删除

我们将使用以下方法创建一个 Node.js 应用程序:

  • 表达为框架

  • 序列化为 ORM

  1. 我们将 Dockerize Node.js 应用程序

  1. 我们将有一个 Postgres 实例,我们将使用 Tableplus 对其进行测试

  1. 我们将创建一个 docker compose 文件来运行这两个服务

  1. 我们将使用 Postman 测试 API


分步指南

这是一个分步指南。

新建一个文件夹

mkdir node-crud-api

步入其中

cd node-crud-api

初始化一个新的 npm 项目

npm init -y

安装依赖项

npm i express pg sequelize
  • express 是 Node.js 框架

  • pg 是与 Postgres 数据库连接的驱动程序

  • sequelize 是 ORM,所以我们避免输入 SQL 查询

创建4个文件夹

mkdir controllers routes util models

使用您喜欢的 IDE 打开文件夹。如果你有 Visual Studio Code,你可以从终端输入:

code .

你现在应该有一个类似于这个的文件夹:

现在让我们开始编码。

数据库连接

在“util”文件夹中创建一个名为“database.js”的文件。

此文件将包含内部配置以允许 Node.js 应用程序和正在运行的 Postgres 实例之间的连接。

填充 util/database.js 文件

constSequelize=require('sequelize');constsequelize=newSequelize(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、名称和电子邮件的用户。

填充 models/user.js 文件:

constSequelize=require('sequelize');constdb=require('../util/database');constUser=db.define('user',{id:{type:Sequelize.INTEGER,autoIncrement:true,allowNull:false,primaryKey:true},name:Sequelize.STRING,email:Sequelize.STRING});module.exports=User;

控制器

该文件包含所有要执行的函数,以便与数据库交互并具有 4 个基本功能:

在“controllers”文件夹中创建一个名为“users.js”的文件

填充 controllers/users.js 文件

constUser=require('../models/user');// CRUD Controllers//get all usersexports.getUsers=(req,res,next)=>{User.findAll().then(users=>{res.status(200).json({users:users});}).catch(err=>console.log(err));}//get user by idexports.getUser=(req,res,next)=>{constuserId=req.params.userId;User.findByPk(userId).then(user=>{if(!user){returnres.status(404).json({message:'User not found!'});}res.status(200).json({user:user});}).catch(err=>console.log(err));}//create userexports.createUser=(req,res,next)=>{constname=req.body.name;constemail=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 userexports.updateUser=(req,res,next)=>{constuserId=req.params.userId;constupdatedName=req.body.name;constupdatedEmail=req.body.email;User.findByPk(userId).then(user=>{if(!user){returnres.status(404).json({message:'User not found!'});}user.name=updatedName;user.email=updatedEmail;returnuser.save();}).then(result=>{res.status(200).json({message:'User updated!',user:result});}).catch(err=>console.log(err));}//delete userexports.deleteUser=(req,res,next)=>{constuserId=req.params.userId;User.findByPk(userId).then(user=>{if(!user){returnres.status(404).json({message:'User not found!'});}returnUser.destroy({where:{id:userId}});}).then(result=>{res.status(200).json({message:'User deleted!'});}).catch(err=>console.log(err));}

航线

在“routes”文件夹中创建一个名为“users.js”的文件。

填充 routes/users.js 文件

constcontroller=require('../controllers/users');constrouter=require('express').Router();// CRUD Routes /usersrouter.get('/',controller.getUsers);// /usersrouter.get('/:userId',controller.getUser);// /users/:userIdrouter.post('/',controller.createUser);// /usersrouter.put('/:userId',controller.updateUser);// /users/:userIdrouter.delete('/:userId',controller.deleteUser);// /users/:userIdmodule.exports=router;

索引文件

要运行我们的应用程序,我们需要在根级别创建更多文件。这是将由 docker 容器执行的文件。

在根文件夹中,创建一个名为 index.js 的文件

填充“index.js 文件”:

constexpress=require('express');constbodyparser=require('body-parser');constsequelize=require('./util/database');constUser=require('./models/user');constapp=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 routeapp.get('/',(req,res,next)=>{res.send('Hello World');});//CRUD routesapp.use('/users',require('./routes/users'));//error handlingapp.use((error,req,res,next)=>{console.log(error);conststatus=error.statusCode||500;constmessage=error.message;res.status(status).json({message:message});});//sync databasesequelize.sync().then(result=>{console.log("Database connected");app.listen(3000);}).catch(err=>console.log(err));

码头部分

让我们在根级别再创建 3 个文件:

  • .dockerignore(以点开头)

  • Dockerfile(大写字母 D)

  • docker-compose.yml

结构应如下所示:

.dockerignore 将包含一行:

node_modules

Dockerfile

要创建 Docker 镜像,我们需要一个简单但功能强大的文件。这就是所谓的“Dockerfile”(大写字母 D)。我们可能会使用不同的名称,但让我们暂时保持简单。

FROM node:14# Create app directoryWORKDIR /appCOPY package*.json ./RUN npm install# Bundle app sourceCOPY . .EXPOSE 3000CMD [ "node", "index.js" ]

Docker 组合文件

要运行多个服务,一种简单的方法是创建一个名为“docker-compose.yml”的文件

docker-compose.yml 文件:

version:"3.9"services:node_app:container_name:node_appbuild:.image:francescoxx/node_live_appports:-"3000:3000"environment:-PG_DB=node_live_db-PG_USER=francesco-PG_PASSWORD=12345-PG_HOST=node_dbdepends_on:-node_dbnode_db:container_name:node_dbimage:postgres:12ports:-"5432:5432"environment:-POSTGRES_DB=node_live_db-POSTGRES_USER=francesco-POSTGRES_PASSWORD=12345volumes:-node_db_data:/var/lib/postgresql/datavolumes:node_db_data:{}

构建 Docker 镜像并运行 docker 容器

在容器中运行 Postgres

首先,让我们运行 postgres 容器:

docker compose up -d node_db

要检查日志,我们可以键入:

docker compose logs

你应该得到类似于这个的输出:

如果我们看到“数据库系统已准备好接受连接”,我们就可以开始了!

让我们使用 TablePlus 对其进行测试。

单击 + 创建新连接

从 docker-compose.yml 文件复制值。(如果您保留原值,密码为 12345)

构建并运行 Docker 服务

其次,让我们构建我们的 Docker iamge:

docker compose build

最后,让我们启动服务:

docker compose up node_app

这应该是终端上的输出

使用 Postman 测试应用

让我们使用 Postman 测试应用程序。

向 localhost:3000 发出 GET 请求

向 localhost:3000/users 发出 GET 请求

我们应该有一个空数组作为响应

让我们创建 3 个用户:aaa、bbb 和 ccc

让我们再次检查所有用户:

向 localhost:3000/users 发出 GET 请求

我们应该看到 3 个用户:

让我们得到一个用户,例如用户 2

向 localhost:3000/users/2 发出 GET 请求

让我们更新现有用户,例如同一用户 2

使用不同的主体向 localhost:3000/users/2 发出 PUT 请求

最后,让我们删除用户号 3

对 localhost:3000/users/3 进行删除请求

我们还可以使用 TablePlus 检查值

结论

这是一个基本示例,说明如何使用 Node.js、Express、Sequelize、Postres、Docker 和 Docker Compose 构建 CRUD rest API。

相关文章:

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

让我们在 JavaScript 中创建一个 CRUD rest API,使用:节点.js表达续集Postgres码头工人码头工人组成介绍这是我们将要创建的应用程序架构的架构:我们将为基本的 CRUD 操作创建 5 个端点:创造阅读全部读一个更新删除我们将使用以下…...

电子招标采购系统源码之什么是电子招投标系统?

随着互联网时代的到来,各行业都受到不同的影响,其中招投标行业也不例外。为了顺应互联网潮流的发展,电子招投标逐渐取代传统的纸质的招投标方式,给招标方、投标方、招标代理等各方也带来了前所未有的机遇与挑战。那么什么是电子招…...

匹配文件名称模块glob和fnmatch

匹配文件名称模块glob 1.概述 glob模式规则与re模块的正则表达式规则不大相同,glob模块遵循标准的UNIX路径扩展规则。 fnmatch模块用于根据glob模式比较文件名 2.glob表达式匹配文件名 2.1.测试文件 介绍glob配置规则前,先使用下面的代码创建测试文…...

day12_oop

今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、作业 二、继承 三、重写 四、this和super 五、访问修饰符 零、 复习昨日 局部变量和成员变量什么区别 位置,作用域,初始值,内存位置,生命周期 构造方法…...

在 Flutter 中使用 webview_flutter 4.0 | js 交互

大家好,我是 17。 已经有很多关于 Flutter WebView 的文章了,为什么还要写一篇。两个原因: Flutter WebView 是 Flutter 开发的必备技能现有的文章都是关于老版本的,新版本 4.x 有了重要变化,基于 3.x 的代码很多要重…...

嵌入式ARM工业边缘计算机BL302的CAN总线接口如何设置?

CAN 接口如图所示,输入如下命令: ifconfig -a //查看所有网卡 如果 FlexCAN 驱动工作正常的话就会看到 CAN 对应的网卡接口,如图。从图中可 以看出,有一个名为“can0”的网卡,这个就是 BL302 板上的 CAN1 接口对应的 c…...

Win11系统如何安装Ubuntu20.04(WSL版本)并安装docker

终于还是下定决心去换电脑了……这次采用轻量级的WSL,发现虽然没有占内存的GUI界面,但是编码和阅读文档还是非常nice的 1、首先开启Win11的虚拟机服务 2、下载你期望的Ubuntu服务器(这里以20.04为例) 安装成功后,发现…...

Elasticsearch和Solr的区别

背景:它们都是基于Lucene搜索服务器基础之上开发,一款优秀的,高性能的企业级搜索服务器。(是因为他们都是基于分词技术构建的倒排索引的方式进行查询)开发语言:java语言开发诞生时间:Solr2004年…...

如何在北京买房

首先我陈述一点,如果为了买房后再卖掉赚取差价,我这篇文章也许不适合,我这篇文章为整体愿景的发展而设计,为可操作房产的买卖而操作。 买房的愿景: 首先,我们要以一种心态来买房。那就是以始为终的态度&am…...

使用Proxifier+burp抓包总结

一、微信小程序&网页抓包 1. Proxifier简介 Proxifier是一款功能非常强大的socks5客户端,可以让不支持通过代理服务器工作的网络程序能通过HTTPS或SOCKS代理或代理链。 2. 使用Proxifier代理抓包 原理:让微信相关流量先走127.0.0.1:80到burp。具体…...

安装华为aab包的处理方式

1、转换 aab包 为 apks 说明: 1、bundletool-all-1.11.2.jar 转换文件的工具 2、a.aab aab源文件 3、xxx.apks 导入的文件以及路径(例如:D:\Android\xxx.apks) 4、–ksxxxx.jks 该aab打包所需的jsk文件 5、三条命令为 jsk打包所…...

Word处理控件Aspose.Words功能演示:使用 C++ 将 RTF 文档转换为 PDF

Aspose.Words 是一种高级Word文档处理API,用于执行各种文档管理和操作任务。API支持生成,修改,转换,呈现和打印文档,而无需在跨平台应用程序中直接使用Microsoft Word。此外,API支持所有流行的Word处理文件…...

【Java|多线程与高并发】进程与线程的区别与联系

文章目录什么是进程什么是线程上下文切换多线程一定比串行执行快吗进程与线程的区别与联系什么是进程 进程的定义:进程是正在运行的程序实体,并且包括这个运行的程序中占据的所有系统资源,比如说CPU(寄存器),IO,内存&a…...

K8s手工创建kubeconfig

我们通过 kubectl 命令行连接 k8s apiserver 时需要依赖 kubeconfig 文件。 kubeconfig 文件通常包含了 context(上下文)列表,每个 context 又会引用 cluster 和 user,最后通过 current-context 指定当前 kubeconfig 使用哪个 con…...

【SQL开发实战技巧】系列(十七):时间类型操作(下):确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数

系列文章目录 【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事 【SQL开发实战技巧】系列(二):简单单表查询 【SQL开发实战技巧】系列(三):SQL排序的那些事 【SQL开发实战技巧…...

代码随想录算法训练营第二十八天 | 491.递增子序列,46.全排列,47.全排列 II

一、参考资料递增子序列题目链接/文章讲解:https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html 视频讲解:https://www.bilibili.com/video/BV1EG4y1h78v 全排列题目链接/文章讲解:https://programmercarl.…...

使用 Three.js 后处理的粗略铅笔画效果

本文使用Three.js的后处理创建粗略的铅笔画效果。我们将完成创建自定义后处理渲染通道、在 WebGL中实现边缘检测、将法线缓冲区重新渲染到渲染目标以及使用生成和导入的纹理调整最终结果的步骤。翻译自Codrops,有改动。 Three.js 中的后处理 Three.js中的后处理是一…...

推荐一些不常见的搜索引擎

5.雅虎网来自 Yahoo.com 的屏幕截图,2023 年 2 月截至 2022 年 1 月,Yahoo.com(Verizon Media)的搜索市场份额为 11.2%。雅虎的优势在于多元化,除搜索外还提供电子邮件、新闻、金融等服务。二十多年来,雅虎…...

RabbitMQ工作模式

目录1.Work queues工作队列模式1.1 模式说明1.2 代码1.3 测试1.4 小结2.订阅模式类型3.Publish/Subscribe发布与订阅模式3.1 模式说明3.2 代码3.3 测试3.4 小结4.Routing路由模式4.1 模式说明4.2 代码4.3 测试4.4 小结5.Topics通配符模式5.1 模式说明5.2 代码5.3 测试5.4 小结6…...

机器学习在预测脊髓型颈椎病中的应用:一项28名参与者的事后初步研究

机器学习在预测脊髓型颈椎病中的应用:一项28名参与者的事后初步研究 Machine Learning for the Prediction of Cervical Spondylotic Myelopathy: A Post Hoc Pilot Study of 28 Participants 简单说:训练了两个模型:1)预测脊髓型颈椎病诊断&#xff0…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...