likes
comments
collection
share

前端全栈框架 - Express 路由中间件详解 - 《手把手带你从零开始学全栈》

作者站长头像
站长
· 阅读数 19

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

前面说过,当请求到路由的时候会进入路由处理方法中,而路由处理方法本质上就是一个中间件,它包括3个参数,分别为:

  • 请求对象 Request
  • 返回对象 Response
  • 下一步方法 next

1. 请求对象 Request

下面介绍一下请求对象 Request 的常用属性

1-1. Request.url 属性:获取请求地址

Request.url 属性是获取请求地址的属性;看看示例,添加一个/abcd的路由:

// 定义一个GET请求“/abcd”的路由
router.get('/abcd', function (req, res, next) {
  console.log(req.url);                   // 打印Request.url属性值
  res.render('index', { title: 'Express' });
});

在浏览器中请求 http://localhost:3000/abcd 时,终端就会打印 “/abcd” ,对应的就是请求地址;还可以定义一个多层级的路由:

router.get('/abcd/efg', function (req, res, next) {
  console.log(req.url);
  res.render('index', { title: 'Express' });
});

这个时候,终端就会打印“/abcd/efg”,依旧是对应请求地址

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

在url后面加入一些参数看看:

router.get('/abcd/efg? name=jim&age=25', function (req, res, next) {
  console.log(req.url);
  res.render('index', { title: 'Express' });
});

控制台打印的结果是“/abcd/efg? name=jim&age=25”

另外,在请求的时候还可以这样传入参数:

router.get('/book/:id', function (req, res, next) {
  console.log(req.url);
  res.render('index', { title: 'Express' });
});

这里的“:id”代表着请求的时候,这里可以传入一个id字段,即 http://localhost:3000/book/2 ,这时控制台打印的结果是“/book/2”

1-2. Request.query 属性:获取GET请求参数

Request.query 属性常用来获取 GET 请求参数,它是一个对象,包含路由中每个查询字符串参数的属性。如果没有查询字符串,则为空对象 {}

在路由的url中添加一个参数id=15:

// 定义一个GET请求“/book”的路由
router.get('/book', function (req, res, next) {
  console.log(req.query);                          // 打印GET请求参数
  res.render('index', { title: 'Express' });
});

在浏览器中打开 http://localhost:3000/book?id=15 ,控制台打印结果为“{id:15}”

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

🔔 小提示

不能在路由中将请求地址定义成“/book? id=15”,因为这样它会解析成其他的字符串,而给不出你想要的结果


再向路由中添加两个参数:author=jim=time=2015-05-04

在浏览器中打开 http://localhost:3000/book?id=15&author=jim&time=2015-05-04 ,控制台打印的结果为“{ id: '15', author: 'jim', time: '2015-05-04' }”


🔔 小提示

Request.query 只能获得GET请求方式,或者拼接在url后面的参数,不能获取其他请求方式(POST、PUT等)的参数


1-3. Request.body属性:获取POST请求参数

介绍完获取GET请求方式的参数之后,再来介绍另外一个常用的请求方式POST参数的获取方法

和获取GET参数方式一样简单,Express已经将POST请求参数封装在了Request.body对象中,它同样是以键值对的形式存在,方便得到处理

定义一个POST请求的路由,增加路由的代码如下:

// 定义一个POST请求“/abc”的路由
router.post('/abc', function (req, res, next) {
  console.log(req.body);
  res.render('index', { title: 'Express' });        
});

因为POST请求不能直接在浏览器中请求,所以需要使用接口测试工具;在这里推荐使用 Postman汉化中文版 工具,读者可以自行搜索、安装,这里就不赘述了

安装完成之后,打开 Postman,点击新增,界面如图所示

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

在URL输入栏中输入地址 http://localhost:3000/abc ,将前面的请求方式改成POST,接着单击后面的发送按钮,界面如下图所示

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

为了便于查看,可以将获取的参数直接打印到返回值里;更改路由代码:

// 定义一个POST请求“/abc”的路由
router.post('/abc', function (req, res, next) {
  console.log(req.body);
  // 将请求的POST数据返回
  res.send(req.body);
});

再次单击发送按钮发送请求,返回一个空对象,如下图所示

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

上面的代码中,res.send()方法不会渲染页面,而会直接输出传入的参数,以方便查看

返回空对象是因为没有传入任何参数,现在来增加一些POST参数,Postman增加POST参数的方法是在Body中添加字段和值

如下图所示,当选择Postman中的Body选项卡时,会发现里面提供了很多选项,但最常用的是www-form-urlencoded,因为这是HTTP的POST请求的默认请求数据格式,通常情况下不会更改

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

在Body中添加一些字段后再来查看结果

