Node.js第六篇:Express框架

编程

1.2-什么是Express

基于 Node.js 平台,快速、开放、极简的 Web 开发框架。

Express提供了一系列强大的特性,来帮助我们创建各种web应用。

  • 提供了简洁的路由定义方式
  • 对获取HTTP请求参数进行了简化处理
  • 对模板引擎支持程度高,便于渲染动态的HTML页面
  • 提供了中间件机制有效的控制HTTP请求
  • 拥有大量第三方中间件对功能进行扩展

原生Node.js和Express框架路由对比:

原生Node.js和Exprees框架获取请求参数对比

1.3-快速入门

安装express框架

命令:npm install express --save

构建第一个基于express框架的web应用

// 导入express包

const express = require("express")

// 创建服务器对象

const app = express()

// 监听请求(网站根路径)

app.get("/", (req, res) => {

// 响应内容

// send方法自动检测并设置响应内容类型以及状态码

res.send("Hello Expreess")

})

// 设置端口

app.listen(3000, "localhost")

console.log("服务器启动成功:http://localhost:3000")

第二章:中间件

2.1-认识中间件

什么是中间件

我们开发web应用,核心操作无非就是处理请求和响应。

从请求处理开始直到响应处理结束,才是一个完整的周期。

在请求和响应之间,我们可以通过express提供的一系列方法或第三方模块进行额外的操作。

而中间件就是处理请求和响应之间的一系列方法,这些方法可以接收客户端发送的请求、可以对请求作出响应、也可以将请求继续交给下一个中间件处理。

中间件由两部分组成,中间件方法以及请求处理函数

  • 中间件方法由Express提供,负责拦截请求
  • 请求处理函数由开发人员提供,负责处理请求。

比如我们用到的路由,其实就是一个中间件(我们用到的get和post方法就是中间件方法)

体验中间件的使用

我们可以针对同一个请求,设置多个中间件进行多次处理。

默认情况下,请求从上到下依次匹配中间件,一旦匹配成功,终止匹配。

可以调用next方法将请求控制权交给下要给中间件,直到遇到结束请求的中间件。

const express = require("express")

const app = express()

// 中间件1处理请求

app.get("/user", (req, res,next) => {

req.name = "Burce"

// 调用next方法,将控制权交给下一个中间件

next()

})

// 中间件2处理请求

app.get("/user", (req, res) => {

res.send(req.name)

})

app.listen(3000, "localhost")

console.log("服务器启动成功:http://localhost:3000/user")

2.2-中间件use方法

use方法使用介绍

app.use方法可以匹配所有的请求方式(不区分get和post),也可以直接传入请求处理函数,接收所有请求

app.use((req,res,next)=>{

console.log("处理请求")

...

next()

})

app.use第一个参数也可以传入请求地址,代表不论什么请求方式,只要是这个请求地址就可以接收这个请求

app.use("请求路径",(req,res,next)=>{

console.log("处理请求")

...

next()

})

代码

const express = require("express")

const app = express()

// 【中间件a-处理所有请求】

app.use((req, res, next) => {

console.log("中间件a处理了请求")

next()

})

// 【中间b-处理/user请求-不论是get还是post】

app.use("/user", (req, res, next) => {

console.log("中间件b处理了/user请求")

next()

})

// 【中间c-处理/user请求-get请求】

app.get("/user", (req, res, next) => {

console.log("中间件c处理了/user-get请求")

res.send("ok")

})

// 【中间d-处理/user请求-get请求】

app.get("/list", (req, res, next) => {

console.log("中间件d处理了/list-get请求")

res.send("ok")

})

app.listen(3000)

在浏览器中输入地址http://localhost:3000/user发送请求

请求结果

中间件a处理了请求

中间件b处理了/user请求

中间件c处理了/user-get请求

2.3-中间件的实际应用

登录验证

比如登录验证,客户端在访问需要登录的页面时,可以先使用中间件判断用户的登录状态,如果未登录则拦截请求,直接响应,禁止用户进入需要登录的页面。

