📜  Node.js 中的 REST API 是什么?

📅  最后修改于: 2022-05-13 01:56:17.109000             🧑  作者: Mango

Node.js 中的 REST API 是什么?

REST API 是一种应用程序编程接口,它遵循 REST 架构风格的约束并支持与 RESTful Web 服务的交互。相互连接的网络构成了网络。 Web 服务是一组用于在客户端-服务器应用程序之间交换数据的开放协议和标准。遵循 REST 架构的 Web 服务称为 RESTful Web 服务。

什么是 API?

API(应用程序编程接口)是一组命令、函数或协议,它们充当使两个应用程序能够通信的中介。当您从 Zomato 等外卖应用程序订购食物时,跟踪外卖员的位置是很常见的。 Google Map API 使您可以做到这一点。让我们通过餐厅的类比来理解 API。每当您访问餐厅时,服务员都会帮助您下订单。点完菜后,服务员让厨师做你喜欢的菜。饭做好了,服务员就给你端上来。在这种情况下,服务员充当厨师和顾客之间的中介。服务员从顾客(客户端)接收请求(订单),将请求传达给厨师(服务器),并获取准备好的菜肴(响应)。

REST: REST代表RE呈现性状态传输。 Rest 是一种使用 HTTP 协议创建网站的架构风格。开发人员在构建网站或 API 时应遵循某些架构约束。

让我们了解代表性状态转移的含义。

假设我们有一个 Web 客户端和一个 Web 服务器 (API)。客户端请求资源,服务器从其数据库中获取响应。资源是指专属于服务器的东西。当客户端通过 RESTful API 请求资源时,服务器会发送该资源的 Representation。因此,表示是服务器作为响应发送的内容。资源在特定时刻的状态就是它的状态。传输是从服务器到客户端的数据传输。因此,Representational State transfer是指资源的Representation状态的转移。这些表示通过 HTTP 以各种格式传输,包括 JSON(Javascript 对象表示法)、HTML、XML 或纯文本。最流行的文件格式是 JSON,因为它可以被人和机器读取。

例如,JSON 格式的员工数据

[    
   "employee":  
  {    
       "id": 1
       "name":   "Riya",    
       "salary": 50000,    
  }    
]    

Http 协议和动词:我们已经讨论过 REST 在 HTTP 协议上工作,所以让我们探讨一下为什么我们需要一个。 REST 始终与资源(名词)有关,而 SOAP 则与行动有关。现在,需要与基于名词的资源对应的动作来理解我们需要对该产品做什么。超文本传输协议定义了几种方法(称为动词)来确定要对资源执行的操作。可以通过 URI(统一资源标识符)或 URL 访问资源。 HTTP 动词(或方法)包括 POST、GET、PUT、PATCH 和 DELETE。 GET 方法从系统中检索信息。 POST 方法用于创建新资源。 PUT 方法用于使用全新的条目更新数据库、替换以前的条目或创建新资源。 Patch 方法用于部分更新现有资源。通过查看以下示例,您可以更好地理解 PUT 和 PATCH 方法的作用,亚马逊向您运送了一辆坏了的自行车。此问题可以通过更换整个循环 (PUT) 或仅更换损坏的部分 (PATCH) 来解决。 delete 方法用于删除现有资源。

为什么是 REST?

  • 客户端和服务器分离:客户端和服务器的分离使得协议很容易独立用于各种开发项目。它允许我们构建松散耦合的应用程序,客户端和服务器可以分开演进。
    eg:客户端和服务器可能不关心他们使用什么软件。
  • REST 独立于平台和语言。它还可以适应各种语法和工作平台,让您可以从事各种与开发相关的项目。 eg:我们可以使用windows或者mac os
  • 灵活性和可扩展性:REST 是真正可扩展的。这是由于客户端和服务器的分离。这意味着服务器不必将客户端请求保留在其主体中,也不必与客户端通信。
  • 不受一种数据格式的限制。通过序列化 JSON 和 XML 格式的信息来提供灵活的方法。
  • HTTP 缓存可用于优化网络并提高效率。
  • 易于使用和学习。

让我们制作自己的 RESTful API 以更好地理解。  

