Node.js教程-express框架

概述

Express是基于Node.js平台(建立在Node.js内置的http模块上),快速、开放、极简的Web开发框架
中文官网 http://www.expressjs.com.cn/。
Github地址:https://github.com/orgs/expressjs。

Express核心特性:

  • 可设置中间件来响应 HTTP 请求
  • 定义了路由表用于执行不同的 HTTP 请求
  • 可通过向模板传递参数来动态渲染 HTML 页面

安装

npm i express

以上命令会将express安装在当前目录下的node_modules文件夹下,并且将其依赖的包也一并下载下来
以下几个和express搭配使用的包:

  • body-parser 用于处理 JSONRawTextURL中的请求数据
  • cookie-parser 用于处理Cookie
  • multer 用于处理**enctyoe=“multipart/form-data””**的表单数据

基本使用

基本使用步骤:

  1. 导入 express 模块
  2. 创建 express 实例
  3. 创建并启动HTTP服务
  4. 绑定请求事件
// 1. 导入 express 包
const express = require('express')

// 2. 创建 express 实例
const app = express()

// 3. 启动服务
app.listen(80, () => {
  console.log("Express server is starting ...")
})

// 4. 绑定请求事件
app.get("/", (req, res) => {
  console.log("请求进来了 >>> " + req.url)
  res.end("Hello Node.js")
})

set 方法

set方法用于指定变量的值

// 设置 端口
app.set("port", process.env.PORT)

// 设定views变量,意为视图存放的目录
app.set('views', path.join(__dirname, 'views'));

// 设定view engine变量,意为网页模板引擎
app.set('view engine', 'jade');

请求和响应

Express处理请求中回调函数的参数:requestresponse对象来处理请求和响应。

request 对象

request对象表示 HTTP请求,包含了请求查询的字符串参数内容HTTP头部等属性。常见属性:

  • request.appcallback为外部文件时,用其访问express实例
  • request.baseUrl 获取当前的 URL 路径
  • request.method 获取请求方法
  • request.body 获取请求体内容
  • request.cookie 获取 Cookie 内容
  • request.hostname 获取主机名
  • request.ip 获取IP
  • request.originalUrl 获取原始请求 URL
  • request.params 获取请求参数(动态匹配的参数)
  • request.path 获取请求路径
  • request.protocol 获取请求协议
  • request.query 获取URL的查询参数
  • request.route 获取请求匹配的路由
  • request.get() 获取指定的请求头
  • request.is() 判断请求头Content-TypeMIME类型
// http://domain:port/x1/x2/wz?age=18
request.path  // /x1/x2/wz
request.params  // wz
request.query  // age
// 引入express 模块
const express = require('express')

// 创建 实例
const app = express()

// 启动服务
app.listen(80, () => {
  console.log("Server is starting ...")
})

// 绑定 get 请求事件
app.get('/user', (req, res) => {
  // req.protocol 获取请求协议
  console.log("protocol >>> ", req.protocol)
  // req.method 获取请求方法
  console.log("method >>> ", req.method)
  // req.hostname 获取主机名
  console.log("hostname >>> ", req.hostname)
  // req.ip 获取请求 IP
  console.log("ip >>> ", req.ip)
  // req.originalUrl 获取请求原始路径
  console.log("originalUrl >>> ", req.originalUrl)
  // req.path 获取请求路径
  console.log("path >>> ", req.path)
  // req.route 获取请求路由
  console.log("route >>> ", req.route)
  // req.params 获取请求参数
  console.log("params >>> ", req.params)
  // req.query 获取请求查询参数
  console.log("query >>> ", req.query)
  // req.body 获取请求体
  console.log("body >>> ", req.body)

  res.end("GET")
})

// 绑定 post 请求事件
app.post('/user', (req, res) => {
  // req.protocol 获取请求协议
  console.log("protocol >>> ", req.protocol)
  // req.method 获取请求方法
  console.log("method >>> ", req.method)
  // req.hostname 获取主机名
  console.log("hostname >>> ", req.hostname)
  // req.ip 获取请求 IP
  console.log("ip >>> ", req.ip)
  // req.originalUrl 获取请求原始路径
  console.log("originalUrl >>> ", req.originalUrl)
  // req.path 获取请求路径
  console.log("path >>> ", req.path)
  // req.route 获取请求路由
  console.log("route >>> ", req.route)
  // req.params 获取请求参数
  console.log("params >>> ", req.params)
  // req.query 获取请求查询参数
  console.log("query >>> ", req.query)
  // req.body 获取请求体
  console.log("body >>> ", req.body)

  res.end("POST")
})