app.use("/user", (req, res, next) => {

// 模拟是否登陆状态

let isLogin = false

if (isLogin) {

next()

} else {

res.send("请先登录")

}

})

app.get("/user", (req, res, next) => {

res.send("欢迎来到user页面")

})

网站维护公告

在所有的路由最上面定义所有请求的中间件,直接为客户端做出响应,网站正在维护中

app.use((req, res, next) => {

res.send("服务器正在维护中,截止到2030年")

})

app.use("/user", (req, res, next) => {

let isLogin = true

if (isLogin) {

next()

} else {

res.send("请先登录")

}

})

app.get("/user", (req, res, next) => {

res.send("欢迎来到user页面")

})

自定义404页面

可以把接收所有请求的中间接件定义在路由最后面,当上面的路由不满足时,说明没有匹配的路由,此时可以响应页面不存在。

app.use("/user", (req, res, next) => {

let isLogin = true

if (isLogin) {

next()

} else {

res.send("请先登录")

}

})

app.get("/user", (req, res, next) => {

res.send("欢迎来到user页面")

})

app.use((req, res, next) => {

res.status(404).send("你访问的页面被外星人带走了!")

})

2.4-错误处理中间件

使用方式

在程序执行的过程中,不可避免可能会发生一些无法预料的错误,比如数据库连接失败、文件读取失败等。

而错误处理中间件是一个集中处理错误的地方。

app.use((err,req,res,next)=>{

res.status(500).send("服务器内部错误")

})

对于异步错误,调用next方法,可以将错误信息通过参数的方式传递给next()方法,即可触发错误处理中间件。

app.get("/file",(req,res,next)=>{

fs.readFile("01.txt","utf-8",(err,data)=>{

if(err) {

next(err)

}else {

res.send(data)

}

})

})

代码演示

const express = require("express")

const fs = require("fs")

const app = express()

app.use("/user", (req, res, next) => {

throw new Error("未知错误")

})

app.get("/file", (req, res, next) => {

fs.readFile("01.txt", "utf-8", (err, data) => {

if (err) {

next(err)

} else {

res.send(data)

}

})

})

app.use((err, req, res, next) => {

if (err) {

res.status(500).send(err.message)

}

})

app.listen(3000)

2.5-捕获错误

try catch介绍

在node.js中,异步ApI的错误信息都是通过回调函数获取的,支持Promise对象的异步API发送错误可以通过catch方法捕获。

异步函数执行如果发生错误要如何捕获错误呢?

try catch 可以捕获异步函数以及其他同步代码在执行过程中发生的错误,但是不能捕获其他类型的API发送的错误。

代码

const express = require("express")

const fs = require("fs")

/*默认情况下,fs.readFile方法返回的不是promise对象,所以无法使用await关键字,可以通过util模块下的promisify方法改造其他方法,使其可以使用await关键字 */

const promisify = require("util").promisify

fs.readFile = promisify(fs.readFile)

const app = express()

app.get("/file", async (req, res, next) => {

try {

const result = await fs.readFile("01.txt", "utf-8")

res.send(result)

} catch (ex) { // 捕获错误

next(ex)

}

})

app.use((err, req, res, next) => {

if (err) {

res.status(500).send(err.message)

}

})

app.listen(3000)

第三章: 模块化路由

3.1-为什么要构建模块化路由

在项目实际开发当中,我们的项目是要根据业务划分模块并且多人协同开发的,若把所有的路由都集中在一个程序文件中处理,则难以实现多人协同开发且难以维护。

3.2-如何实现模块化路由

实现方式

首先根据模块的划分,为每个模块创建独立的路由程序文件;

其次在模块中通过express的Router方法创建路由对象;

然后在模块中使用路由对象处理指定的请求;

最后,在程序入口文件中导入各个路由模块,并使用use方法挂载到web应用中。

app.use("路由名称",路由对象)

发送请求:/路由名称/请求地址

代码演示

路由模块home.js