方法:我们将创建一个名为gfg-employees的 RESTFUL API。我们将插入员工数据并发送 HTTP 请求。在这个过程中,我们将获取、修改和删除员工数据。Robo3T 将用于数据库。 Postman 将用于发送请求。下面是分步实现。

第一步:新建目录,进入终端,运行以下命令初始化NPM。

npm init -y

初始化 npm

第二步:安装body-parser、mongoose、express

  • body-parser:一个中间件,负责在处理传入的请求正文之前对其进行解析。
  • express: node.js 框架
  • mongoose: Mongoose 将 MongoDB 连接到 Express Web 应用程序
npm i body-parser mongoose express 

安装 body-parser mongoose express

第三步:在当前目录下创建一个app.js文件并设置服务器。我们将包导入我们的项目并配置我们的服务器。

app.js
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require('mongoose');
  
const app = express();
  
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(express.static("public"));
  
app.listen(3000, function() {
    console.log("Server started on port 3000");
});


app.js
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require('mongoose');
  
const app = express();
  
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(express.static("public"));
  
// Connecting gfg-employees database to our express application 
  
mongoose.connect("mongodb://localhost:27017/gfg-employees", 
  { useNewUrlParser: true });
  
  
// Writing schema for employee-data collection
const employeeSchema = {
    employee_name: String,
    employee_department: String,
    employee_salary: Number
};
  
// Creating a model around employeeSchema
const EmployeeData = mongoose.model(
  "EmployeeData", employeeSchema);
  
app.listen(3000, function() {
    console.log("Server started on port 3000");
});


app.js
// Fetching all the employees  
  
app.get("/employees", (req, res) => {
    EmployeeData.find((err, foundEmployees) => {
        if (!err) {
            res.send(foundEmployees)
        } else {
            res.send(err);
        }
    })
})


app.js
// Fetching a specific employee
app.get("/employees/:employee_name", function(req, res) {
  
    Article.findOne({ employee_name: req.params.employee_name }, 
                     function(err, foundEmployees) {
        if (foundEmployees) {
            res.send(foundEmployees);
        } else {
            res.send("No employee matching that name was found.");
        }
    });
})


app.js
// Overwriting the employee data
app.put("/employees/:employee_name", (req, res) => {
    EmployeeData.updateOne(
        { employee_name: req.params.employee_name }, 
        { employee_name: req.body.employee_name, 
        employee_department: req.body.employee_department,
        employee_salary: req.body.employee_salary }, 
        { overwrite: true },
        function(err) {
            if (!err) {
                res.send(
"Successfully updated the selected employee.");
            }
        }
    );
})


app.js
// Updating an employee 
app.patch("/employees/:employee_name", function(req, res) {
  
    EmployeeData.update({employee_name:req.params.employee_name }, 
    { $set: req.body },
        function(err) {
            if (!err) {
                res.send("Successfully updated employee's salary.");
            } else {
                res.send(err);
            }
        }
    );
})


app.js
// Deleting all the employees
app.delete("/employees", function(req, res) {
  
   EmployeeData.deleteMany(function(err) {
        if (!err) {
            res.send("Successfully deleted all employees.");
        } else {
            res.send(err);
        }
    });
});


app.js
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require('mongoose');
  
const app = express();
  
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(express.static("public"));
  
// Connecting gfg-employees database to our express application 
  
mongoose.connect(
  "mongodb://localhost:27017/gfg-employees", 
   { useNewUrlParser: true }
);
  
// Writing schema for employee-data collection
const employeeSchema = {
    employee_name: String,
    employee_department: String,
    employee_salary: Number
};
  
// Creating a model around employeeSchema
const EmployeeData = mongoose.model(
  "EmployeeData", employeeSchema);
  
// Fetching all the employees  
app.get("/employees", (req, res) => {
    EmployeeData.find((err, foundEmployees) => {
        if (!err) {
            res.send(foundEmployees)
        } else {
            res.send(err);
        }
    })
})
  
// Posting a new employee
app.post("/employees", (req, res) => {
    const newEmployee = new EmployeeData({
        employee_name: req.body.employee_name,
        employee_department: req.body.employee_department,
        employee_salary: req.body.employee_salary
    });
  
    // Saving the employee
    newEmployee.save(function(err) {
        if (!err) {
            res.send("Successfully added a new employee.");
        } else {
            res.send(err);
        }
    });
})
  
