热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用Node.js的RESTfulAPI设计

它是Node.js工具的杰出代表。如果您是初学者,有抱负的编码人员或IT专业学生,可能很难为之着迷,但是当您最终习惯它时,它

它是Node.js工具的杰出代表。 如果您是初学者,有抱负的编码人员或IT专业学生,可能很难为之着迷,但是当您最终习惯它时,它会令人大开眼界。 本教程将带您逐步了解API设计的基础知识,并教您如何设置REST API的主干以及如何以逻辑方式构造代码。

随着教程的进行,如果您愿意跟随我并与我一起编码,我将非常高兴。 每个代码段后面都会有一个解释,正确理解它的最好方法是自己编写代码。

在开始之前,您需要了解一些有关Node.js和我将在教程本身中使用的EcmaScript标准的知识。 我不会使用ES6,因为我认为它不像传统 Javascript那样对初学者友好。 但是,我希望您已经了解Node.js的基础知识,包括如何设置基本的Node服务器,该服务器将根据用户正在访问的路由返回一些信息。 如果没有,请绕行并在继续之前检查一下。

“你好,世界!” Node.js和Express的应用程序
您是否使用Node…? 你会。 medium.com

其次,我将使用CommonJS的基本实现。 不用担心,下面将对此进行说明。 随时检查出来这里 ,并在这里进行进一步的参考。 不过,不要忘了回到本教程。 :)
最后,如果您希望完整地查看它,则整个演示都在GitHub上。 它链接在文章的底部。

准备好一些代码了吗?

不,只是开玩笑。 我们需要设置并安装所需的依赖项和节点模块,以使应用程序正常运行。 在创建API时,很明显需要数据库。 我们将使用MongoDB (一个NOSQL数据库) 。 这是满足我们需求的最佳选择,因为我们不需要关系数据库。 为了简单起见,我们只需要在mLab上连接沙箱数据库,而不是在本地安装和运行它。

但是,请记住,mLab就像一个玩具,我建议使用MongoDB Atlas在生产环境中托管数据库。 这是官方的MongoDB云托管服务。

继续,创建一个帐户,并创建一个新的MongoDB部署。

在您帐户的主页上,创建一个新的MongoDB部署

选择免费的沙箱数据库,并为其选择一个名称。

(选择单节点和沙箱)

辛苦了,只要做一件事,您的数据库就可以采取行动了。 单击新创建的数据库,然后按照黄色文字编写的说明进行操作。 按用户标签并添加新用户。

(将新用户添加到您的数据库中)

而已。 现在可以使用数据库了。 您将使用数据库名称下方所述的MongoDB URI与其连接。

总结一下,您已经准备好开始配置应用程序本身。 初始化npm并安装以下模块:

npm init
npm install express --save
npm install mongoose --save
npm install body-parser --save

我们将为此应用程序使用Express ,因为它是当今绝大多数Node应用程序的事实上的标准。 猫鼬是一个ORM —对象关系映射器 。 确切地说,用于MongoDB的官方ORM。 要对其进行分解,我们使用ORM来简化应用程序与数据库之间的数据传输。 它映射我们在应用程序中拥有的数据,以维护数据库设置的一组严格规则。 body-parser模块只是我们用来解析通过HTTP请求发送的数据的中间件。

您终于可以编写一些代码了。

让我们先跳起来吧? 首先,创建一个应用程序文件并编写基本设置。 将其写在您的app.js中。

// app.js
var express = require ( 'express' );
var app = express();
module .exports = app;

该文件将仅用于配置应用程序。 关于将要实现的特定功能的所有逻辑将放入其各自的目录中。 当我们使用require()调用时,我们使用module.exports使该应用程序对象对程序的其余部分可见。

现在我们需要告诉应用程序在哪里收听。 继续创建另一个名为server.js的文件,并将其记录下来。

// server.js
var app = require ( './app' );
var port = process.env.PORT || 3000 ;
var server = app.listen(port, function ( ) {console .log( 'Express server listening on port ' + port);
});

在这里,您需要使用该应用程序并将其放入变量中。 该应用程序是您在app.js中创建的实际应用程序对象。 选择要在其上运行的应用程序的端口,然后最后通过app.listen启动服务器。 继续并打开终端窗口并测试是否可行。 转到创建这些文件的目录,然后运行节点server.js。 您应该看到在端口3000上侦听的Express服务器被记录到命令行中。

您已经在运行服务器,万岁!

两个下来,三个走。 随着服务器的启动和运行,现在您需要连接数据库。 返回您的文本编辑器并创建一个新文件,将其新颖地命名为db.js ,因为它将用于存储数据库连接。 它看起来应该像这样:

