Node.js—Express使用、Express 路由 、Express 中间件、托管静态资源、使用 Express 写接口、node.js链接sqlite数据库

简介: Node.js—Express使用、Express 路由 、Express 中间件、托管静态资源、使用 Express 写接口、node.js链接sqlite数据库


一小池勺❤️❤️❤️ ❤️❤️❤️❤️胸有惊雷而面如平湖者,可拜上将军也。


前言

前端也是可以编写接口的噢,我们一步一步学下去吧。

Express 安装

首先假定你已经安装了 Node.js,接下来为你的应用创建一个目录,然后进入此目录并将其作为当前工作目录。

$ mkdir myapp
$ cd myapp

通过 npm init 命令为你的应用创建一个 package.json 文件。

$ npm init

此命令将要求你输入几个参数,例如此应用的名称和版本。 你可以直接按“回车”键接受大部分默认设置即可,下面这个除外:

entry point: (index.js)

**键入 app.js 或者你所希望的名称,这是当前应用的入口文件。**如果你希望采用默认的 index.js 文件名,只需按“回车”键即可。

接下来在 myapp 目录下安装 Express 并将其保存到依赖列表中。如下:

$ npm install express --save

如果只是临时安装 Express,不想将它添加到依赖列表中,可执行如下命令:

$ npm install express --no-save

安装nodemon工具

为什么要使用nodemon

在编写调试 Node.js项目的时候,如果修改了项目的代码,则需要频繁的手动close掉,然后再重新启动,非常繁琐.。现在,我们可以使用nodemon (https/www.npmjs.com/package/nodemon)这个工具,它能够监听项目文件的变动,当代码被修改后,nodemon 会自动帮我们重启项目。极大方便了开发和调试。

安装

npm i -g nodemon

使用nodemon

第一个案例体验

const express = require('express') // => 引入 express 模块
const app = express() // => 实例化模块
const port = 8080 // => 定义端口变量
app.get('/', (req, res) => {
  res.send('Hello World!')
})
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

如上就是一个使用 express 创建的最基本的web服务器

第五行中 '/',指的是根目录,可以理解为什么都没带,就比如我是8080端口打开,那么此时的地址栏为 http://localhost:8080/。req指的是请求,res指的是响应

现在站在服务端的视角来看:req是前端传过来的,res是响应返回给前端的

第九行中调用app.listen方法,启动服务器,是监听了port这个端口号,监听成功后执行回调

Express基本使用之监听请求

监听get请求

通过 app.get() 方法,可以监听客户端的GET请求,具体语法格式如下:

监听post请求

将内容响应给客户端

通过res.send()方法,可以把处理好的内容,发送给客户端:

基础代码示例
/*
res.send()
1. send 方法内部会检测响应内容的类型
2. send 方法会自动设置 http 状态码
3. send 方法还会帮我们自动设置响应的内容类型以及编码
*/
// => 引入 express 框架
const express = require('express')
// => 创建网站服务器
const app = express();
app.get('/', (req, res) => {
    res.send('Hello Express');
})
app.get('/list', (req, res)=> {
    // => 调用express提供的res.send()方法,向客户端响应一个JSON对象
    res.send({name: 'zhangsan', age: 20});
})
app.post('/list',(req,res) => {
    // => 调用express提供的res.send()方法,向客户端响应一个文本字符串
})
// => 监听端口
app.listen(3000);
console.log('网站服务器启动成功');

Express之获取URL中的参数

获取 URL 中携带的查询参数

// => 引入 express 框架
const express = require('express')
// => 创建网站服务器
const app = express();
app.get('/', (req, res) => {
    // => 通过 req.query 可以获取到客户端发送过来的查询参数
    // => 注意:默认情况下,req.query是一个空对象
    console.log(req.query)
    res.send(req.query)
})
// 监听端口
app.listen(3000);
console.log('网站服务器启动成功');

如上,我们服务器站点已经打开为 http://localhost:3000,处理的是地址为’/'的get请求

现在我们使用postman工具模拟客户端来发起get请求,并带query参数