// Fetching a specific employee
app.get("/employees/:employee_name", function(req, res) {
  
    EmployeeData.findOne({ employee_name: req.params.employee_name }, 
                         function(err, foundEmployees) {
        if (foundEmployees) {
            res.send(foundEmployees);
        } else {
            res.send("No employee matching that name was found.");
        }
    });
})
  
// Replacing a specific employee
app.put("/employees/:employee_name", (req, res) => {
  
    EmployeeData.update({ employee_name: req.params.employee_name }, 
                       { employee_name: req.body.employee_name, 
                        employee_department: req.body.employee_department, 
                        employee_salary: req.body.employee_salary },
                        { overwrite: true },
        function(err) {
            if (!err) {
                res.send("Successfully updated the selected employee.");
            }
        }
    );
})
  
// Updating an employee 
app.patch("/employees/:employee_name", function(req, res) {
  
    EmployeeData.update({ employee_name: req.params.employee_name },
    { $set: req.body },
        function(err) {
            if (!err) {
                res.send("Successfully updated employee's salary.");
            } else {
                res.send(err);
            }
        }
    );
})
  
// Deleting all the employees
app.delete("/employees", function(req, res) {
  
    EmployeeData.deleteMany(function(err) {
        if (!err) {
            res.send("Successfully deleted all employees.");
        } else {
            res.send(err);
        }
    });
});
  
  
app.listen(3000, function() {
    console.log("Server started on port 3000");
});


第 4 步:在 Robo3T 上创建数据库。考虑一个包含employee_name、employee_department、employee_salary 字段的员工数据库。

{

    "employee_name" : "Riya Verma",
    "employee_department" : "IT",
    "employee_salary":"90000"
},
{

    "employee_name" : "Saransh Gupta",
    "employee_department" : "Finance",
    "employee_salary":"75000"
},
{

    "employee_name" : "Harsh Sehgal",
    "employee_department" : "Production",
    "employee_salary":"60000"
},
{

    "employee_name" : "Arihant Kumar",
    "employee_department" : "Marketing",
    "employee_salary":"85000"
},
{

    "employee_name" : "Ananya Sharma",
    "employee_department" : "Human Resource Management",
    "employee_salary":"50000"
}
  • 转到Robo3t并创建一个新连接。
  • 通过单击新连接按钮创建一个名为 gfg-employees 的数据库。
  • 将创建一个数据库“gfg-employees”。现在单击它并创建一个名为“employeedatas”的新集合
  • 要插入文档,请单击employeedatas 并选择插入文档。
  • 从上面复制每个文档并一张一张插入。
  • 要查看所有文件,请单击employeedatas。

下面展示了如何创建数据库和插入文档。

创建员工数据库

第 5 步:设置 MongoDB 并为我们的员工数据编写模式以创建模型。要设置 MongoDB,我们将使用 mongoose。我们将我们的应用程序连接到 MongoDB 位置并将数据库名称添加到 URL字符串。默认情况下,MongoDB 使用端口 27017。

mongoose.connect("mongodb://localhost:27017/gfg-employees", {useNewUrlParser: true});

模式定义了我们集合的结构。我们将创建一个名为employeeSchema 的模式,它包含三个字段——employee_name、employee_department 和employee_salary。

const employeeSchema = {
 employee_name: String,
 employee_department: String,
 employee_salary : Number
};

现在我们将从employeeSchema 创建一个模型。

const EmployeeData = mongoose.model("EmployeeData", employeeSchema);

将以下代码添加到app.js文件中的现有代码中。

应用程序.js

const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require('mongoose');
  
const app = express();
  
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(express.static("public"));
  
// Connecting gfg-employees database to our express application 
  
mongoose.connect("mongodb://localhost:27017/gfg-employees", 
  { useNewUrlParser: true });
  
  
// Writing schema for employee-data collection
const employeeSchema = {
    employee_name: String,
    employee_department: String,
    employee_salary: Number
};
  
// Creating a model around employeeSchema
const EmployeeData = mongoose.model(
  "EmployeeData", employeeSchema);
  
app.listen(3000, function() {
    console.log("Server started on port 3000");
});

第 6 步:使用 GET 方法访问所有员工。我们可以通过指定资源的路由和处理请求的回调函数发送获取请求来获取所有员工。