如下图所示,在Body中添加了一些参数之后,在下面的返回结果中已经得到了对应的数据

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

1-4. Request.params属性:获取URL中的自定义参数

在上面的小节中定义过这样的路由:

// 定义一个GET请求
router.get('/book/:id', function(req, res, next) {
  console.log (req.url);                           
  res.render('index', { title: 'Express' });
});

使用Postman发送请求 http://localhost:3000/book/2 时,可以看到控制台打印出了“/book/2”,也就是说上面定义的这个id变成了请求地址中的2;在这种情况下,其实是可以获取到这个id值的,Express提供了获取这个id的方法,就是Request.params属性

在上面定义的路由中打印Request.params属性:

// 定义一个GET请求
router.get('/book/:id', function (req, res, next) {
  res.send(req.params);                             
});

这时再次发送请求 http://localhost:3000/book/2 ,可以看到返回结果是“{id :2}”

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

还可以定义多个参数,将路由代码更改如下:

// 定义一个GET请求
router.get('/book/:userId/:id', function (req, res, next) {
  // 将Request.params值返回
  res.send(req.params);
});

再次通过Postman发送请求 http://localhost:3000/book/2/3 ,可以看到返回结果中有多个自定义的URL参数,如下图所示

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

Express把通过URL传入的参数存到了Request.params属性中,同时它又是一个对象,包含所有自定义的URL参数,可以很轻松地获取到任意一个参数

1-5. Request.headers属性:获取请求头数据

除了可以获取到请求体的数据之外,Express还能获取到请求头的数据,它们被保存在Request.headers属性中

更改路由代码:

// 定义一个POST请求“/abc”的路由
router.post('/abc', function (req, res, next) {
  res.send(req.headers);
});

接着在Postman中发送请求,查看结果;如下图所示,返回了很多数据,这些数据都是在Postman中默认添加的;请求头中还可以添加一些自定义参数

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

如下图所示,在请求头中添加了cookietoken字段,在返回结果中也获取到了相应的值

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

1-6. Request.cookies属性:获取客户端cookie

在和前端数据交互的时候,有时需要将数据存放在客户端的cookie中,在客户端再次发送请求的时候,后端可以拿到cookie中的值来做一些操作

上一节提到,从Request.headers中可以获取到cookie,但是获取过来的是字符串,并不太容易操作;Express提供了一种更简单的方式,它将cookie信息保存在了Request.cookies属性中;如果请求不包含cookie,则默认为{}


🔔 小提示

客户端的cookie是存在于请求头里面的,而并不在请求体中,使用Request.cookies能够获取到cookie,是因为Express做了处理,所以在设置的时候需要到请求的Header中去设置


将路由代码更改如下:

// 定义一个POST请求“/abc”的路由
router.post('/abc', function (req, res, next) {
  res.send(req.cookies);
});

接着在Postman中添加一个cookie,发送请求,查看结果;如下图所示,很轻松地就获取到了客户端请求所带的cookie,并且它很智能地将多个cookie值分开了,变成Request.cookie对象的一个属性

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》


2. 返回对象 Response

有请求就有返回,介绍完请求Request对象,接下来介绍返回Response对象

2-1. Response.render()方法:渲染页面

Response.render()方法是渲染页面的一个方法,它有3个参数,如下表所示

参数参数类型是否必选作用
viewString页面文件,用于渲染文件路径
localsObject属性定义页面的局部变量
callbackFunction回调函数;返回可能的错误和呈现的字符串,但不执行自动响应;发生错误时,该方法在 next(err)内部调用

下面是相关的示例代码

// 渲染一个页面文件到客户端
res.render('index');                       
// 回调函数,明确指定发送HTML字符串
res.render('index', function (err, html) {
  res.send(html);
});
// 设置一个局部变量,渲染到user页面上
res.render('user', {
  name: 'Tobi'
}, function (err, html) {
  // 渲染完毕的回调函数
});

2-2. Response.send()方法:发送HTTP响应

Response.send()方法是发送一个HTTP响应至前端,它只接收一个参数,这个参数可以是任何类型,可以是一个Buffer对象、一个String、一个Object,或一个Array;相关示例代码如下:

res.send(new Buffer('hello'));
res.send({ name: 'john' });
res.send('<p>html</p>');
res.send([1,2,3]);
res.send('some string');

Response.send()方法之所以可以接收任何类型的参数,是因为执行这个方法返回的时候它会自动设置响应头数据类型,即响应头里的Content-Type字段

(1)当参数是Buffer对象时,Response.send()方法将Content-Type响应头字段设置为application/octet-stream

// 返回一个buffer 
res.send(new Buffer('<p>html</p>'));