我们可以看到在模拟客户端的工具内确实是响应了JSON对象(res.send(req.query))

同时我们也可以看到服务端的打印情况

获取 URL 中的动态参数

// => 引入 express 框架
const express = require('express')
// => 创建网站服务器
const app = express();
// => :id 是一个动态的参数
app.get('/user/:id',(req,res) => {
    // => res.params 是动态匹配到的 URL 参数,默认也是一个空对象
    console.log(req.params)
    res.send(req.params)
})
// 监听端口
app.listen(3000);
console.log('网站服务器启动成功');

同样我们来看客户端和服务端的响应情况

客户端

服务端

当然,,也是可以有多个动态参数的,如:

/user/:name/:age

Express之托管静态资源

express提供了一个非常好用的函数,叫做express.static(),通过它,我们可以非常方便地创建一个静态资源服务器,例如,通过如下代码就可以将public目录下的图片、CSS文件、JavaScript 文件对外开放访问了:

app.use(express.static('public'))

现在,你就可以访问public目录中的所有文件了:

http://localhost:3000/images/bg.jpg

http://localhost:3000/css/style.css

http://localhost:3000/js/login.js

注意:Express在指定的静态目录中查找文件,并对外提供资源的访问路径。因此,存放静态文件的目录名不会出现在URL中,就比如寻找静态资源时,就没有带上public文件目录名。

代码示例

const express = require('express')
const app = express()
// => 在这里,调用 express.static() 方法,快速地对外提供静态资源
app.use(express.static('./public'))
app.listen(8080,() => {
    console.log('express server runing at http://locallhost:8080')
})
托管多个静态资源目录

访问静态资源文件时,express.static()函数会根据目录的添加顺序查找所需的文件。如上,在访问静态资源时,比如要找的时index.html,此时,public和files中都有index.html文件夹,这样在public中找到后,便不会继续往下找了。

挂载路径前缀

如果希望在托管的静态资源访问路径之前,挂载路径前缀,则可以使用如下的方式:

app.use("/public", express.static("public"))

现在,就可以通过带有/public前缀地址来访问public目录中的文件了:

http://localhost3000/public/images/kitten.jpg

http://localhost:300d7public/css/style.css

http://localhost:3000/publicljs/app.js

Express之路由

现实生活的路由

在这里,路由是按健与服务之问的映射关系

Express中的路由

在 Express 中,路由指的是客户端的请求服务器处理函数之间的映射关系

Express中的路由分三部分组成,分别是请求的类型请求的URL地址处理函数,格式如下:

app.METHOD(PATH,HANDLER)
Express中的路由例子
const express = require('express')
const app = express()
// => 匹配 GET 请求,且请求 URL 为 /
app.get('/',function(req,res) {
    res.send('Hello')
})
// => 匹配 POST 请求,且请求 URL 为 /
app.post('/',function(req,res) {
    res.send('Got a POST request')
})
理解路由的匹配过程

每当一个请求到达服务器之后,需要先经过路由的匹配,只有匹配成功之后,才会调用对应的处理函数。

在匹配时,会按照路由的顺序进行匹配,如果请求类型请求的URL同时匹配成功,则 Express 会将这次请求,转交给对应的function函数进行处理。

路由的使用
最简单的路由用法

在Express中使用路由最简单的方式,就是把路由挂载到app上,如下

const express = require('express ')
// => 创建web服务器,命名为app
const app = express()
// => 挂载路由
app.get('/',(req,res) => { res.send('hell World') })
// => 启动 Web 服务器
app.listen(8080,()=>{console.log('启动')})
路由的模块化

为了方便对路由进行模块化的管理,Express 不建议将路由直接挂载到app上,而是推荐将路由抽离为单独的模块。将路由抽离为单独模块的步骤如下:

① 创建路由模块对应的 .js 文件

② 调用 express.Router() 函数创建路由对象

③ 向路由对象上挂载具体的路由

④ 使用 Module.exports 向外共享路由对象

⑤ 使用 app.use() 函数注册路由模块

① —> ④,如下