app.get(route, (req,res)=>{
})

要检索所有员工,我们必须找到员工并从数据库中读取他们。

.find({conditions},function(err,results){
// Using the result
});

将以下代码添加到现有的app.js文件中。

应用程序.js

// Fetching all the employees  
  
app.get("/employees", (req, res) => {
    EmployeeData.find((err, foundEmployees) => {
        if (!err) {
            res.send(foundEmployees)
        } else {
            res.send(err);
        }
    })
})

运行应用程序的步骤:通过运行以下命令启动应用程序。

node app.js

输出:我们可以在 localhost:3000/employees 访问员工。

通过发送 GET 请求获取所有员工

第 7 步:使用 POST 方法创建新员工。我们将创建一个将添加到数据库中的新员工。在这里,客户端向服务器发送数据。我们还没有前端,但是我们有一个可以访问我们的数据库的服务器。我们将使用 Postman 测试我们的 API,而不是创建表单或前端。我们的目标是向我们的服务器发送一个发布请求。

我们将使用 post 方法:

app.post(route,(req,res)=>{
   ...
})

一旦客户端发送了 post 请求,我们需要通过 req.body 获取该数据。

前往邮递员并向 localhost:3000/employees 发送一个发布请求。在 body 选项卡下,将编码更改为 form-url 编码,并在 key 中添加employee_name、employee_department 和employee_salary,以及表示我们要与请求一起发送的数据的值。

key value
employee_nameSrikant Iyer
employee_departmentR&D
employee_salary45000

在正文选项卡中添加字段

我们需要将此员工保存在我们的数据库中。

const =new ({
:,..
});

将以下代码添加到 app.js 文件中的先前代码中。重新启动服务器并使用邮递员发送发布请求。

输出:转到 Robo3T 并刷新您的收藏以查看添加的文章。现在我们有一个额外的条目。

发送发布请求以添加新员工

第 8 步:获取特定员工。我们将使用 findOne 方法从数据库中读取特定员工。

.findone({conditions},(req,res)=>{
});

在这里,我们将获取具有员工姓名 Ananya Sharma 的员工。

将以下代码添加到您的app.js文件中。

应用程序.js

// Fetching a specific employee
app.get("/employees/:employee_name", function(req, res) {
  
    Article.findOne({ employee_name: req.params.employee_name }, 
                     function(err, foundEmployees) {
        if (foundEmployees) {
            res.send(foundEmployees);
        } else {
            res.send("No employee matching that name was found.");
        }
    });
})

输出:我们将在 URL 中指定employee_name 以及将显示其姓名匹配的员工。我们将在 URL 中使用 %20 来表示employee_name 中Name 和Surname 之间的空格。空格编码为 %20。因此,我们将从 localhost:3000/employees/Ananya%20Sharma 获取员工信息。

获取特定员工

第 9 步:使用 PUT 方法覆盖员工。要更换现有员工,我们将发送 put 请求。

app.put(route ,(req,res)=>{
...
});

我们将使用 Mongoose 更新方法更新员工。覆盖指定我们要替换整篇文章。

.update(
{conditions},
{updates},
{overwrite:true}
(err,results)=>{
})

将以下代码添加到您的app.js文件中

应用程序.js

// Overwriting the employee data
app.put("/employees/:employee_name", (req, res) => {
    EmployeeData.updateOne(
        { employee_name: req.params.employee_name }, 
        { employee_name: req.body.employee_name, 
        employee_department: req.body.employee_department,
        employee_salary: req.body.employee_salary }, 
        { overwrite: true },
        function(err) {
            if (!err) {
                res.send(
"Successfully updated the selected employee.");
            }
        }
    );
})

在这种情况下,我们将更改employee_name Harsh Sehgal 的员工数据,如下所示:

keyvalue
employee_nameHimanshu Raj
employee_departmentDeveloper
employee_salary56000

通过向 localhost:3000/employees/Harsh%20Sehgal 路由发送 put 请求

如果服务器发现一个参数的employee_name 为Harsh Sehgal,它会将employee_name 替换为新名称,将employee_department 替换为新部门,并更新salary 字段。

通过发送 PUT 请求覆盖员工数据