response 对象

response 对象表示 HTTP响应,即在接受到请求时向客户端发送的数据。常见属性:

  • response.appcallback为外部文件时,用其访问express实例
  • response.cookie(name, value[, options]) 设置Cookie信息
  • response.clearCookie() 清空Cookie
  • response.download() 传送指定的文件
  • response.get() 获取指定的HTTP头信息
  • response.set(name, value) 设置响应头(Header)
  • response.json() 响应JSON格式的数据
  • response.render(view[, locals], callback) 渲染网页模版
  • response.send() 发送响应
  • response.sendFile(path[, options][, fn]) 传送文件
  • response.status() 设置 HTTP 状态码
  • response.type() 设置 Content-TypeMIME类型
  • response.redirect() 设置重定向

路由

路由即路径映射。在Express中,路由指客户端的请求与服务器处理函数的映射。
Express中路由是一个单独的组件Express.Router
Express中路由由三部分组成,分别为请求类型请求URL处理函数。其格式如下:

app.method(path, handler())

路由匹配过程

  • 请求到达服务器时,先经过路由的匹配,匹配成功了,才会调用对应的处理函数
  • 在匹配时,按照定义的顺序依次匹配,仅当请求类型和请求URL同时匹配成功了,才会调用对应的处理函数

Node.js教程-express框架_第1张图片

// 导入 express 模块
const express = require('express')

// 创建 express 实例
const app = express()

// 创建路由实例
const router = express.Router()

// 挂载路由
router.get('/user', (req, res) => {
  res.send("express router")
})

// 注册路由
app.use('/api', router)

// 启动服务
app.listen(80, () => {
  console.log("Server is starting ...")
})

// 访问路径 http://domain:port/api/user

中间件

中间件(Middleware)指业务流程的中间处理环节。其是一个函数,包含了requestrespoonsenext三个参数,其中 next() 把流转交给下一个中间件或路由。

Express 中间件调用流程
Node.js教程-express框架_第2张图片
注意:

  1. 在注册路由之前注册中间件(错误中间件除外)
  2. 多个中间件共享requestresponse对象
  3. next() 函数后不能再写逻辑代码

全局中间件

通过app.use()注册的中间件为全局中间件

const express = require('express')

const app = express()

// 注册全局中间件
app.use((req, res, next) => {
	console.log("中间件A")
})

// 注册全局中间件
app.use((req, res, next) => {
	console.log("中间件B")
})

app.get('/user', (req, res) => {
	res.send("ok")
})

app.listen(8888)

局部中间件

const express = require('express')

const app = express()

// 定义中间件
const mw1 = (req, res, next) => {
	console.log("中间件A")
}

// 注册全局中间件
const mw2 = (req, res, next) => {
	console.log("中间件B")
}

app.get('/user', mw1, mw2, (req, res) => {
	res.send("ok")
})

app.post('/user', [mw1, mw2], (req, res) => {
	res.send("ok")
})

app.listen(8888)

中间件分类

中间件按照作用可划分为三类:应用级别中间件路由级别中间件错误级别中间件

应用级别中间件

通过app.use()app.method()注册,即绑定到app实例上的中间件即为应用级别中间件。(其中methodgetpostputdelete等请求方法)

const express = require('express')

const app = express()

// 注册路由
app.use('/', (req, res, next) => {
	next()
})
路由级别中间件

通过router.use()注册,即绑定到router实例上的中间件即为路由级别中间件

const express = require('express')

const app = express()
const router = express.Router()

// 路由上注册中间件
router.use((req, res, next) => {
	next()
})

// 注册路由
app.use('/', router)
错误级别中间件

错误级别中间件用来捕获整个项目中发生的异常,从而防止项目异常崩溃。
错误级别中间件的处理函数中必须有4个形参,即(error, request, response, next)
错误级别中间件必须注册在所有路由之后

const express = require('express')

const app = express()

// 请求处理 ...

// 注册错误中间件
app.use((err, req, res, next) => {
	next()
})

内置中间件

Express中内置了多个中间件,极大的提高了 Express 项目的开发效率。常见内置中间件:

  • express.static 快速托管静态资源

    express.static(root[, options])

  • express.json 解析JSON格式的请求体数据

  • express.urlencoded 解析 url-encoded 格式的请求体数据

