基于Node.js-http模块的Express框架

初识Express

Express简介

官方给出的概念: Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架

通俗的理解: Express 的作用和 Node.js 内置的 http 模块类似,是专门用来创建 Web 服务器的

Express的本质:就是一个npm 上的第三方包,提供了快速创建Web 服务器的便捷方法

Express 的中文官网

Express 能做什么

对于前端程序员来说,最常见的两种服务器,分别是:

  • Web 网站服务器:专门对外提供 Web 网页资源的服务器
  • API 接口服务器:专门对外提供API 接口的服务器

使用Express,我们可以方便、快速的创建 Web 网站的服务器或API 接口的服务器

Express 基本使用

Express 安装

  1. 初始化根目录 npm init -y
  2. 安装express npm i express@4.17.1

创建基本的服务器

app.listen(端口号, 启动成功后的回调), 启动服务器

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

// 创建web服务器
const app = express()

// 调用app.listen(端口号, 启动成功后的回调), 启动服务器
app.listen(8099, function () {
    console.log('express server running at http://127.0.0.1:8099')
})

监听 get 请求

  1. 参数1: 客户端请的 URL 地址
  2. 参数2: 请求对应的处理函数
    • req: 请求对象(包含了与请求相关的属性与方法)
    • resp: 响应对象(包含了与响应相关的属性与方法)
app.get('请求URL', function(req, resp) { /*处理函数*/ })

监听 post 请求(和 get 请求类似)

把内容响应给客户端

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

app.get('/user', (req, resp) => {
    
    //向客户端发送json对象
    resp.send({name: 'xxx', age: 19})
})

app.post('/login', (req, resp) => {
    
    //向客户端发送文本内容
    resp.send('请求成功!')
})

获取 url 中携带的请求参数

通过 req.query 对象,可以访问到客户端通过查询字符串的形式,发送到服务器的参数:

req.query 默认是一个空对象

客户端使用 ?name=zs&age=20 这种查询字符串形式,发送到服务器的参数

可以通过 req.query 对象访问到,例如:

req.query.name, req.query.age

app.get('/', (req,resp) => {
    console.log(req.query)
    resp.send('请求成功')
})

获取 url 中的动态参数

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

req.params 默认为一个空对象,里面存放着通过:动态匹配到的参数值

// URL 地址中,可以通过:参数名 的形式,匹配动态参数值
app.get('/user/:id', (req, resp) => {
    console.log(req.params)
    resp.send('请求成功')
})

托管静态资源

express 提供了一个非常好用的函数,叫做 express.static(资源路径)

通过它,我们可以非常方便地创建一个静态资源服务器

例如,通过如下代码就可以将 public 目录下的图片、CSS 文件、JavaScript 文件对外开放访问了

//调用express.static()方法,快速对外提供静态资源
app.use(express.static('../../public'))

注意:
Express在指定的静态目录中查找文件,并对外提供资源的访问路径

因此,存放静态文件的目录名不会出现在 URL 中。

托管多个静态资源文件夹,就调用多个express.static(资源路径)
查找资源时,会根据文件夹的调用顺序,顺序查找

挂载路径前缀

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

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

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

安装 nodemon

在编写调试 Node.s 项目的时候,如果修改了项目的代码,则需要频繁的手动 close 掉