第 9 步:使用 PATCH 方法更新员工的工资。我们将通过发送带有我们希望更新的员工姓名的补丁请求来更新现有员工。要更新员工,我们必须在正文选项卡中提供要更改的字段。现在我们只更改员工的一个字段而不是整个员工数据,当我们调用 update 方法来更新我们的数据库时,就不需要覆盖方法了。要更新员工,我们必须在正文选项卡中提供要更改的字段。

在您的 app.js 文件中添加以下代码以修改员工数据。

应用程序.js

// Updating an employee 
app.patch("/employees/:employee_name", function(req, res) {
  
    EmployeeData.update({employee_name:req.params.employee_name }, 
    { $set: req.body },
        function(err) {
            if (!err) {
                res.send("Successfully updated employee's salary.");
            } else {
                res.send(err);
            }
        }
    );
})

输出:它只更新我们提供的字段。名为 Riya Verma 的员工的工资更新为 9500

通过发送 PATCH 请求更新员工数据

第 10 步:使用 DELETE 方法删除所有员工。要从我们的数据库中删除所有员工,我们将使用 deleteMany mongoose 方法并从邮递员发送删除请求。

将以下代码添加到您的app.js文件中。

应用程序.js

// Deleting all the employees
app.delete("/employees", function(req, res) {
  
   EmployeeData.deleteMany(function(err) {
        if (!err) {
            res.send("Successfully deleted all employees.");
        } else {
            res.send(err);
        }
    });
});

输出:我们将向 localhost:3000/employees 发送删除请求以删除我们所有的员工。访问 Robo3T 并刷新您的收藏。如果我们从邮递员那里发送删除请求,我们将不会观察任何员工。

删除所有员工

最终代码:

应用程序.js

const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require('mongoose');
  
const app = express();
  
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(express.static("public"));
  
// Connecting gfg-employees database to our express application 
  
mongoose.connect(
  "mongodb://localhost:27017/gfg-employees", 
   { useNewUrlParser: true }
);
  
// Writing schema for employee-data collection
const employeeSchema = {
    employee_name: String,
    employee_department: String,
    employee_salary: Number
};
  
// Creating a model around employeeSchema
const EmployeeData = mongoose.model(
  "EmployeeData", employeeSchema);
  
// Fetching all the employees  
app.get("/employees", (req, res) => {
    EmployeeData.find((err, foundEmployees) => {
        if (!err) {
            res.send(foundEmployees)
        } else {
            res.send(err);
        }
    })
})
  
// Posting a new employee
app.post("/employees", (req, res) => {
    const newEmployee = new EmployeeData({
        employee_name: req.body.employee_name,
        employee_department: req.body.employee_department,
        employee_salary: req.body.employee_salary
    });
  
    // Saving the employee
    newEmployee.save(function(err) {
        if (!err) {
            res.send("Successfully added a new employee.");
        } else {
            res.send(err);
        }
    });
})
  
// Fetching a specific employee
app.get("/employees/:employee_name", function(req, res) {
  
    EmployeeData.findOne({ employee_name: req.params.employee_name }, 
                         function(err, foundEmployees) {
        if (foundEmployees) {
            res.send(foundEmployees);
        } else {
            res.send("No employee matching that name was found.");
        }
    });
})
  
// Replacing a specific employee
app.put("/employees/:employee_name", (req, res) => {
  
    EmployeeData.update({ employee_name: req.params.employee_name }, 
                       { employee_name: req.body.employee_name, 
                        employee_department: req.body.employee_department, 
                        employee_salary: req.body.employee_salary },
                        { overwrite: true },
        function(err) {
            if (!err) {
                res.send("Successfully updated the selected employee.");
            }
        }
    );
})
  
// Updating an employee 
app.patch("/employees/:employee_name", function(req, res) {
  
    EmployeeData.update({ employee_name: req.params.employee_name },
    { $set: req.body },
        function(err) {
            if (!err) {
                res.send("Successfully updated employee's salary.");
            } else {
                res.send(err);
            }
        }
    );
})
  
// Deleting all the employees
app.delete("/employees", function(req, res) {
  
    EmployeeData.deleteMany(function(err) {
        if (!err) {
            res.send("Successfully deleted all employees.");
        } else {
            res.send(err);
        }
    });
});
  
  
app.listen(3000, function() {
    console.log("Server started on port 3000");
});