使用 Nodejs、Express、Postgres、Docker 在 JavaScript 中构建 CRUD Rest API
让我们在 JavaScript 中创建一个 CRUD rest API,使用:
节点.js
表达
续集
Postgres
码头工人
码头工人组成
介绍
这是我们将要创建的应用程序架构的架构:
我们将为基本的 CRUD 操作创建 5 个端点:
创造
阅读全部
读一个
更新
删除
我们将使用以下方法创建一个 Node.js 应用程序:
表达为框架
序列化为 ORM
我们将 Dockerize Node.js 应用程序
我们将有一个 Postgres 实例,我们将使用 Tableplus 对其进行测试
我们将创建一个 docker compose 文件来运行这两个服务
我们将使用 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)预测脊髓型颈椎病诊断࿰…...
【智能计算数学】微积分
高数问题解决流程引例:回归回归引例:分类分类线性可分FLD线性不可分智能计算讨论范围下降法为什么要用下降法?- 解析解很难写出公式或很复杂难计算有哪些常用的下降法?- 梯度下降&高斯-牛顿法梯度下降(Gradient De…...
win10+RTX4070ti+libtorch部署
环境cuda 11.7、cudnn8.6.0、libtorch1.13.1cu117 注意: 1)libtorch官网进不去的可直接下载 Release version https://download.pytorch.org/libtorch/cu117/libtorch-win-shared-with-deps-1.13.1%2Bcu117.zip Debug version https://download.pytorch.…...
【Python百日进阶-Web开发-Vue3】Day518 - Vue+ts后台项目5:用户列表
文章目录 一、获取用户列表的数据1.1 定义用户列表和角色列表的接口src/request/api.ts1.2 获取用户列表数据src/views/UserView.vue二、定义用户列表数据类型2.1 src/type/user.ts三、展示用户列表内容3.1 element-plus中的Select 选择器3.2 element-plus中的表格插槽3.3 展示…...
Linux内核转储---kdump原理梳理
文章目录Kexec和Kdump设计的区别kexeckdumpKdump的执行流程kexec的实现用户空间kexec内核空间vmcoreKdump的实现可以分为两部分:内核和用户工具。内核提供机制,用户工具在这些机制上实现各种转储策略,内核机制对用户工具的接口是一个系统调用…...
【C++】从0到1入门C++编程学习笔记 - 实战篇:演讲比赛流程管理系统
文章目录一、演讲比赛程序需求1.1 比赛规则1.2 程序功能1.3 程序效果图:二、项目创建2.1 创建项目2.2 添加文件三、创建管理类3.1创建文件3.2 头文件实现3.3 源文件实现四、菜单功能4.1 添加成员函数4.2 菜单功能实现4.3 测试菜单功能五、退出功能5.1 提供功能接口5…...
04 OpenCV位平面分解
1 基本概念 位平面分解的核心思想是将图像的每一个像素分解为多个二进制位,分别存储在不同的位平面上。例如,如果一个图像是8位深度的,则可以分解为8个位平面,每个位平面上存储一个二进制位。 位平面分解在图像压缩中有着重要的…...
Onvif协议如何判断摄像机支持 —— 筑梦之路
有人就问什么是Onvif协议呢? 全称为:Open Network Video Interface Forum.缩写成Onvif。 翻译过来是:开放型网络视频接口论坛,目的是确保不同安防厂商的视频产品能够具有互通性,这样对整体安防行业才是良性发展。 现…...
情人节new一个对象给你
今天情人节,有没对象的吗?假设你不知道new怎么用,每个人都有两种身份,一种没对象的人,这个时候new一个对象给你,一种是有对象的人,这个delete对象。等你学完这个new和delete知识点,无…...
linux篇【15】:应用层-网络https协议
目录 一.HTTPS介绍 1.HTTPS 定义 2.HTTP与HTTPS (1)端口不同,是两套服务 (2)HTTP效率更高,HTTPS更安全 3.加密,解密,密钥 概念 4.为什么要加密? 5.常见的加密方式…...
索引-性能分析-explain
explain 执行计划 explain 执行计划各字段含义 1)id 就是代表 sql 的执行顺序或者表的执行顺序;id相同从上往下执行,id不同,id值越大越先执行;(注:有子查询时就会出现sql执行顺序)…...
做网站的学什么代码/wix网站制作
乒乓操作是一个主要用于数据流控制的处理技巧,典型的乒乓操作如下图所示。 外部输入数据流通过“输入数据选择控制”模块送入两个数据缓冲区中,数据缓冲模块可以为任何存储模块,比较常用的存储单元为双口RAM(Dual RAM)、SRAM、SDRAM、FIFO等。…...
wordpress交流群/百度网盘官网登录首页
属性选择器 1、作用:根据指定的属性名称找到对应的标签,然后设置属性 该选择器,最常用于input标签 2、格式与具体用法: [属性名] 其他选择器[属性名] [属性名值] [属性名^值] [属性名$值] [属性名*值] 例1:找到所有包含…...
更改wordpress网站的url/网页制作代码大全
2. 面向对象三大特性之封装 面向对象三大特征:封装,继承,多态封装就是将一些细节信息隐藏起来,对外界不可见 方法就是一种封装private关键字也是一种封装 2.1 private和this关键字 private关键字(私有化)…...
网站建设营销型网站/网站seo分析案例
为什么80%的码农都做不了架构师?>>> 引擎类型myisam,innodb,区别,性能,默认事务级别,多版本机制,并发扣库存怎么解决索引数据结构,为什么要这样的数据结构锁,锁的原因,怎么分析锁慢SQL日志,分析慢SQL,优化高性能设计及容量规划SQL注入分库分表建议看: 高…...
物流运输做网站的素材/百度如何免费推广
https://blog.csdn.net/coding_hello/category_5839687.html https://zhuanlan.zhihu.com/p/37518037 Dataset操作 Dataset操作都是在操作列,官方Spark API文档介绍的比较详细。 // Dataset usnchr spark.read().load(paths);JavaRDD操作 第一步就是创…...
网站结构优化包括什么/百度提问在线回答问题
下载源码: https://github.com/yanfengliu/cython_bbox.git 然后 cd cython_bbox-master python setup.py install 即可安装,注意你直接使用pip install cython_bbox是装不上的...