然后再重新启动,非常繁琐现在,我们可以使用 nodemon (https://www.npmis.com/package/nodemon) 这个具

它能够监听项目文件的变动,当代码被修改后,nodemon 会自动帮我们重启项目,极大方便了开发和调试

安装:

npm i nodemon -g

使用:

//之前:node app.js
//现在:
nodemon app.js

Express 路由

路由的简单介绍和安装

一个路由分为三部分:请求方式、请求路径、请求的回调函数
app.method('路径', function() {......})
简单举例:

app.get('/user', (req, resp) => {
    
    //向客户端发送json对象
    resp.send({name: 'xxx', age: 19})
})

app.post('/login', (req, resp) => {
    
    //向客户端发送文本内容
    resp.send('登录请求成功!')
})

路由的匹配过程

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

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

路由匹配的注意点:

  1. 按照定义的先后顺序进行匹配
  2. 请求类型和请求的 URL 同时匹配成功,才会调用对应的处理函数

路由的使用

创建路由模块
//这是路由模块
let express = require('express')  //导入express
let user = express.Router()  //创建路由对象

user.get('/user', (req, resp) => {
    resp.send('user')
})

user.get('/login', (req, resp) => {
    resp.send({username: 'jsl', password: '123'})
})

module.exports = user

注册路由模块

app.use() 函数的作用,就是用来注册全局中间件

//导入express
const express = require('express')
//创建APP对象
const app = express()
//导入user路由模块
const userRouter = require('./router/user')
//app.use()函数的作用,就是用来注册全局中间件
//使用user路由模块
app.use(userRouter)

app.listen(8099, () => {
    console.log('express server running at http://127.0.0.1:8099')
})

为路由模块添加前缀

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

const userRouter = require('./router/user')

app.use('/user', userRouter)

Express 中间件

中间件的概念

中间件的调用流程

当一个请求到达Express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理
在这里插入图片描述

Express 中间件的格式

Express 的中间件,本质上就是一个 function 处理函数,Express 中间件的格式如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zWTTfcwU-1670731370283)(img_1.png)]

注意:中间件函数的形参列表中,必须包含 next 参数。而路由处理函数中只包含 req 和res

中间件初体验

定义一个中间件函数

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

//常量mw所指向的,就是一个中间件
const mw = function (req, resp, next) {
    console.log('这是最简单的一个中间件')
    //注意:中间件业务逻辑处理完毕后,必须调用next()函数
    //表示把流转关系转交给下一个中间件或路由
    next()
}
全局生效的中间件

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

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

//常量mw所指向的,就是一个中间件
const mw = function (req, resp, next) {
    console.log('这是最简单的一个中间件')
    //注意:中间件业务逻辑处理完毕后,必须调用next()函数
    //表示把流转关系转交给下一个中间件或路由
    next()
}

// 将 mw 注册为全局生效的中间件
app.use(mw)

'......'
中间件的作用

多个中间件之间,共享同一份 req 和 res。基于这样的特性,我们可以在上游的中间件中,统一为 reg 或 res 对象添加自定义的属性或方法,供下游的中间件或路由进行使用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zbGpEq0B-1670731370284)(img_2.png)]

const express = require('express')
const moment = require('moment')
//创建APP对象
const app = express()


//简化的中间件函数
app.use((req, resp, next) => {
    //获取到请求到达服务器的时间
    const time = moment().format('YYYY-MM-DD HH:mm:ss')
    //为req对象,挂载一个自定义属性,把时间共享给后面的所有路由
    req.startTime = time
    console.log('简化的一个中间件函数')
    next()
})

app.get('/user', (req, resp) => {
    console.log('user')
    console.log(req.startTime)
    resp.send('请求成功')
})

app.get('/login', (req, resp) => {
    console.log('login')
    console.log(req.startTime)
    resp.send({username: 'jsl', password: '123'})
})

app.listen(8099, () => {
    console.log('express server running at http://127.0.0.1:8099')
})

局部中间件

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

const express = require('express')

const app = express()

const mw = (req, resp, next) => {
    console.log('局部中间件')
    next()
}

app.get('/', mw, (req, resp) => {
    resp.send('请求成功')
})

app. get('/01', (req, resp) => {
    resp.send('请求成功01')
})

app.listen(8099, () => {
    console.log('express server running at http://127.0.0.1:8099')
})

定义多个局部中间件

可以在路由中,通过如下两种等价的方式,使用多个局部中间件:

//写法1
app.get('/', mw1, mw2, (req, resp) => {
    resp.send('请求成功')
})
//写法2
app.get('/', [mw1, mw2], (req, resp) => {
    resp.send('请求成功')
})
了解中间件的5个使用注意事项
  1. 一定要在路由之前注册中间件
  2. 客户端发送过来的请求,可以连续调用多个中间件进行处理
  3. 执行完中间件的业务代码之后,不要忘记调用 next() 函数
  4. 为了防止代码逻辑混乱,调用 next() 函数后不要再写额外的代码
  5. 连续调用多个中间件时,多个中间件之间,共享 reqres 对象

中间件的分类

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

  1. 应用级别的中间件
  2. 路由级别的中间件
  3. 错误级别的中间件
  4. Express 内置的中间件
  5. 第三方的中间件
应用级别的中间件

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

// 应用级别的中间件(全局中间件)
app.use((req, res, next) => {
    next()
})
// 应用级别的中间件(局部中间件)
app.get('/', mw1, (req, res) => {
    res.send('Home page')
})
路由级别的中间件

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

//这是路由模块
let express = require('express')  //导入express
let user = express.Router()  //创建路由对象

user.get('/user', (req, resp) => {
    console.log('user')
    console.log(req.startTime)
    resp.send('请求成功')
})

user.get('/login', (req, resp) => {
    console.log('login')
    console.log(req.startTime)
    resp.send({username: 'jsl', password: '123'})
})

//对外暴露
module.exports = user


错误级别的中间件

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

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

const express = require('express')

const app = express()

app.get('/', (req, resp) => {//路由
    throw new Error('服务器内发生了错误')//抛出一个自定义的错误
    resp.send('home page')
})

app.use(function (err, req, resp, next) {//错误级别的中间件
    console.log(err.message)
    resp.send(err.message)//向客户端响应错误内容
})

app.listen(8099, () => {
    console.log('express server running at http://127.0.0.1:8099')
})

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

Express内置的中间件

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

  1. express.static 快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS 样式等(无兼容性)
  2. express.json 解析 JSON 格式的请求体数据 (有兼容性,仅在 4.16.0+ 版本中可用)
  3. express.urlencoded 解析 URL-encoded 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)
// 配置解析 application/json 格式数据的内置中间件
app.use(express.json())

// 配置解析 application/x-ww-form-urlencoded 格式数据的内置中间件
app.use(express.urlencoded({ extended: false }))
第三方的中间件

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

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

  1. 运行 npm install body-parser 安装中间件
  2. 使用 require 导入中间件
  3. app.use() 注册并使用中间件
const express = require('express')

const app = express()

// app.use(express.urlencoded({ extended: false }))
const body_parser = require('body-parser')
app.use(body_parser.urlencoded({extended: false}))

app.post('/user', (req,resp) => {
    //如果没有配置任何解析表单数据的中间件,则 req.body 默认为 undefined
    console.log(req.body)
    resp.send('ok')
})

app.listen(8099, () => {
    console.log('express server running at http://127.0.0.1:8099')
})

Express内置的 express.urlencoded 中间件,就是基于 body-parser 这个第三方中间件进一步封装出来的。

使用 Express 写接口

编写get接口

const express = require('express')
const router = express.Router()

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

module.exports = router


/*----------*/

// 导入 express
const express = require('express')
// 创建服务器实例
const app = express()

const apiRouter = require('./apiRouter')
app.use('/api', apiRouter)

// 启动服务器
app.listen(8099, () => {
    console.log('express server running at http://127.0.0.1:8099')
})

编写post接口

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

/*----------*/

// 导入 express
const express = require('express')
// 创建服务器实例
const app = express()
// 配置解析表单数据的中间件
app.use(express.urlencoded({ extended: false }))

const apiRouter = require('./apiRouter')
app.use('/api', apiRouter)

// 启动服务器
app.listen(8099, () => {
    console.log('express server running at http://127.0.0.1:8099')
})

CORS 跨域资源共享

接口的跨域问题:

上面编写的GETPOST接口,存在一个很严重的问题: 不支持跨域请求

解决接口跨域问题的方案主要有两种:

  1. CORS (主流的解决方案,推荐使用)
  2. JSONP(有缺陷的解决方案:只支持 GET 请求)