const express = require("express")

const home = express.Router();

home.get("/index", (req, res) => {

res.send("欢迎来到home首页")

})

home.get("/list", (req, res) => {

res.send("欢迎来到home列表页")

})

module.exports = home

路由模块admin.js

const express = require("express")

const admin = express.Router();

admin.get("/index", (req, res) => {

res.send("欢迎来到admin首页")

})

admin.get("/list", (req, res) => {

res.send("欢迎来到admin列表页")

})

module.exports = admin

web应用程序入口app.js

const express = require("express")

// 导入home路由模块

const home = require("./router/home")

// 导入admin路由模块

const admin = require("./router/admin")

const app = express()

// 把home路由模块挂载到web应用中,监听/home路径下的请求

app.use("/home", home)

// 把admin路由模块挂载到web应用中,监听/admin路径下的请求

app.use("/admin", admin)

app.listen(80)

访问:例如http://localhost/admin/list

结果:欢迎来到admin列表页

第四章:请求参数

4.1-获取get请求参数

获取方式

req.query,返回值是一个对象。

express框架内部将请求参数转换为对象。

代码演示

const express = require("express")

const app = express()

app.get("/index", (req, res) => {

res.send(req.query)

})

app.listen(80)

请求:http://localhost/index?word=程序媛&gender=女

结果:{"word":"程序媛","gender":"女"}

4.2-获取post请求参数

获取方式

安装第三方模块:npm install body-parser

导入并配置body-parser模块:

const bodyParser = require("body-parser")

// 拦截所有请求

// extend: false 表示方法内部使用querystring模块处理请求参数格式

// extend: true 表示方法内部使用第三方模块qs处理请求参数格式

app.use(bodyParser.urlencoded({extend: false}))

获取参数:req.body 返回一个对象

代码演示

form表单

  <form action="http://localhost/add" method="post">

<p>账号:<input type="text" name="account"></p>

<p>密码:<input type="password" name="pwd"></p>

<p><input type="submit" value="提交"></p>

</form

服务端程序

const express = require("express")

// 导入body-parser模块

const bodyParser = require("body-parser")

const app = express()

// 配置bodyParser

app.use(bodyParser.urlencoded({extended:false}))

app.post("/add", (req, res) => {

// 获取post请求参数

res.send(req.body)

})

app.listen(80)

返回结果:{"account":"admin","pwd":"123456"}

4.3-Express中的路由参数

路由参数的定义和使用

请求路径格式: /路径名称/:参数1名称/:参数2名

调用方式:http://localhost/find/值1/值2

代码演示

const express = require("express")

const app = express()

app.get("/find/:id", (req, res) => {

res.send(req.params)

})

// 测试:http://localhost/find/1

app.get("/find/:id/:name", (req, res) => {

res.send(req.params)

})

// 测试:http://localhost/find/1/admin

app.get("/find", (req, res) => {

res.send("find")

})

// 测试:http://localhost/find

app.listen(80)

第五章:静态资源的处理

通过Express内置的express.static可以方便地托管静态文件,例如img、css、javascript文件等。

配置方式

app.use("虚拟路径",express.static("静态资源真实路径"))

虚拟路径可选

代码演示

const express = require("express")

const path = require("path")

const app = express()

const statiPath = path.join(__dirname,"./public")

// app.use(express.static(statiPath))

// 测试:http://localhost/index.html

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

// 测试:http://localhost/static/index.html

app.listen(80)

第六章:Express中使用模板引擎

为了使art-template模板引擎能够更好的和Express框架结合,模板引擎官方在原art-template模板引擎的基础上封装了express-art-template

安装模板引擎

安装命令: npm install art-template express-art-template

代码演示

app.js

const express = require("express")

const path = require("path")

const app = express()

// 多个模板使用公共数据

// app.locals.key = value

app.locals.users = [

{name:"Bruce",age: 10},

{name:"Andy",age: 20}

]

// 配置框架使用哪个模板引擎,以及处理后缀为什么的模板