在Postman中查看请求,会发现返回的响应头中Content-Type字段值为application/octet-stream

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

(2)当参数为String时,Response.send()方法将Content-Type设置为text/html

// 返回一个字符串
res.send('<p>some html</p>'); 

(3)当参数是Array或Object时,Express以JSON表示响应,设置Content-Typeapplication/json

// 返回一个对象
res.send({ name: 'jim' }); 
// 返回一个数组
res.send([1,2,3]); 

具体返回结果大家可以自己在Postman里查看一下,这里就不再演示了

2-3. Response.json()方法:返回JSON格式的数据

除了使用模板页面返回HTML页面之外,返回JSON格式的数据也是目前开发人员常做的事,尤其是在目前流行前后端分离开发方式的形势下,学习怎么返回JSON格式的数据显得尤为重要

在Express中,返回JSON格式的数据也特别简单,使用Response.json()方法就能轻松地将封装好的数据通过JSON的方式返回给前端;定义一个路由,代码如下:

// 定义一个GET请求“/book”的路由
router.get('/book', function (req, res, next) {
  // 返回JSON格式的数据
  res.json({
    name: 'john',
    age: 28,
    hobby: ['打篮球', '唱歌’', '旅游']
  })
});

在Postman中查看结果,如下图所示

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

Response.json()方法只接收一个参数,可以是任何的JSON格式类型,包括对象、数组、字符串、布尔值或数字,甚至可以将其他值转换为JSON格式类型,例如null和undefined(尽管这些格式类型在技术上是无效的JSON)

// JSON格式返回null
res.json(null);
// JSON格式返回一个对象                          
res.json({ user: 'tobi' });
// 设定HTTP状态码为500并返回JSON格式数据
res.status(500).json({ error: 'message' });

2-4. Response.status()方法:设定HTTP状态码

有时候需要给前端返回指定的HTTP状态码,让前端更能明确地知道本次请求的状态;使用Express提供的Response.status()方法可以轻松地做到,定义路由代码如下:

// 定义一个GET请求“/book”路由
router.get('/book', function (req, res, next) {
  res.status(403).end();
});

在Postman中预览,效果如下图所示;在标注框中可以看出本次请求返回的状态码是403

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

在控制台中也可以看到打印日志:

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》


🔔 小提示

在使用Response.status()方法时,后面一定要有结束方法end()或者发送方法send()json()等,因为Response.status()方法并不是返回结果,它只是设置了一个状态


还可以定义状态码之后继续返回结果;定义路由代码如下:

// 定义一个GET请求“/book”的路由
router.get('/book', function (req, res, next) {
  // 定义一个404状态码,并以JSON格式返回
  res.status(404).json({
    statusCode: 404,
    msg: 'Not Found'
  })
});

在Postman中预览,效果如下图所示;可以看到不但改变了HTTP状态码,而且返回了JSON格式的数据

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

2-5. Response.redirect()方法:跳转指定路由

在实际开发过程中,经常需要跳转URL;Express提供了很好的跳转方法Response.redirect(),使用该方法可以很轻松地跳转到指定的路由

定义路由文件代码如下:

// 定义一个GET请求“/book”的路由
router.get('/book', function (req, res, next) {
  console.log('book');
  // 跳转到“/book2”路由
  res.redirect('/book2');
});

// 定义一个GET请求“/book2”的路由
router.get('/book2', function (req, res, next) {
  console.log('book2');
  // 直接结束
  res.end();
});

接着用浏览器或者Postman发送请求 http://localhost:3000/book ,会看到在控制台中输出如下:

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

当后端接收到请求的时候,首先进入“/book”的路由方法中打印book,接着再进入“/book2”的路由方法里打印book2,这其中发生了一次302跳转,这都是通过Response. redirect()方法完成的

除了可以跳转到本地路径外,还可以跳转到任意一个URL,例如:

router.get('/book', function (req, res, next) {
  console.log('book');
  res.redirect('http://www.baidu.com');
});

打开浏览器,访问 http://localhost:3000/book ,会发现浏览器自动跳转到了 www.baidu.com

此外,Response.redirect()方法还提供了设置HTTP状态码的参数;示例如下:

// 定义一个GET请求“/book”的路由
router.get('/book', function (req, res, next) {
  console.log('book');
  // 301跳转到“/book2”路由
  res.redirect(301, '/book2');
});

// 定义一个GET请求“/book2”的路由
router.get('/book2', function (req, res, next) {
  console.log('book2');
  // 直接结束
  res.end();
});

访问 http://localhost:3000/book ,在控制台中可以看到:

前端全栈框架 -  Express 路由中间件详解 - 《手把手带你从零开始学全栈》

请求被301重定向到了“/book2”路由