什么是 CORS

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

浏览器的同源安全策略默认会阻止网页"跨域"获取源。但如果接口服务器配置了 CORS 相关的 HTTP 响应头就可以解除浏览器端的跨域访问限制
在这里插入图片描述

使用 cors 中间件解决跨域问题

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

  1. 运行 npm install cors 安装中间件
  2. 使用 const cors = require(cors) 导入中间件
  3. 在路由之前调用 app.use(cors()) 配置中间件
cors 跨域简单请求

同时满足以下两大条件的请求,就属于简单请求:

  1. 请求方式: GETPOSTHEAD 三者之一
  2. HTTP 头部信息不超过以下几种字段: 无自定义头部字段、Accept、Accept-Language、 Content-Language、DPR、Downlink、Save-Data Viewport-Width、 WidthContent-Type (只有三个值:application/x-www-form-urlencoded、multipart/form-data、 text/plain)
cors 跨域预检请求

只要符合以下任何一个条件的请求,都需要进行预检请求:

  1. 请求方式为 GET、POST、HEAD 之外的请求 Method 类型
  2. 请求头中包含自定义头部字段
  3. 向服务器发送了 application/json 格式的数据

在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为" 预检请求 "服务器成功响应预检请求后,才会发送真正请求,并且携带真实数据

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

概念:浏览器端通过

  1. JSONP不属于真正的Ajax 请求,因为它没有使用XMLHttpRequest 这个对象
  2. JSONP 仅支持 GET 请求,不支持 POST、PUT、DELETE 等请求
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,基于Node.jsExpress框架实现上述方法,您可以按照以下步骤进行: 1. 创建Express应用程序:首先,您需要在Node.js环境下安装Express框架,然后创建一个Express应用程序。可以通过以下命令来创建: ``` mkdir myapp cd myapp npm init npm install express --save ``` 2. 设计搜索窗口:在Express应用程序中,可以通过定义路由和模板引擎等方式来设计搜索窗口。可以使用EJS、Handlebars等模板引擎,将搜索窗口的HTML代码与后台逻辑进行分离。例如,可以在`views`目录下创建一个`search.ejs`文件,用于显示搜索窗口的HTML代码。可以使用以下代码: ``` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Search Window</title> </head> <body> <form action="/search" method="get"> <input type="text" name="keyword"> <button type="submit">Search</button> </form> </body> </html> ``` 3. 实现搜索功能:在Express应用程序中,可以通过定义路由和控制器等方式来实现搜索功能。例如,在`routes`目录下创建一个`search.js`文件,用于处理搜索请求。可以使用以下代码: ``` const express = require("express"); const router = express.Router(); const db = require("../models/db"); router.get("/", (req, res) => { res.render("search"); }); router.get("/search", (req, res) => { const keyword = req.query.keyword; const results = db.search(keyword); res.render("results", { results }); }); module.exports = router; ``` 其中,`db`代表数据库模块,`search`方法用于在数据库中进行搜索,`results`表示搜索结果。 4. 显示搜索结果:在Express应用程序中,可以通过定义路由和模板引擎等方式来显示搜索结果。例如,在`views`目录下创建一个`results.ejs`文件,用于显示搜索结果的HTML代码。可以使用以下代码: ``` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Search Results</title> </head> <body> <% if (results.length === 0) { %> <p>No results found.</p> <% } else { %> <ul> <% for (let i = 0; results[i]; i++) { %> <li><%= results[i].name %></li> <% } %> </ul> <% } %> </body> </html> ``` 其中,`results`代表搜索结果。 5. 启动Express应用程序:最后,您需要在Node.js环境下启动Express应用程序,以便用户可以访问搜索窗口。可以使用以下命令来启动: ``` node app.js ``` 综上所述,基于Node.jsExpress框架实现上述方法,需要创建Express应用程序,设计搜索窗口,实现搜索功能,以及显示搜索结果。在实现过程中,需要注意路由、控制器和模板引擎等方面的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多喝热水,重启试试

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值