Node.js零基础入门教程(第3章)-Express

在这里插入图片描述

1. 初始Express

1.1 Express 简介

在这里插入图片描述
Express的中文官网:link

在这里插入图片描述

在这里插入图片描述

1.2 Express 的基本使用

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
代码如下:

// 1. 导入 express
const express = require('express')
// 2. 创建 web 服务器
const app = express()

// 4. 监听客户端的 GET 和 POST 请求,并向客户端响应具体的内容
app.get('/user', (req, res) => {
    // 调用 express 提供的 res.send() 方法,向客户端响应一个 JSON 对象
    res.send({ name: 'theshy', age: 20, gender: '男'})
})
app.post('/user', (req, res) => {
    // 调用 express 提供的 res.send() 方法,向客户端响应一个 文本字符串
    res.send('请求成功!')
})

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

演示:(验证服务器是否可以反应)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

演示:
在这里插入图片描述

综合代码如下:

// 1. 导入 express
const express = require('express')
// 2. 创建 web 服务器
const app = express()

// 4. 监听客户端的 GET 和 POST 请求,并向客户端响应具体的内容
app.get('/user', (req, res) => {
    // 调用 express 提供的 res.send() 方法,向客户端响应一个 JSON 对象
    res.send({ name: 'theshy', age: 20, gender: '男'})
})
app.post('/user', (req, res) => {
    // 调用 express 提供的 res.send() 方法,向客户端响应一个 文本字符串
    res.send('请求成功!')
})

app.get('/', (req, res) => {
    // 通过 req.query 可以获取到客户端发送过来的 查询参数
    // 注意:默认情况下,req.query 是一个空对象
    console.log(req.query)
    res.send(req.query)
})

// 注意:这里的 :id 是一个动态的参数
app.get('/user/:id', (req, res) => {
    // req.params 是动态匹配到的 URL 参数,默认也是一个空对象
    console.log(req.params)
    res.send(req.params)
})

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

1.3 托管静态资源

在这里插入图片描述

演示:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

演示:(express.static()函数会按代码顺序来查找所需文件)
情况1:按此代码,浏览器打开是clock文件夹下的index.html文件,因为clock的代码排在前面,优先查找了clock文件夹里的index.html文件。
在这里插入图片描述
在这里插入图片描述
情况2:调换顺序,把files文件夹代码放到上面后,同样的地址,浏览器打开是files文件夹下的index.html文件。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