// db.js
var mongoose = require ( 'mongoose' );
mongoose.connect( 'mongodb://yourDatabaseURI' );

yourDatabaseURI更改为上述URI。 返回您的mLab帐户并复制MongoDB URI。 将其粘贴在代码中的两个引号之间。 将更改为为创建的用户输入的凭据。 完成此操作后,您现在需要告诉应用程序它具有可用的连接。 只需在app.js中添加require() ,如下所示:

// app.js
var express = require ( 'express' );
var app = express();
var db = require ( './db' ); //ADD THIS LINE
module .exports = app;

通过这样指定,我们告诉要求在app.js所在的目录中抓取一个文件并包含它。 而已。 现在,我们的应用程序知道它已经准备好数据库并等待访问。

您的程序现在应该具有三个文件。 一个用于配置应用程序的app.js ,一个用于指定与数据库的连接的db.js和一个用于在您选择的特定端口上扩展节点服务器的server.js

现在您准备开始编写程序的业务逻辑。

开始做生意。

首先创建一个名为user的新文件夹 该文件夹将以与我们与数据库有关用户的通信有关的任何方式包含所有文件。 您将从创建用户模型开始。 该模型将用作一个蓝图,显示数据库中所有用户的外观。 创建一个名为User.js的文件并编写以下代码:

// User.js
var mongoose = require ( 'mongoose' );
var UserSchema = new mongoose.Schema({ name : String ,email : String ,password : String
});
mongoose.model( 'User' , UserSchema);
module .exports = mongoose.model( 'User' );

您正在创建一个架构,该架构将为数据库中的每个用户提供特定的外观。 用户将具有名称,电子邮件和密码。 通过指定mongoose.model('User', UserSchema)您可以将架构的布局绑定到名为'User'的模型。 这就是您用来访问数据库中数据的方式,这就是为什么要将其导出以在程序的其他部分中使用的原因。

现在来了有趣的部分,为您的应用程序创建路由并将其绑定到相应的动作。

创建另一个文件,并将其命名为UserController.js。 您将使用其名称为控制器命名,这不仅是为了简单起见,还因为它将包含控制数据进出数据库的动作。

// UserController.js
var express = require ( 'express' );
var router = express.Router();
var bodyParser = require ( 'body-parser' );
router.use(bodyParser.urlencoded({ extended : true }));
router.use(bodyParser.json());
var User = require ( './User' );
module .exports = router;

上面是用户控制器的原始布局。 您将使用快速路由器创建路由的子集,这些路由可以是模块化的,并且与整个应用程序无关。 如果您需要重新构建程序,则可以轻松地进行操作,因为这种方法使您能够将从一个位置插入插入其他位置。 主体解析器模块用作中间件,以更优雅的方式处理数据。 当使用表单通过HTTP请求发送数据时,这将派上用场。

有趣的部分仅带有require('./User') 。 现在,您了解了为什么需要从User.js导出模型。 您将开始在UserController.js中真正使用它 只要像上面那样创建模型,它就会自动接收与数据库交互的所有必要方法,包括创建,读取,更新和删除操作。 最后,在文件底部,导出路由器,因为app.js中将需要它。

我离题了!

让我们快速介绍一下REST,以更好地了解我们为与数据库交互而采取的4种操作。 它们被称为CRUD。 站在对C reate,R EAD,U PDATE和d elete。 使用HTTP请求,我们可以使用相应的动作来触发这四个CRUD操作中的每一个。

  • POST用于将数据发送到服务器- 创建
  • GET用于从服务器获取数据— 阅读
  • PUT用于发送和更新数据— 更新
  • DELETE用于删除数据— 删除

理解这一点的最好方法是直接进入。

回到业务。

// UserController.js
var express = require ( 'express' );
var router = express.Router();
var bodyParser = require ( 'body-parser' );
router.use(bodyParser.urlencoded({ extended : true }));
router.use(bodyParser.json());
var User = require ( './User' );
// ADD THIS PART
// CREATES A NEW USER
router.post( '/' , function ( req, res ) {User.create({name : req.body.name,email : req.body.email,password : req.body.password}, function ( err, user ) {if (err) return res.status( 500 ).send( "There was a problem adding the information to the database." );res.status( 200 ).send(user);});
});
// RETURNS ALL THE USERS IN THE DATABASE
router.get( '/' , function ( req, res ) {User.find({}, function ( err, users ) {if (err) return res.status( 500 ).send( "There was a problem finding the users." );res.status( 200 ).send(users);});
});
module .exports = router;