app.engine("art", require("express-art-template"))

// 设置模板存放的目录

app.set("views", path.join(__dirname, "views"))

// 设置模板的默认后缀

app.set("view engine", "art")

app.get("/index", (req, res) => {

// index 模板名称 data模板中需要的数据

res.render("index", { data: "首页的数据" })

// render方法会自动匹配并响应

})

app.get("/list", (req, res) => {

res.render("list",{data:"列表页的数据"})

})

app.listen(80)

list.art

{{data}}

<ol>

{{each users}}

<li>

第{{$index+1}}个用户

<ul>

<li>name:{{$value.name}}</li>

<li>age:{{$value.age}}</li>

</ul>

</li>

{{/each}}

</ol>

index.art

{{data}}

<ol>

{{each users}}

<li>

第{{$index+1}}个用户

<ul>

<li>name:{{$value.name}}</li>

<li>age:{{$value.age}}</li>

</ul>

</li>

{{/each}}

</ol>

第七章:cookie和Session

7.1-概述

​ 众所周知,Http协议是无状态的,也就意味着,针对浏览器与服务器之间的请求和响应(也叫会话),当两者之间的会话结束时,服务器端并不会记忆客户端(浏览器)曾经访问过。

​ 但是,在实际应用程序开发中,有些业务需要浏览器和服务器之间能够保持会话。比如常见的登录业务,在同一个浏览器下,当用户第一次登录成功并进入首页时,下次再使用同一个浏览器访问首页时,则不需要再登录。而要实现下次访问不再登录时,需要让服务端能够识别曾经访问过它的浏览器,这就需要会话跟踪技术来实现。分别是cookiesession

7.2-cookie

cookie:浏览器在电脑硬盘中开辟的一块空间,主要提供服务端存储数据。

  • cookie中的数据是以域名的形式进行区分的。
  • cookie中的数据是有过期时间的,超过时间数据会被浏览器自动删除。
  • cookie中的数据会随着请求被自动发送到服务器端。

7.3-session

实际上就是一个对象,存储在服务器端的内存中,在session对象中也可以存储多条数据,每一条数据都有一个sessionid做为唯一标识。

session依赖于cookie,比如我们要实现一个邮箱和密码登录会话跟踪的功能。其实现过程如下图:

7.4-express-session

在express框架中,可以使用第三方包express-session操作session

具体代码如下:实现一个记录用户使用某个终端访问该网站的次数

// 导入express模块

const express = require("express")

// 导入express-session模块

const session = require("express-session")

// 创建服务对象

const app = express();

// session的名称

let identityKey = "skey";

//使用session

app.use(session({

name: identityKey,

secret: "appkey", // 用来对session id相关的cookie进行签名

// store: new FileStore(), // 本地存储session(文本文件,也可以选择其他store,比如redis的)

saveUninitialized: false, // 是否自动保存未初始化的会话,建议false

resave: false, // 是否每次都重新保存会话,建议false

cookie: {

maxAge: 10 * 1000 // 有效期,单位是毫秒

}

}));

// session存储数据

app.get("/", (req, res) => {

// 判断是否是第一次访问

if (req.session.count) {

req.session.count += 1;

} else {

req.session.count = 1

}

res.send("欢迎访问,您是第" + req.session.count + "此访问我们")

})

//清除session

app.get("/logout", function(req, res, next){

// 备注:这里用的 session-file-store 在destroy 方法里,并没有销毁cookie

// 所以客户端的 cookie 还是存在,导致的问题 --> 退出登陆后,服务端检测到cookie

// 然后去查找对应的 session 文件,报错

// session-file-store 本身的bug

req.session.destroy(function(err) {

if(err){

res.json({ret_code: 2, ret_msg: "退出登录失败"});

return;

}

// req.session.loginUser = null;

res.clearCookie(identityKey);

res.send("ok")

});

});

app.listen(80)

以上是 Node.js第六篇:Express框架 的全部内容, 来源链接: utcz.com/z/516363.html

回到顶部