/*
    这是路由模块
*/
// => 1. 导入express
const express = require('express')
// => 2. 创建路由对象
const router = express.Router()
// => 3. 挂载具体路由
router.get('/user/list',(req,res) => {
    res.send('Get user List.')
})
router.post('/user/add',(req,res) => {
    res.send('Add new user.')
})
// => 4. 向外导出路由对象
module.exports = router

⑤,如下

const express = require('express')
const app = express()
// => 导入路由模块
const router = require('./08-router')
// => 注册路由模块
app.use(router)
app.listen(8080,() => {
    console.log('http:127.0.0.1')
})
为路由模块添加前缀

类似于托管静态资源时,为静态资源统一挂载访问前缀一样,路由模块添加前缀的方式也非常简单:

Express之中间件

生活当中的例子

在处理污水的时候,一般要经过三个处理环节,从而保证处理过的废水,达到排放标准。

处理污水的这三个中间处理环节,就可以叫做中间件。

Expres中间件的调用流程

当一个请求到达 Express 的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。

Express 中间件的格式

注意:中间件函数的形参列表中,必须包含 next 参数,而路由处理函数中只包含 req 和 res。因此区分是中间件处理函数还是路由处理函数的区别就是看参数列表是否包含next参数。

next 函数的作用

next函数是实现多个中间件连续调用的关键。它表示把流转关系转交给下一个中间件或路由。

定义中间件函数

可以通过如下的方式,定义一个最简单的中间件函数:

const express = require('express')
const app = express()
// => 定义一个最简单的中间件函数
const mw = function(req,res,next) {
    console.log('这是最简单的中间件函数')
    // => 把流转关系,转交给下一个中间件或路由
    next()
}
app.listen(8080,() => {
    console.log('Web服务启动');
})
全局生效的中间件

客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。

通过调用app.use(中间件函数),即可定义一个全局生效的中间件,示例代码如下:

const express = require('express')
const app = express()
// => 定义一个最简单的中间件函数
const mw = function(req,res,next) {
    console.log('这是最简单的中间件函数')
    // => 把流转关系,转交给下一个中间件或路由
    next()
}
// => 全局生效的中间件
app.use(mw)
app.get('/',(req,res) => {
    console.log('这次流转到我 / 这里了')
    res.send('Home page')
})
app.get('/user',(req,res) => {
    res.send('User page.')
})
app.listen(8080,() => {
    console.log('Web服务启动');
})

接着我们使用 postman 给我们这个开启的 Web 服务器发起请求

客户端:

服务器:

定义中间件的简化形式

中间件在实际开发中的作用

多个中间件之间,共享同一份req和res。基于这样的特性,我们可以在上游的中间件中,统一reqres对象添加自定义属性方法,供下游的中间件或路由进行使用。

代码示例

/*
*  捕获请求到达到达服务器的时间
*/
const express = require('express')
const app = express()
app.use((req,res,next) => {
    // => 获取请求到达服务器的时间
    const time = Date.now()
    // => 为 req 对象,挂载自定义属性,从而把时间共享给后面的所有路由
    req.startTime = time
    next()
})
app.get('/',(req,res) => {
    console.log('这次流转到我 / 这里了' + ' 请求时间是' + req.startTime)
    res.send('Home page')
})
app.get('/user',(req,res) => {
    console.log('这次流转到我 /user 这里了' + ' 请求时间是' + req.startTime)
    res.send('User page.')
})
app.listen(8080,() => {
    console.log('Web服务启动');
})
定义多个全局中间件

可以使用app.use()连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用,示例代码如下:

const express = require('express')
const app = express()
// => 定义一个全局中间件
app.use((req,res,next) => {
    console.log('调用了第1个全局中间件')
    next()
})
// => 定义第二个全局中间件
app.use((req,res,next) => {
    console.log('调用了第二个全局中间件')
    next()
})
// => 定义一个路由
app.get('/user',(req,res) => {
    res.send('User page')
})
app.listen(8080,() => {
    console.log('启动')
})
局部生效的中间件

不使用app.use0定义的中间件,叫做局部生效的中间件,示例代码如下:

const express = require('express')
const app = express()
// 1. 定义中间件函数
const mw1 = (req,res,next) => {
    console.log('调用了局部生效的中间件')
    next()
}
// 2. 创建路由
// mw1 就是局部的中间件了
app.get('/',mw1,(req,res) => {
    res.send('Home page')
})
app.get('/user',(req,res) => {
    res.send('User page')
})
// => 指定端口号,并启动web服务器
app.listen(8080,function(){
    console.log('启动');
})
定义多个局部中间件
const express = require('express')
const app = express()
// 1. 定义中间件函数
const mw1 = (req,res,next) => {
    console.log('调用了第一个局部生效的中间件')
    next()
}
const mw2 = (req,res,next) => {
    console.log('调用了第二个局部生效的中间件')
    next()
}
// 2. 创建路由
app.get('/',mw1,mw2,(req,res) => {
    res.send('Home page')
})
app.get('/user',(req,res) => {
    res.send('User page')
})
// => 指定端口号,并启动web服务器
app.listen(8080,function(){
    console.log('启动');
})
中间件的注意事项

一定要在路由之前注册中间件

客户端发送过来的请求,可以连续调用多个中间件进行处理执行完中间件的业务

代码之后,不要忘记调用next()函数

为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码

连续调用多个中间件时,多个中间件之间,共享req和res 对象

监听 req 的 data 事件

在中间件中,需要监听req对象的data事件,来获取客户端发送到服务器的数据。

如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以data事件可能会触发多次,每一次触发data事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接。

// 定义变量,用来储存客户端发送过来的请求体数据
let str = ''
// 监听 req 对象的 data 事件(客户端发送过来的新的请求体数据)
req.on('data',(chunk) => {
  // 拼接请求体数据,隐式转换为字符串
  str += chunk
})
监听 req 的 end 事件

当请求体数据接收完毕之后,会自动触发req的end 事件。

因此,我们可以在req的end 事件中,拿到并处理完整的请求体数据。示例代码如下:

// 监听 req 对象的 end 事件(请求体发送完毕后自动触发)
req.on('end',() => {
  // => 打印完整的请求体数据
  console.log(str)
  // TODO: 业务逻辑
  // .......
})
Express中间件的分类

为了方便理解和记忆中间件的使用,Express 官方把常见的中间件用法,分成了5大类,分别是:

应用级别的中间件

通过app.use()或app.get()或 app.post(),绑定到app实例上的中间件,叫做应用级别的中间件,代码示例如下:

路由级别的中间件

绑定到express.Router()实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到 app实例上,路由级别中绚件摸定到router 实例上,代码示例如下:

错误极别的中间件

错误级别中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。

格式:错误级别的中间件的 function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是(err,req,res,next)。

代码示例

**注意:**错误级别的中间件必须注册在所有路由之后。

// 引入 express 框架
const express = require('express')
// 创建网站服务器
const app = express();
// 1. 定义路由
app.get('/',(req,res) => {
   // 1.1 人为的制造错误
   throw new Error('服务器内部发生错误')
})
// 2. 定义错误级别的中间件,捕获整个项目的异常错误,从而防止程序的崩溃
app.use((err,req,res,next) => {
    console.log('发生了错误!' + err.message)
    res.send('Error:' + err.message)
}) 
// 监听端口
app.listen(8080,function() {
    console.log('Express server is running')
})

Express内置的中间件

自Express 4.16.0版本开始,Express 内置了3个常用的中间件,极大的提高了Express 项目的开发效率和体验:

express.static快速托管静态资源的内置中间件,例如:HTML文件、图片、CSS样式等(无兼容性

express.json解析JSON格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)

// => 配置解析 application / json 格式数据的内置中间件
app.use(express.json())

express.urlencoded解析URL-encoded格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)

// => 配置解析 application / x-www-from-urlencoded 格式数据的内置中间件
app.use(express.urlencoded({ extended: false }))

代码示例