演示:给files文件夹挂在路径前缀,这样默认index.html地址(http://127.0.0.1:880/index.html)就会跳转到clock(时钟案例)的index.html,而只有在index.html前面加上files路径前缀(http://127.0.0.1:880/files/index.html)才会跳到files文件夹里的index.html(显示abc)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.4 nodemon(工具)

在这里插入图片描述
nodemon链接:link
有了nodemon这个工具,就不需要在每次修改代码之后,繁琐地关闭再重启服务器了。以后启动服务器文件使用nodemon + js文件而不再是node + js文件
在这里插入图片描述

在这里插入图片描述

演示:
使用nodemon启动服务器,它将监听代码的变化,具有自动重启更新项目的效果。
在这里插入图片描述


2. Express路由

2.1 路由的概念

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

METHOD: 请求的类型
PATH: 请求的 URL 地址
HANDLER: 处理函数

在这里插入图片描述

在这里插入图片描述

2.2 路由的使用

在这里插入图片描述
值得一提的是,实际开发中并不会把路由挂载在app上,因为随着代码量的增长,会挂载越来越多的路由,文件的体积会越来越大并且不方便管理。

演示:
先进行初始化操作npm init -y,之后在当前项目文件夹下安装express(版本为4.17.1)
在这里插入图片描述
在这里插入图片描述
编写完app代码后启动服务器,使用Postman进行测试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

// 这是路由模块,这样别人require(./03-router.js)得到的就是这个路由对象,可以直接使用
// 1. 导入 express
const express = require ('express')
// 2. 创建路由对象
const router = express.Router()

// 3. 挂载具体的路由
router.get('/user/list', () => {
    res.send('Get user list.')
})
router.post('/user/add', (req, res) => {
    res.send('Add new user.')
})

// 4. 向外导出路由对象
module.exports = router

在这里插入图片描述

演示:
(03-router.js是自己定义好的路由模块,可以在02-模块化路由.js中拿来使用)
在这里插入图片描述
在这里插入图片描述
测试:
nodemon运行文件启动服务器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

演示:
在这里插入图片描述
在这里插入图片描述
测试:
添加前缀之后,以后访问都需要/user/list或/user/add都需要在/前面加api了。
在这里插入图片描述
在这里插入图片描述


3. Express中间件

3.1 中间件的概念

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.2 Express中间件的初体验

3.2.1 定义中间件函数

在这里插入图片描述

演示:
在这里插入图片描述

3.2.2 全局生效的中间件

在这里插入图片描述

演示:
先处理唯一的中间件函数mw,处理完就通过next流转给下一个中间件,但是没有下一个中间件了,顺延给路由,调用路由。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2.3 定义全局中间件的简化形式

在这里插入图片描述

轻松改写:
在这里插入图片描述

3.2.4 中间件的作用

在这里插入图片描述

演示:
想在每个中间件里添加一个获取请求到达服务器时间的功能,但是给每个中间件这样添加很麻烦,可以直接在上游的中间件中添加自定义的方法
在这里插入图片描述
修改后:(使用中间件共享req的特性)
在这里插入图片描述

3.2.5 定义多个全局中间件

在这里插入图片描述

3.2.6 局部生效的中间件

在这里插入图片描述

演示:
访问http://127.0.0.1:880/因为路由调用了mw1中间件所以终端会打印文字调用了局部生效的中间件,而访问http://127.0.0.1:880/user时因为其没有调用mw1,所以不会调用中间件mw1
在这里插入图片描述
在这里插入图片描述

3.2.7 定义多个局部中间件

在这里插入图片描述

演示:
在这里插入图片描述
Postman访问地址1:
在这里插入图片描述
终端结果1:
在这里插入图片描述
Postman访问地址2:
在这里插入图片描述
终端结果2:
因为/user没有调用中间件,所以终端不会执行中间件函数(不会打印结果)
在这里插入图片描述

3.2.8 了解中间件的5个使用注意事项

在这里插入图片描述
关于第一点有一个例外,即:如果是错误级别的中间件,那必须注册在所有路由之后

3.3 中间件的分类

在这里插入图片描述

3.3.1 应用级别的中间件

在这里插入图片描述

3.3.2 路由级别的中间件

在这里插入图片描述

3.3.3 错误级别的中间件

没有错误级别的中间件时:
在这里插入图片描述
终端和Postman都会崩溃报错:(所以定义错误级别中间件防止崩溃时是很有必要的
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
注意:错误级别的中间件必须注册在所有路由之后,否则项目会崩溃

定义错误级别中间件之后:(成功防止了异常崩溃的情况)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3.4 Express内置的中间件

在这里插入图片描述
express.static中间件没有兼容性,在任何版本中都能使用

新知识:(解释以下操作)
通过Post的方式,请求http://127.0.0.1:880/user这个地址,通过body方式发送JSON格式的请求体数据
在这里插入图片描述

(express.json中间体的使用)演示
关键就是app.use(express.json())这个中间件起到了解析数据的作用
有这个中间件才能解析客户端发送过来的请求数据
在这里插入图片描述
在这里插入图片描述
成功拿到请求体数据{name: 'theshy', age: 20}
在这里插入图片描述


(express.urlencoded中间体的使用)演示如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
点击Send之后,终端结果如下:
在这里插入图片描述

3.3.5 第三方的中间件

在这里插入图片描述
body-parser中间件的注册方法跟express.urlencoded近似,因为express.urlencoded是基于它封装出来的

演示:(body-parser中间件的使用)
在这里插入图片描述
在这里插入图片描述
终端结果:
在这里插入图片描述

3.4 自定义中间件

在这里插入图片描述
说明

  1. 触发了req的data事件,就说明有数据被提交到服务器了。
  2. 触发了req的end事件,就说明数据已经发送完毕了,我们在服务器端已经完整地接收到了post提交到服务器的表单数据。
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
封装前的完整代码:

// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 导入 Node.js 内置的 querystring 模块
const newQs = require('querystring')

// 这是解析表单数据的中间件
app.use(function(req, res, next){
    // 定义中间件具体的业务逻辑
    // 1. 定义一个 str 字符串,专门用来存储客户端发送过来的请求体数据
    let str = ''
    // 2. 监听 req 的 data 事件
    req.on('data', (chunk) => {
        // 拼接请求体数据
        str += chunk
    })
    // 3. 监听 req 的 end 事件
    req.on('end', () => {
        // 在 str 中存放的是完整的请求体数据
        // console.log(str)
        // TODO: 把字符串格式的请求体数据,解析成对象格式
        const body = newQs.parse(str)
        // 挂载为自定义属性,供下游使用
        req.body = body
        next()
    })
})

app.post('/user', (req, res) => {
    // req.body能在Postman中成功反应,说明下游可以使用req.body,自定义属性挂载成功了
    res.send(req.body)
})

// 启动服务器
app.listen(880, function() {
    console.log('Express server running at http://127.0.0.1')
})

在这里插入图片描述

演示:
封装的独立模块
在这里插入图片描述
使用前面封装好的独立模块进行处理
在这里插入图片描述
结果:
在这里插入图片描述


4. 使用Express写接口

4.1 创建基本的服务器

在这里插入图片描述

4.2 创建 API 路由模块

在这里插入图片描述

演示:( 4.3 编写GET接口 开始,演示代码是在以下两个代码的基础上改进的)
在这里插入图片描述
在这里插入图片描述

4.3 编写 GET 接口

在这里插入图片描述

演示:
在这里插入图片描述
在这里插入图片描述

4.4 编写 POST 接口

在这里插入图片描述

演示:
在这里插入图片描述
在这里插入图片描述
结果:
在这里插入图片描述

4.5 CORS 跨域资源共享

在这里插入图片描述

在这里插入图片描述

演示:(由于我们有 GET 和 POST请求,得选 CORS 解决方案来处理接口的跨域问题)
staticfile.org中复制箭头所指地址到html文件中导入
在这里插入图片描述
(复制文件地址,从CDN中载入jQuery。)在html文件中使用
这个演示需要两个文件,一个是如下的js文件负责开启服务器和配置中间件,一个是html文件负责验证我们解决了接口的跨域问题。
这里因为我的80端口被占用了,用的是880端口,使用时特别注意一下。(刚学的时候被这个小问题卡了半天

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
默认情况下,网页可以跨域请求,但是无法拿到请求回来的数据。
在这里插入图片描述

4.5.5 CORS 响应头部 - Access-Control-Allow-Origin

在这里插入图片描述

在这里插入图片描述

4.5.6 CORS 响应头部 - Access-Control-Allow-Headers

在这里插入图片描述

4.5.7 CORS 响应头部 - Access-Control-Allow-Methods

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

演示:
在这里插入图片描述
在这里插入图片描述
用火狐浏览器打开html文件,点击GET按钮,发送一次请求。而点击DELETE按钮,是发送两次请求(第一次是预检请求,预检成功之后才会发第二次,第二次是真正的请求)。
在这里插入图片描述

在这里插入图片描述

4.6 JSONP 接口

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
演示:(JSONP
html文件中的改动:(设置JSONP按钮,同时为其绑定点击事件处理函数)
注意method: 'GET'dataType: 'jsonp'都是很重要的,同时满足才能发起真正的JSONP请求
在这里插入图片描述

网页html文件的完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
    <button id="btnGET">GET</button>
    <button id="btnPOST">POST</button>
    <button id="btnDELETE">DELETE</button>
    <button id="btnJSONP">JSONP</button>

    <script>
        $(function () {
            // 1. 测试 GET 接口
            $('#btnGET').on('click', function() {
                $.ajax({
                    type: 'GET',
                    url: 'http://127.0.0.1:880/api/get',
                    data: { name: 'theshy', age: 22 },
                    success: function (res) {
                        console.log(res)
                    },
                })
            })
            // 2. 测试 POST 接口
            $('#btnPOST').on('click', function() {
                $.ajax({
                    type: 'POST',
                    url: 'http://127.0.0.1:880/api/post',
                    data: { bookname: '水浒传', author: '施耐庵' },
                    success: function (res) {
                        console.log(res)
                    },
                })
            })
            // 3. 为删除按钮绑定点击事件处理函数
            $('#btnDELETE').on('click', function() {
                $.ajax({
                    type: 'DELETE',
                    url: 'http://127.0.0.1:880/api/delete',
                    data: { name: 'theshy', age: 22 },
                    success: function (res) {
                        console.log(res)
                    },
                })
            })

            // 4. 为 JSONP 按钮绑定点击事件处理函数
            $('#btnJSONP').on('click', function(){
                $.ajax({
                    method: 'GET',
                    url: 'http://127.0.0.1:880/api/jsonp',
                    dataType: 'jsonp',  // 表示要发起 JSONP 请求
                    success: function (res) {
                        console.log(res)
                    }
                })
            })
        })
    </script>
</body>
</html>

服务器js文件中的改动:(配置 JSONP 的接口)
在这里插入图片描述

服务器js文件具体代码如下:

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

// 配置解析表单数据的中间件
app.use(express.urlencoded({ extended: false }))

// 必须在配置 cors 中间件之前,配置 JSONP 的接口
// 在jsonp前加/api是因为它没有在路由中进行统一注册,需要手动加一个/api
app.get('/api/jsonp', (req, res) => {
    // TODO: 定义 JSONP 接口具体的实现过程
    // 1. 得到函数的名称
    const funcName = req.query.callback
    // 2. 定义要发送到客户端的数据对象
    const data = { name: 'theshy', age: 22}
    // 3. 拼接出一个函数的调用
    const scriptStr = `${funcName}(${JSON.stringify(data)})`
    // 4. 把拼接的字符串,响应给客户端
    res.send(scriptStr)
})

// 一定要在路由之前,配置 cors 这个中间件,从而解决接口跨域的问题
const cors = require('cors')
app.use(cors())

// 导入路由模块
const router = require('./15-apiRouter')
// 把路由模块,注册到 app 上
app.use('/api', router)

// 启动服务器
app.listen(880, function() {
    console.log('Express server running at http://127.0.0.1')
})

检验结果:(在火狐浏览器运行html文件)
点击 JSONP 按钮,控制台中成功打印出数据。运行成功!说明我们写的 JSONP 接口确实可以正常工作。

在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值