// 快速托管静态资源
app.use(express.static(path))

// 通过 express.json() 这个中间件,解析表单中的 JSON 格式的数据
app.use(express.json())

// 通过 express.urlencoded() 这个中间件,来解析表单中的 url-encoded 格式的数据
app.use(express.urlencoded({ extended: false }))

第三方中间件

cookie-parser

cookie-parser 用于处理请求中的Cookie
https://github.com/expressjs/cookie-parser

设置Cookie

res.cookie(name, value[, options])

参数说明

  • name cookie名称
  • value cookie值
  • options 配置参数
    • domain 域名。默认为当前域名
    • expires 失效时间。未设置或0,表示浏览器关闭后即失效
    • maxAge 最大失效时间(指从当前时间开始多久后失效),单位毫秒
    • securetrue时,cookie 在 http 失效,https 生效
    • path cookie在什么路径下有效。默认为**/**
    • httpOnly 只能被访问,防止 XSS攻击
    • signed 是否签名。默认指为false

不签名实例

const express = require('express')
const cookieParser = require('cookie-parser')

// 创建 app 实例
const app = express()

// 注册 Cookie中间件
app.use(cookieParse())

app.get('/setCookie', (req, res) => {
	res.cookie('name', '张三', {
		maxAge: 10000
	})
	res.send('cookie set success!')
})

app.listen(8888)

签名实例

const express = require('express')
const cookieParser = require('cookie-parser')

const app = express()

app.use(cookieParser('^123$'))  // ^123$ 为签名秘钥

app.get('setCookie', (req, res) => {
    // 将cookie的name 进行签名
	res.cookie("name", "张三", {maxAge: 100000, signed: true})
})

获取Cookie

注意:Cookie签名与不签名获取的方式不一样。req.cookies获取不签名cookiereq.signedCookies获取签名cookie
不签名实例

const express = require('express')
const cookieParser = require('cookie-parser')

// 创建 app 实例
const app = express()

// 注册 Cookie中间件
app.use(cookieParser())  //

app.get('/getCookie', (req, res) => {
	console.log(req.cookies)
	res.send("cookie got")
})

app.listen(8888)

签名实例

const express = require('express')
const cookieParser = require('cookie-parser')

// 创建 app 实例
const app = express()

// 注册 Cookie中间件
app.use(cookieParser('^123$'))  // ^123$ 为签名秘钥

app.get('/getCookie', (req, res) => {
	console.log(req.signedCookies)
	res.send("cookie got")
})

app.listen(8888)
删除Cookie

res.clearCookie(name[, options])

express-session

express-session用于处理请求中的会话。
https://github.com/expressjs/session

配置 session

session(options)

参数说明:

  • options 配置参数
    • cookie cookie设置
    • genid sessionid算法。默认为uid-safe库自动生成id
    • name 会话名称。默认为 connect.sid
    • secret 会话签名秘钥
    • store 会话存储方式。默认为内存
    • resave 是否强制保存会话,及时未被修改也被保存。默认为true
    • saveUninitialized 强制将未初始化的会话保存至存储中。(会话是新的且未被修改即为未初始化)
    • unset 是否保存会话。默认为keep,不保存可设置为destory
const express = require('express')
const session = require('express-session')

const app = express()

app.use(session({
	name: "session-cookie",
	secret: "^123456$",  // 会话签名秘钥
	cookie: {
		maxAge: 2 * 60 * 60 * 1000
	}
}))

req.session

req.session可用于存储或访问会话数据,以JSON的形式序列化。

const express = require('express')
const session = require('express-session')

// 创建服务实例
const app = express()

// 配置session,并注册session中间件
app.use(session({
  name: "express",
  secret: "^123456$",
  resave: false,
  saveUninitialized: true
}))

app.get('/setSession', (req, res) => {
  // 存储会话
  req.session.name = "李四"
  res.send("set session success")
})

app.get('/getSession', (req, res) => {
  // 获取会话
  console.log(req.session)
  res.send("session got")
})


// 启动服务
app.listen(8888)
属性
属性 说明
req.session.id 会话ID
req.session.sessionID 会话ID
req.session.cookie 获取会话中的 cookie 对象, 而后可对其修改
req.session.cookie.maxAge 会话有效剩余时长
req.session.cookie.originalMaxAge 返回会话 cookie 的原始 maxAge, 以毫秒为单位
方法
方法 说明
req.session.regenerate(callback) 重新生成会话
req.session.destroy(callback) 销毁会话并取消设置 req.session 属性
req.session.reload(callback) 从存储重新加载会话数据并重新填充 req.session 对象
req.session.save(callback) 讲会话保存至 store,用内存中的内容替换 store上的内容
req.session.touch() 更新 .maxAge属性
JWT

JWT(JSON Web Token)是由三部分组成:HeaderPayload(真正的用户信息,加密后的字符串)、Signature
JWT工作原理:用户的信息以Token的字符串的形式,保存在客户端中。用户每次请求,将Token存放在请求头Authorization上,服务器拿到该值后进行解析处理。
Node.js教程-express框架_第3张图片
Expressjsonwebtoken模块用于生成JWT字符串,express-jwt用于将JWT字符串还原成JSON对象。

使用
  1. 安装模块
    npm install jsonwebtoken express-jwt
    
  2. 引入模块
    const jwt = requre('jsonwebtoken')
    const expressJWT = require('express-jwt')
    
  3. 生成 JWT 字符串

    jwt.sign(payload, secret[, options[, callback]])

    payload 存储的对象
    secret 签名秘钥
    options 配置参数。常见有 expiresIn(过期时间)、algorithm(签名算法)
    callback 回调函数

    app.post('/api/login', (req, res) => {
    	let token = jwt.sign({username: username}, '^123456$', {expireIn: '2h'})
    })
    
  4. 还原 JWT 字符串
    // 此处的 secret 值必须和jwt 生成时所使用的秘钥相同
    // unless 指定了哪些接口无须携带Token访问
    app.use(expressJWT({secret: '^123456$'}).unless({path:[/^\/api\//]}))
    
  5. 获取 JWT 信息

    在访问权限的接口中,可通过req.user对象即可访问 JWT 字符串中解析的内容

  6. 捕获 JWT 异常
    // 通过异常中间件来处理JWT解析失败
    app.use((err, req, res, next) => {
    	if(err.name === 'UnauthorizedError') {
    	  // TODO
    	}
    	next()
    })
    
multer

multer是用于处理multipart/form-data类型的表单数据,主要用于上传文件。(不会处理任何非 multipart/form-data 的数据 )
multer在解析完请求体后,会向request对象上添加一个body对象和一个filefiles对象。body对应表单中提交的文本字段,filefiles包含了表单上传的文件。
https://github.com/expressjs/multer

multer(options)

参数说明:

  • options 参数配置
    • dest / storage 上传文件存放目录。
    • fileFilter 文件过滤器
    • limits 限制上传文件 (可有效防止Dos攻击)
      • fieldNameSize field名字最大长度。默认为 100 bytes
      • fieldSize field指最大长度。默认为1MB
      • fields 非文件field的最大数量。默认为无限
      • fileSize 文件最大长度,单位字节。默认为无限
      • files 文件最大数量。默认为无限
      • parts part传输的最大数量(field + file)。默认为无限
      • headerPairs 键值对最大组数。默认为2000
    • preservePath 保存包含文件名的完整路径
storage

storage为存储引擎,multer中具有DiskStorageMemoryStorage和第三方等引擎。

DiskStorage

DiskStorage为磁盘存储引擎,其有两个选项可用:destinationfilename
destination 用来确定上传的文件存放的位置。可提供一个 stringfunction。若没有设置则使用操作系统默认的临时文件夹。
注意:destination 是一个function,则需用手动创建文件夹;若destination 是一个string,multer 会自动创建。
filename用来确定文件夹中文件名。若未设置该参数,则文件将设置一个随机文件名且没有后缀名。

const storage = multer.DiskStorage({
	distination: function(req, file, cb) {
		cb(null, '/xxx/xxx')
	}
	filename: function(req, file, cb) {
		cb(null, file.fieldname + "_" + Date.now())
	}
})

const upload = multer({storage: storage})
MemoryStorage

MemoryStorage 为内层存储引擎(将内容存储在Buffer中)

const storage = multer.memoryStorage()
const upload = multer({storage: storage})

注意:当使用内层存储,上传文件非常大,或上传文件非常多时,可能会导致内层溢出。

方法

multer.single(fieldname)
multer.signle()接受一个以filename命名的文件,文件保存至request.file
multer.array(fieldname[, maxCount])
multer.array() 接受一个以fieldname命名的文件数组,可配置maxCount来限制上传文件数量,文件保存至request.files
multer.fields(fields)
multer.fields()接受fileds的混合文件,文件保存至request.files
multer.none()
multer.none() 只接受文本域,和multer.fields([])效果一样。若该模式有文件上传,则抛出LIMIT_UNEXPECTED_FILE
multer.any()
multer.any() 接受一切上传的文件。文件保存至request.files

const multer = require('multer')

// 存储设置
const storage = multer.DiskStorage({
	distination: function(req, file, cp) {
		cp(null, '/xxx/xx')
	}
	filename: function(req, file, cp)
})

const upload = multer({storage:storage})

app.post('/upload/photo', upload.single('avatar'), function (req, res) {
  // req.file 是 `avatar` 文件的信息
  // req.body 将具有文本域数据,如果存在的话
})

app.post('/upload/file', upload.array('file', 3), function (req, res) {
  // req.files 是 `file` 文件组的信息
  // req.body 将具有文本域数据,如果存在的话
})

app.post('/upload', upload.fields([{name: 'avatar', maxCount: 1},{name: 'file', maxCount: 3}]), function (req, res) {
  // req.files 是一个对象 (String -> Array) 键是文件名,值是文件数组
  // 	req.files['avatar'][0] -> File
  //    req.files['file'] -> Array
  // req.body 将具有文本域数据,如果存在的话
})
文件属性
属性 说明
fieldname 表单定义的名称
originalname 文件原始名称
encoding 文件编码
mimetype 文件的 MIME 类型
size 文件大小
distination 文件保存路径
filename 保存至 distination 中的文件名
path 已上传文件的完整路径
buffer 存放整个文件的 Buffer

自定义中间件

自定义中间件流程:

  1. 定义中间件
  2. 监听request对象的 data 事件
  3. 监听 request 对象的 end 事件
  4. 解析请求参数
  5. 封装模块

自定义中间件解析POST提交的数据

// querything 是 Node.js的内置模块
const qs = require('querything')

// 定义中间件
const bodyParser = (req, res, next) => {
	let str = ''

	// 监听 req 的 data 事件
	req.on('data', (chunk) => {
		str += chunk
	})
	
	req.on('end', () => {
		// 解析数据,并将数据放在 req 的 body 中,供下游访问
		req.body = qs.parse(str)
		next()
	})
}

module.exports = bodyParser

模板

Express模板是用于渲染视图的文件,可以包含HTMLCSSJavaScript等内容,用于构建 Web应用程序的图形界面。
使用Express模板可以快速、方便地创建Web应用程序,并可轻松地将动态数据注入到模板中,以便呈现动态效果。常见的模版引擎有:EJS、Pug、Handlebars 等。

分类

Express模板可分静态模板动态模板两类:

  1. 静态模板 预先定义好的 HTML 文件,可通过路由直接呈现
  2. 动态模板 通过模版引擎加载动态数据来生成动态内容

Express中常用的模板引擎:

  • 基于HTML的模版引擎:MustacheHandlebars
  • 基于JavaScript的模版引擎:EJSUnderscore.js
  • 基于CSS的模版引擎:LESSSASS

使用

模版使用步骤

  1. 下载模板包
  2. 配置模版引擎 app.set("view engine", "xxx")
  3. 配置模板路径 app.set("views", path.resolve(__dirname, "views")) (表示模板存放在当前目录下views文件夹中)
  4. 在请求响应中设置渲染 res.render('xx',renderDataObj)

express-generator

express-generator 是 快速创建 express 项目生成器工具。

使用

## 1. 全局安装 express-generator
npm i -g express-generator


## 2. 创建项目
#### 快速创建 [project_name[ 的项目,并且使用默认的 jade 模板引擎
express [project_name]  

#### 快速创建 [project_name[ 的项目,并且使用指定的 ejs 模板引擎
express [project_name] --view=ejs


## 3.进入到项目根目录下执行 npm install
npm install

## 4. 启动项目
#### npm 命令
npm run start   或   npm start

#### node 命令
node ./bin/www

## 5.访问 express-generator生成的项目服务默认端口为 3000 

项目结构

Node.js教程-express框架_第4张图片

你可能感兴趣的:(node.js,express)