NodeJS - Express使用

  1. Express 的作用 和 Node.js内置的http模块 类似,我们可以方便、快速的创建Web网站服务器(专门对外提供Web网页资源的服务器)或API接口服务器(专门对外提供API接口的服务器)
  2. Express的本质:就是一个npm上的第三方包,其基于内置的http模块进一步封装,能够极大的提高开发效率

1. 参数

1.1 获取URL中的动态参数

通过req.params对象,可以访问到URL中,通过 : 匹配到的动态参数

app.post('/user/:id/:name', (req, res) => {
    const q = req.params;
    console.log(q);
    res.send(q);
})

POST :http://127.0.0.1:8081/user/1001/zhangsan

2. 静态资源

express提供了一个非常好用的函数,叫做express.static(),通过它,我们可以创建一个静态资源服务器。
如果要托管多个静态资源目录,需要多次调用 express.static() 函数

2.1 挂载路径前缀

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

//express.static(),通过它,我们可以创建一个静态资源服务器
// http://127.0.0.1:8080/loess/body.html
app.use( '/loess',express.static('../../file'));

3. nodemon

nodemon 它能够监听项目文件的变动,当代码被修改后,nodemon 会自动帮我们重启项目,代替了手动频繁重启。
nodemon xxx.js

4.1路由

在Express中,路由指的是客户端的请求与服务器处理函数之间的映射关系。
Express中的路由分3部分组成,分别是请求的类型、请求的URL地址、处理函数

4.1 路由的匹配过程

每当一个请求到达服务器之后,需要先经过路由的匹配,在匹配时,会按照路由的顺序进行匹配 ( 按照定义的先后顺序、从上向下匹配),如果请求类型和请求的URL同时匹配成功,则Express会将这次请求,转交给对应的function函数进行处理。

4.2 模块化路由

为了方便对路由进行模块化的管理,Express 不建议将路由直接挂载到对象上,而是推荐将路由抽离为单独的模块。
将路由抽离为单独模块的步骤如下:
① 创建路由模块对应的js文件
② 调用express.Router0函数创建路由对象
③ 向路由对象上挂载具体的路由
④ 使用module.exports向外共享路由对象
⑤ 使用app.use0函数注册路由模块

4.3 为路由模块添加前缀
// 导入路由模块
const router = require('./webrouter')
// 注册路由模块
// app.use()函数的作用,用来注册全局中间件
app.use('/api',router);

http://127.0.0.1:8081/api/user/1001/zhangsan

5. 中间件

当一个请求到达Express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。
在这里插入图片描述
Express的中间件,本质上是一个function处理函数,只不过中间件函数的形参列表中,必须包含next参数。而路由处理函数中只包含req和res.
next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。

5.1 全局生效的中间件

客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。
通过调用app.use(中间件函数),即可定义一个全局生效的中间件

const expresss = require('express')
const app = expresss();

const mw = function (req, res, next) {
    console.log("将mw注册为全局生效的中间件")
    next()
}
app.use(mw);
5.2 全局生效中间件的简化形式
// 定义全局中间件的简化形式
app.use((req, res, next)=>{
    console.log("将mw注册为全局生效的中间件")
    next()
})
5.3 中间件的作用

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

5.4 局部生效的中间件

不使用app.use()定义的中间件,叫做局部生效的中间件, 只在路由中生效

const expresss = require('express')
const app = expresss();

在这里插入图片描述
上例中,局部中间件只在路由"/“中生效,在路由”/user"中不生效

5.5 定义多个局部中间件
const mw1 = function (req, res, next) {
    console.log("将mw注册为第一个局部生效的中间件")
    next()
}

const mw2 = function (req, res, next) {
    console.log("将mw注册为第二个局部生效的中间件")
    next()
}

app.get('/user/:id',  mw1,mw2,function (req, res) {
    console.log(req.url);
    const q = req.query;
    res.send(q);
})
5.6 使用中间件的五个注意事项

①一定要在路田之前注册中间件
②客户端发送过来的请求,可以连续调用多个中间件进行处理
③执行完中间件的业务代码之后,不要忘记调用next()函数
④为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
⑤连续调用多个中间件时,多个中间件之间,共享req和res对象

5.7 中间件分类
5.7.1 应用级别的中间件

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

5.7.2 路由级别的中间件

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

5.7.3 错误级别的中间件

错误级别中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。
格式:错误级别中间件的function处理函数中,必须有4个形参,形参顺序从前到后,分别是(err, req, res, next)。
错误级别的路由器必须放在所有路由之后

5.7.4 Express 内置的中间件

① express.static() 快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS 样式等(无兼容性)
② express.json() 解析JSON格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
③ express.urlencoded() 解析URL-encoded格式的请求体数据 (有兼容性,仅在4.16.0+版本中可用)
④ express.json() 和 express.urlencoded() 需要放在路由的前面,若不注册该中间件函数,路由函数中获取到的值为undefined