// 引入 express 框架
const express = require('express')
// 创建网站服务器
const app = express();
// 注意:除了错误级别的中间件,其他中间件,必须在路由之前进行配置
// 通过 express.json 这个内置中间件,解析表单中 json 格式的数据
app.use(express.json())
// 通过 express.ulencoded() 这个中间件,解析表单中 url-encoded 格式的数据
app.use(express.urlencoded({ extended: false }))
app.post('/user',(req,res) => {
    // 在服务器,可以使用req.body这个属性,来接受客户端发送过来的请求体数据
    // 默认情况下,如果不配置解析表单数据的中间件,则 req.body 默认等于 undefined
    console.log(req.body)
    res.send('ok')
})
app.post('/book',(req,res) => {
    console.log(req.body)
    res.send('ok')
})
app.listen(3000,function() {
    console.log('网站服务器启动成功');
})

第三方的中间件

非Express官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中,大家可以按需下载并配置第三方中间件,从而提高项目的开发效率。

例如:在express@4.16.0之前的版本中,经常使用body-parser这个第三方中间件,来解析请求体数据。使用步骤如下:

运行npm install body-parser安装中间件

使用require导入中间件

调用app.use()注册并使用中间件

自定义中间件

需求描述与实现步骤

自己手动模拟一个类似于express.urlencoded这样的中间件,来解析POST提交到服务器的表单数据。

实现步骤

定义中间件

监听req的data事件

监听req的end 事件

使用querystring模块解析请求体数据

将解析出来的数据对象挂载为req.body

将自定义中间件封装为模块

代码示例

// => 引入 express 框架
const express = require('express')
// => 创建网站服务器
const app = express()
// 1. 导入自己封装的中间件模块
const custonBodyParser = require('./21-封装')
// 2. 将自定义的中间件函数注册为全局可用的中间件
app.use(custonBodyParser)
app.post('/user',(req,res) => {
    res.send('ok')
    res.send(req.body)
})
// => 监听端口
app.listen(3000,function() {
    console.log('网站服务器启动成功')
})

封装的模块

// => 导入 Node.js内置的 querystring 模板
const bodyParser = require('body-parser')
const qs = require('querystring')
app.use((req,res,next) => {
    // => 定义中间件具体的业务逻辑
    let str = ''
    req.on('data',(chunk) => {
        str += chunk
    })
    req.on('end',() => {
        console.log(str) // => 在 str 中存放的是完整的请求体数据
        // => 业务:把字符串格式的请求体数据,解析成对象格式
        const body = qs.parse(str)
        console.log(body)
        req.body = body
        next()
    })
})
modules.exports = bodyParser

使用Express编写接口

编写 GET 接口

核心代码

apiRouter.get('/get',(req,res) => {
    // 1. 获取到客户端通过查询字符串,发送到服务器的数据
    const query = req.query
    // 2. 调用 res.send() 方法,把数据响应给客户端
    res.send({
        status: 0, // 状态,0 表示成功
        msg: 'GET请求成功!', // 状态描述
        data: query // 需要响应给客户端的具体数据
    })
})
编写 POST 接口

核心代码

apiRouter.post('/post',(req,res) => {
    // 1. 获取客户端通过请求体,发送到服务器的 URL-encoded 数据
    const body = req.body
    // 2. 调用 res.send() 方法,把数据响应给客户端
    res.send({
        status: 0, // 状态,0 表示成功,1 表示失败
        msg: 'POST请求成功!', // 状态描述信息
        data: body // 需要响应给客户端的具体数据
    })
})

注意:如果要获取URL-encoded格式的请求体数据,必须配置中间件 app.use(express.urlencoded(extended:false))

创建服务器及编写简单接口

首先创建基本的服务器,提供接口的导入口

const express = require('express') // => 导入 express
const app = express() // => 创建服务器实例
app.use(express.urlencoded({extended:false})) // => 配置解析表单的数据中间件
// => 本来路由写在这里的,现在模块化管理了,导入注册即可
// => 导入并注册路由模块,这样客户端到达的请求就会到对应封装好的接口中去匹配对应的路由
const router = require('./23-接口')
app.use('/api',router)
// => 启动服务器
app.listen(3000,() => {
    console.log('Web服务器已经创建');
})