查看第一种方法,您将看到路由器对象具有一个带两个参数的.post方法。 第一个是将链接到功能的路线。 此功能是第二个参数。 它采用另外两个参数,分别代表对服务器的请求和来自服务器的响应 。 在函数内部,将使用上面需要的用户模型。 用户模型具有一个create方法,该方法也带有两个参数。 第一个是对象,第二个是函数。 该对象包含要插入数据库的值。 您会看到,它们的结构类似于您在上面创建的架构。 创建回调函数后,将使用另外两个参数( 错误值和成功值)来调用回调函数。 您将检查在创建新用户的过程中是否出错,并相应地进行响应,或者如果一切正常,请使用新创建的用户的数据进行响应。

第二种方法更简单。 路由器对象还有一个.get方法,该方法也有两个参数。 现在,在函数中,您find()在用户模型上调用find()方法,该方法也有两个参数。 查找是一种从数据库返回值的方法。 它的第一个参数是一个对象,它定义了返回值必须满足的要求。 在此示例中,该对象为空,将返回数据库中的所有用户。

现在,您需要让该应用知道它具有用户控制器。 将此添加到您的app.js。

// app.js
var express = require ( 'express' );
var app = express();
var db = require ( './db' );
// ADD THESE TWO LINES
var UserController = require ( './user/UserController' );
app.use( '/users' , UserController);
module .exports = app;

那么,这里发生了什么魔术? 我们真的什么也不会。 您需要用户控制器,并需要app.use告诉应用程序将其链接到路由/users 。 现在,用户控制器中的/路由将映射到/users 。 这太酷了,对!!

兄弟,你还要测试吗?

ew,那是少数。 让我们休息一下,测试我们的应用程序。 对于测试API,我始终使用Postman 。 这是一个非常棒的工具,可以测试所有4种HTTP操作的URL。 它还增加了在HTTP请求的正文中发送数据的可能性。 正是您需要测试您的应用程序。 下载,安装并启动Postman,然后继续。

Postman是一个非常基本的工具,您可以输入要向其发送HTTP请求的URL,选择一种方法,并在需要时输入参数。 让我们从发送POST请求到http://localhost:3000/users 。 这意味着您将需要在请求正文中输入一组参数。

切换到主体选项卡,然后输入键-与您先前创建的用户模型匹配的值对。 您需要一个名称,一封电子邮件和一个密码。 点击发送。 瞧! 一个回应。 如果一切正常,响应将包含与最近创建的用户匹配的数据。

现在,继续并将HTTP方法更改为GET,然后再次单击send。 您将看到所有创建的用户都从数据库中返回。 继续进行一些操作,添加更多用户,并观察GET请求的行为。

返回代码。

到目前为止,您已经设置了服务器,配置了应用程序,将其连接到数据库,并创建了两个用于与数据库通信的API。 还有三个要实现的API。 从数据库中检索单个用户,更新用户,最后删除用户。 所有这些都有一个共同点。 它们都有一个查询参数,通常称为路由参数。 别害怕 这只是一个将随请求传递的值。 让我们跳进去。

// UserController.js
//...
// GETS A SINGLE USER FROM THE DATABASE
router.get( '/:id' , function ( req, res ) {User.findById(req.params.id, function ( err, user ) {if (err) return res.status( 500 ).send( "There was a problem finding the user." );if (!user) return res.status( 404 ).send( "No user found." );res.status( 200 ).send(user);});
});
//...

现在,您已经添加了另一个GET请求,但请查看路由,router.get方法的第一个参数。 现在,它的值由冒号和一些文本组成。 这种表示法表示它是查询参数(一个简单的值)的占位符,它将与请求一起发送。 传递给'/:id'的值将可以通过req.params对象访问。 查询参数的名称将映射到req.params对象上具有相同名称的属性。

继续,Mongoose有一个很棒的方法,称为.findById,它将只需要返回用户的ID。 ID是第一个参数,而回调函数是第二个。 您能看到一种新模式吗? 所有Mongoose方法都希望将值作为第一个参数,并将回调函数作为最后一个参数。 数据库返回查询值后,将调用此回调。 在DELETE请求中也可以看到相同的模式。

// UserController.js
//...
// DELETES A USER FROM THE DATABASE
router.delete( '/:id' , function ( req, res ) {User.findByIdAndRemove(req.params.id, function ( err, user ) {if (err) return res.status( 500 ).send( "There was a problem deleting the user." );res.status( 200 ).send( "User " + user.name + " was deleted." );});
});
//...

router.delete方法看起来与上面的router.get完全相同。 甚至Mongoose方法看起来都一样,只是名称不同。 通过将要删除的用户的ID指定给该方法,您将从数据库中删除该用户。 .findByIdAndRemove方法将与findById一样查找用户,但也会从数据库中删除该用户。