// 配置解析application/json格式请求数据的内置中问件
app.use(expresss.json( ))
// 配置解析application/ x-www-form-urlencoded格式请求数据的内置中间件
app.use( expresss.urlencoded({ extended: false }))

// 导入路由模块
const router = require('./webrouter')
// 注册路由模块
// app.use()函数的作用,用来注册全局中间件
app.use('/api', router);
//express.static(),通过它,我们可以创建一个静态资源服务器
app.use('/loess', expresss.static('../../file'));
5.7.5 第三方的中间件

非Express官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。

const bodyparser = require('body-parser')

app.use(bodyparser.json);
app.use(bodyparser.urlencoded({extended: false}));
5.7.6 自定义中间件
const expresss = require('express')
const app = expresss();
const qs = require('querystring')

app.use((req, res, next) => {
    // 定义一个str字符串,专门用来存储客户端发送过来的请求数据
    let str = '';
    req.on('data', (chunk) => {
        str += chunk;
    })
    req.on('end', () => {
        const body = qs.parse(str);
        req.body = body;
        next();
    })
});

app.post('/user', (req, res) => {
    console.log(req.method + "," + req.url);
    res.send(req.body);
})

6. 跨域资源共享

6.1 使用CORS跨域资源共享

CORS (Cross-Origin Resource Sharing,跨域资源共享)由一系列HTTP响应头组成,这些HTTP响应头决定浏览器是否阻止前端JS代码跨域获取资源。

浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了CORS相关的HTTP响应头,就可以解除浏览器端的跨域访问限制。

安装cors:npm i cors

const cors = require('cors')
app.use(cors) // 在路由之前注册跨域中间件
6.2 CORS的注意事项

① CORS主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了CORS的接口。
② CORS在浏览器中有兼容性。只有支持XMLHttpRequest Level2的浏览器,才能正常访问开启了CORS的服务端接口(例如: IE10+、 Chrome4+、FireFox3.5+)

6.3 CORS响应头
6.3.1 Access-Control-Allow-Origin

Access-Control-Allow-0rigin: | *
origin参数的值指定了允许访问该资源的外域URL。
通配符*,表示允许来自任何域的请求。

6.3.2 Access-Control-Allow-Headers

默认情况下,CORS仅支持客户端向服务器发送如下的9个请求头:
Accept.、Accept Language、Content-Language、 DPR、 Downlink. Save-Data、 Viewport-Width.、Width、Content- Type (值仅限于text/plain、multiprt/form-data、 application/x-www-form-urlencoded三者之一)
如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过Access-Control-Allow-Headers对额外的请求头进行声明,否则这次请求会失败!

6.3.3 Access-Control-Allow-Methods

默认情况下,CORS仅支持客户端发起GET、POST、 HEAD请求。
如果客户端希望通过PUT、DELETE 等方式请求服务器的资源,则需要在服务器端,通过Access-Control-Alow-Methods 来指明实际请求所允许使用的HTTP方法。

6.4 CORS请求的分类
6.4.1 简单请求

同时满足以下两大条件的请求,就属于简单请求:
① 请求方式: GET、 POST、 HEAD三者之一
② HTTP头部信息不超过以下九种字段:无自定义头部字段、Accept.、Accept-Language、 Content-Language、 DPR、Downlink、Save -Data、Viewport-Width、 Width、Content- Type (只有三个值pplication/x www-form-urlencoded、multipart/form-data、 text/plain)

6.4.2 预检请求

只要符合以下任何一个条件的请求,都需要进行预检请求:
① 请求方式为 GET、POST、HEAD之外的请求Method类型
② 请求头中包含自定义头部字段
③ 向服务器发送 了application/jison 格式的数据
在浏览器与服务器正式通信之前,浏览器会先发送OPTION请求进行预检,以获知服务器是否允许该实际请求,所以这一次的OPTION请求称为"预检请求"。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。

简单请求的特点:客户端与服务器之间只会发生一次请求。
预检请求的特点:客户端与服务器之间会发生两次请求,OPTION预检请求成功之后,才会发起真正的请求。

7. JSONP接口

浏览器端通过script标签的src属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做JSONP.
① JSONP 不属于真正的Ajax请求,因为它没有使用XMLHttpRequest这个对象。
② JSONP仅支持GET请求,不支持POST、 PUT、 DELETE等请求。

如果项目中已经配置了CORS跨域资源共享,为了防止冲突,必须在配置CORS中间件之前声明JSONP的接口。否则JSONP接口会被处理成开启了CORS的接口。示例代码如下:

7.1.1 使用JSONP接口的步骤

① 获取客户端发送过来的回调函数的名字
② 得到要通过JSONP形式发送给客户端的数据
③ 根据前两步得到的数据,拼接出一个函数调用的字符串
④ 把上一步拼接得到的字符串,响应给客户端的script标签进行解析执行

在这里插入图片描述

const cors = require('cors')
app.use(cors)

在网页中使用jQuery发起JSONP请求
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值