封装API接口并暴露链接

const express = require('express')
const router = express.Router()
// => 在这里挂载对应的路由
// 如下, 编写一个 GET 接口
router.get('/get',(req,res) => {
    // 通过req.query获取客户端通过查询字符串,发送到服务器的数据
    const query = req.query
    // 调用res.send()方法,向客户端响应处理的结果
    res.send({
        status:0, // => 0表示处理成功,1表示处理失败
        msg:'GET 请求成功', // => 状态的描述
        data: query // => 需要响应给客户端的数据
    })
})
// 如下,编写一个 POST 接口
router.post('/post',(req,res) => {
    // 通过 req.body 获取请求体中包含的 url-encoded 格式的数据
    const body = req.body
    // 调用 res.send 方法,向客户端响应数据
    res.send({
        status:0,
        msg:'POST请求成功',
        data: body
    })
})
module.exports = router

使用Express框架链接sQlite3数据库

一. 安装sqlite3,运行如下命令
yarn add sqlite3 --ignore-scripts
二. 实现链接

文件夹目录

▽ Message
   ▸ node_modules
   ▸ public
     ▸ hello.html
   ▸ db
     ▸ db.sqlite3
     ▸ dbutils.js
   ▸ router
     ▸ MessageRouter.js
   ▸ app.js
   ▸ package-lock.json
   ▸ package.json
   ▸ yarn.lock

1、创建数据库

  • 创建数据库文件:

注意 ,数据文件配置的路径是要和我们项目调用数据文件保持一致

  • 新建一个表:

  • 添加字段:

  • 添加数据

2、使用NODE开始链接数据库

首先,我们希望的是,使用我们搭建的服务器来连接数据库,那么创建服务器

app.js

const express = require("express")
const path = require("path")
const app = express()
let port = 3000
// => 为前端开放跨域请求
app.use(function (req,res,next) {
    // => 设置允许跨域的域名,* 代表允许任意域名跨域
    res.header("Access-Control-Allow-Origin","*");
    // => 允许的header类型
    res.header("Access-Control-Allow-Headers","content-type");
    // => 跨域允许的请求方式
    res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
    if(req.method == "OPTIONS") res.sendStatus(200) // => 让options尝试请求快速结束
    else next()
})
// => 导入路由
app.use("/message",require("./router/MessageRouter.js"))
// => 导入静态资源
app.use(express.static(path.join(__dirname,"./public")))
app.get("/",(req,res) => {
    res.send("hello")
})
app.listen(port,(req,res) => {
    console.log(`启动成功`)
})

然后我们配置相关路由

router / MessageRouter.js

const express = require("express")
const {db} = require("../db/dbutils")
var router = express.Router()
router.get("/test",(req,res) => {
    // => 查询数据库
    db.all("select * from `message`",(err,rows) => {
        res.send(rows)
    })
})
module.exports = router

为了使得数据库导出及复用性更高,我们将其单独封装成一个链接

db / dbutils.js

const path = require("path") // => 导入 path 模块
const sqlite3 = require("sqlite3").verbose() // => 导入依赖
const db = new sqlite3.Database(path.join(__dirname,"./db.sqlite3")) // => 实例化
// => 暴露
module.exports = {db}

启动

查看是否链接成功

接口的跨域问题

咱们刚才编写的 GET 和 POST 接口,存在一个很严重的问题,不支持跨域请求(跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制)。

我们仍然使用刚才所打开的服务器,现在测试发起请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.staticfile.org/jquery/3.7.0/jquery.slim.js"></script>
</head>
<body>
    <button id="btnGET">GET</button>
    <button id="btnPOST">POST</button>
    <script>
        // => 1. 测试GET接口
       $('#btnGET').on('click',function() {
        $.ajax({
            type: 'GET',
            url: 'http://localhost:3000/api/get',
            data: {name:'hv',age:20},
            success: function(res) {
                console.log(res)
            }
        })
       })
        // => 2. 测试POST接口
       $('#btnPOST').on('click',function() {
        $.ajax({
            type: 'POST',
            url: 'http://localhost:3000/api/get',
            data: {bookname:'水浒传',author:'施耐庵'},
            success: function(res) {
                console.log(res)
            }
        })
       })
    </script>