应用程序的最后一步将是实现一种更新数据库中现有用户的方法。 这是通过PUT请求完成的。

// UserController.js
//...
// UPDATES A SINGLE USER IN THE DATABASE
router.put( '/:id' , function ( req, res ) {User.findByIdAndUpdate(req.params.id, req.body, { new : true }, function ( err, user ) {if (err) return res.status( 500 ).send( "There was a problem updating the user." );res.status( 200 ).send(user);});
});
//...

router.put请求与您上面编写的两个请求非常相似。 它还采用一个查询参数,即ID。 与众不同的是,它也接受主体参数,就像您首先编写的POST请求一样。 仅有正文的HTTP方法是POST和PUT。 请记住。

猜猜.findByIdAndUpdate做什么? 你是对的。 此方法与您上面编写的方法有些不同。 它具有三个主要参数:一个ID,一个与要更新其值的用户相对应的对象,以及一个回调函数。 您将传递请求主体作为第二个参数,即对象,因为它已经被我们所需的中间件正确解析了,并在UserController.js的顶部使用了该中间件。 更新某些值的一个好习惯是要求将更新后的值发送回给您。 这很重要,因为您想访问新更新的值。 因此,您添加了另一个第四个参数{new:true},它代表要返回的值的版本(对于您的用户而言)。 更新前的一个或更新后的一个。 返回此值将向您显示您更新的用户。

准备进行更多测试了吗?

编程通常是混乱与宁静之间的平衡。 解决问题的混乱似乎是不合逻辑的,与最终解决问题时的平静相比,这显得不合逻辑。 测试是您获得宁静的方式。 我遇到过一个扎根于我见过的所有编码人员的心态的说法。

编写可在第一次尝试,第一次编译或第一次运行时工作的代码,称为编程大奖。
—每个程序员

当它真正发生时(如果有的话),您会感到好像太阳已选择向您特别发光。 不习惯这个。 建立这种永远不会发生的理解。 您需要单击内容,按下按钮,并深入研究开发人员工具,才能使混乱和平静化。

准备? 让我们按一些按钮。

再次启动命令提示符,并使用节点server.js启动服务器。 打开Postman并继续尝试刚创建的新方法。 对单个用户的普通GET请求看起来像这样:

实际上,在URL中添加用户的ID作为查询参数实际上只会返回具有该特定ID的用户。

继续执行PUT请求,将方法更改为PUT,向主体添加值(确保属性与上面创建的用户架构的属性匹配),然后单击send。

您已将“管理员”的名称更改为“ imNotTheAdminAnymore”。

如果您理解这一点,那么DELETE方法将是小菜一碟。 将方法更改为DELETE,然后再次单击发送。 现在,您将从数据库中删除具有给定ID的用户。

我知道很快将您的头缠在一切上都是困难的。 这就是为什么我将所有代码推送到GitHub的原因。 如果您遇到任何困难,请随时在此处查看整个项目。 或者,如果您想阅读我的最新文章,请转到这里。

AdnanRahić撰写的最新故事-中
阅读AdnanRahić在Medium上撰写的最新故事。 软件工程师@bookvar_co。 编码教育者@ ACADEMY387… medium.com

所以你以为是吗?

您只刮了一个巨大的冰山一角。 但是,现在就足够了。 保持好奇心,提出问题,并持续按下按钮。 我已经为您提供了许多在成星之旅中需要了解的核心技能的基础知识。

不要让Node吓到你。 这只是普通的Javascript。 以与在浏览器中编写代码相同的方式查看它。 要分解它,它只是一堆事件侦听器和处理程序。 例如:

router.get( '/:id' , function ( req, res ) {User.findById(req.params.id, function ( err, user ) {if (err) return res.status( 500 ).send( "There was a problem finding the user." );if (!user) return res.status( 404 ).send( "No user found." );res.status( 200 ).send(user);});
});

服务器正在侦听HTTP请求,以使用GET方法访问路由'/:id' 。 发生此类请求时,将调用回调函数。 此函数内部的所有内容都将被评估并执行。 是不是很熟悉?

button.addEventListener( 'click' , function ( e ) {console .log( "Well it's very familiar for me." );
});

希望你们和我喜欢写这本书一样喜欢阅读。 很好奇,它肯定对我有很大帮助。

您认为本教程对某人有帮助吗? 不要犹豫,分享。 如果您喜欢它,请单击 下面 拍手 ,以便其他人可以在“中”此处看到。

多亏了我父亲,我成为我的灵感来源,并一直保持着好奇心。

From: https://hackernoon.com/restful-api-design-with-node-js-26ccf66eab09



推荐阅读
author-avatar
茶不离
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有