使用Node.js和Oracle数据库创建REST API。 第三部分

第3部分。创建REST API:处理GET请求


上一篇文章中,您建立了到数据库的连接。

同时,添加路由,控制器和数据库逻辑以处理对“员工” API端点的HTTP GET请求。

添加路由逻辑


Express附带了Router类,该类简化了HTTP请求到相应控制器逻辑的路由。 路由路径定义API URL的端点,并且可能包含捕获URL中值的路由参数

有很多方法可以确定应用程序的路由。 例如,当应用程序启动时,您可以读取控制器目录中的所有文件,并根据一些预定义的规则自动生成路由逻辑,例如它们提供的文件名和属性。 或者,您可以将文件添加到配置目录并在启动时读取它。

在此应用程序中,您将使用一个较低级别的方法,以编程方式定义通过新路由器模块的路由。 在services目录中创建一个名为router.js的新文件。 将以下代码添加到文件中并保存更改。

const express = require('express'); const router = new express.Router(); const employees = require('../controllers/employees.js'); router.route('/employees/:id?') .get(employees.get); module.exports = router; 

路由器模块通过请求Express模块​​开始,然后创建Router Express类的新实例。 路由器模块的路由方法用于根据传输的数据确定路由。 该路径包括一个名为id的可选参数(由于问号)。 从路由器返回的路由具有与HTTP方法匹配的方法,并允许定义处理程序。 在这种情况下,get方法用于将传入的GET请求映射到员工控制器(将在下面创建)中定义的get函数。

目前您拥有路由器,但是该路由器未在应用程序中使用。 要使用它,请打开services / web-server.js文件,并在顶部删除需要数据库模块的行(仅在一篇文章中用于测试)。 在其位置添加以下代码行。

 // *** line that requires ../config/web-server.js is here *** const router = require('./router.js'); 

然后,使用以下代码替换整个app.get处理程序,该处理程序使用数据库模块(所有7行)响应GET请求。

 // *** line that adds morgan to app here *** // Mount the router at /api so all its routes start with /api app.use('/api', router); 

现在,在Web服务模块中请求了路由器,并将其“挂载”在/ api中。 这意味着雇员端点的完整URL将为http://服务器:端口/ api /雇员/:id。

添加控制器逻辑


控制器逻辑将从知道端点URL和HTTP方法的那一刻起开始运行。 由于Web服务器是使用Express构建的,因此将使用可访问请求和响应对象以及下一个功能的特殊中间件或功能来确定控制器逻辑。

中间件功能将使用来自请求对象的输入来生成响应,该响应被发送到响应对象。 下一个函数通常用于调用管道中的下一个中间件函数。 但是,在此API中,控制器逻辑将是管道中的最后一步,并完成HTTP响应。 仅当发生将控制权传递给标准Express错误处理程序的错误时,才会调用下一个函数。

转到controllers目录并创建一个名为employee.js的新文件。 将以下代码复制并粘贴到文件中,然后保存更改。

 /*01*/const employees = require('../db_apis/employees.js'); /*02*/ /*03*/async function get(req, res, next) { /*04*/ try { /*05*/ const context = {}; /*06*/ /*07*/ context.id = parseInt(req.params.id, 10); /*08*/ /*09*/ const rows = await employees.find(context); /*10*/ /*11*/ if (req.params.id) { /*12*/ if (rows.length === 1) { /*13*/ res.status(200).json(rows[0]); /*14*/ } else { /*15*/ res.status(404).end(); /*16*/ } /*17*/ } else { /*18*/ res.status(200).json(rows); /*19*/ } /*20*/ } catch (err) { /*21*/ next(err); /*22*/ } /*23*/} /*24*/ /*25*/module.exports.get = get; 

第1行:员工数据库API(将在下面创建)。
第3-23行:声明了一个名为get 异步函数。 在函数体中使用try-catch块来捕获在主线程中引发的异常并将它们传递给下一个函数。
第5-7行:声明了具有命名上下文的常量-这是一个通用对象,将包含与数据库API搜索方法相关的属性。 id属性基于req.params.id的值添加到上下文中。
第9行: find方法用于在数据库中检索适当的员工记录。
第11-19行:条件逻辑用于确定正确的HTTP状态代码和响应正文。 如果请求一位雇员但未找到,则发送错误代码“ 404 Not Found”作为响应。 否则,将发送200 OK代码以及基于JSON的响应正文。
第25行:模块导出,以便您可以添加到其他模块

req.params对象只是用于从传入请求对象获取数据的几个属性之一。 其他常见属性包括URL中查询字符串值的req.query,请求正文的req.body和req.cookies。 可以使用req.get方法获取HTTP标头。

添加数据库逻辑


要启动员工数据库模块,请转到db_apis目录并创建一个名为employee.js的新文件。 将以下代码添加到文件中。

 const database = require('../services/database.js'); const baseQuery = `select employee_id "id", first_name "first_name", last_name "last_name", email "email", phone_number "phone_number", hire_date "hire_date", job_id "job_id", salary "salary", commission_pct "commission_pct", manager_id "manager_id", department_id "department_id" from employees`; async function find(context) { let query = baseQuery; const binds = {}; if (context.id) { binds.employee_id = context.id; query += `\nwhere employee_id = :employee_id`; } const result = await database.simpleExecute(query, binds); return result.rows; } module.exports.find = find; 

员工数据库模块引入了一个公共数据库模块,并为员工表中的SQL查询初始化了一个名为baseQuery的常量。 双引号列别名用于控制返回键的大小写。

然后,声明一个名为find的函数,该函数用于执行查询并返回提取的行。 如果传递的上下文参数具有真实的id值,则将where子句添加到请求中,因此仅返回一名员工。

请注意,context.id值未直接添加到请求中。 相反,使用了一个名为:employee_id的占位符-这称为绑定变量 。 就安全性和性能而言,使用Oracle数据库绑定变量非常重要。 将bind变量的值分配给binds对象,该对象随查询一起传递给database.simpleExecute。 最后,将从数据库中检索到的行返回给调用方。

启动应用程序,然后转到浏览器,位于http://本地主机:3000 / api / employee。 您应该看到如下员工列表(我折叠了几张):
图片
您可以通过在URL末尾添加标识符来选择一名员工,例如:http://本地主机:3000 / api / employee / 100。

图片

此时,您的API可以在员工的端点处理GET请求。 在下一篇文章中,您将通过添加处理POST,PUT和DELETE请求的逻辑来扩展CRUD功能。

Source: https://habr.com/ru/post/zh-CN473350/


All Articles