</body>
</html>

如下,可以看见违反了同源策略( 同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域)。

如下的协议名是 file

以前我们使用 postman 发起请求的时候,是没有违反同源策略的,用的就是服务器的域名。

使用 cors 中间件解决跨域问题(主流的解决方案,推荐使用)

cors 是 Express的一个第三方中间件。通过安装和配置cors中间件,可以很方便地解决跨域问题。使用步骤分为如下3步:

  1. 运行 npm install cors 安装中间件
  2. 使用 const cors = require('cors') 导入中间件
  3. 在路由之前 调用app.use(cors()) 配置中间件
const express = require('express') // => 导入 express
const app = express() // => 创建服务器实例
app.use(express.urlencoded({extended:false})) // => 配置解析表单的数据中间件
// => 一定要在路由之前,配置 cors 这个中间件,从而解决接口跨域的问题
const cors = require('cors')
app.use(cors())
// => 本来路由写在这里的,现在模块化管理了,导入注册即可
// => 导入并注册路由模块,这样客户端到达的请求就会到对应封装好的接口中去匹配对应的路由
const router = require('./23-接口')
app.use('/api',router)
// => 启动服务器
app.listen(3000,() => {
    console.log('Web服务器已经创建');
})

注意:

CORS主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了CORS的接口。

CORS在浏览器中有兼容性。只有支持XMLHttpRequest Level2的浏览器,才能正常访问开启了CORS的服务端接口。

结语

保持热爱,永远都在前进的路上❤️

目录
相关文章
|
3月前
|
SQL 关系型数据库 MySQL
后端接口性能优化分析-数据库优化(上)
后端接口性能优化分析-数据库优化
115 0
|
3月前
|
前端开发 数据库 Python
使用 Python 的 Web 框架(如 Django 或 Flask)来建立后端接口,用于处理用户的请求,从数据库中查找答案并返回给前端界面
【1月更文挑战第13天】使用 Python 的 Web 框架(如 Django 或 Flask)来建立后端接口,用于处理用户的请求,从数据库中查找答案并返回给前端界面
87 7
|
3月前
|
SQL 关系型数据库 MySQL
后端接口性能优化分析-数据库优化(下)
后端接口性能优化分析-数据库优化
70 1
|
1月前
|
存储 关系型数据库 MySQL
解释一下如何使用Python的数据库接口库进行数据库操作。
【2月更文挑战第12天】【2月更文挑战第33篇】解释一下如何使用Python的数据库接口库进行数据库操作。
|
3月前
|
JavaScript 关系型数据库 MySQL
百度搜索:蓝易云【Node.js写接口连接MySQL数据库教程】
现在,你的Node.js应用已经启动,可以通过访问 `http://localhost:3000/users`来获取所有用户的信息。注意替换上述代码中的数据库连接信息为你自己的实际数据。
50 0
|
3月前
|
SQL 关系型数据库 MySQL
后端接口性能优化分析-数据库优化(中)
后端接口性能优化分析-数据库优化
121 0
|
3月前
|
Java 数据库 Nacos
spring-gateway基于数据库 + nacos 的动态路由
spring-gateway基于数据库 + nacos 的动态路由
73 0
|
4月前
|
JavaScript 关系型数据库 MySQL
如何在 Node.js 中连接 MySQL 数据库
如何在 Node.js 中连接 MySQL 数据库
96 0
|
8月前
|
NoSQL Java Redis
阿里Java高级岗中间件二面:GC+IO+JVM+多线程+Redis+数据库+源码
虽然“钱多、事少、离家近”的工作可能离技术人比较远,但是找到一份合适的工作,其实并不像想象中那么难。但是,有些技术人确实是认真努力工作,但在面试时表现出的能力水平却不足以通过面试,或拿到高薪,其实不外乎以下 2 个原因:
|
8月前
|
算法 NoSQL Java
2023年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)