IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> day4 Express -> 正文阅读

[JavaScript知识库]day4 Express

作者:token punctuation

day4 Express

1、初识Express

  1. 什么是Express

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

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

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

    Express的中文官网:http://www.expressjs.com.cn/

  2. Express能做什么

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

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

    使用Express都可以快速创建

  3. Express的基本使用
    1. 在项目根目录中,运行下面的命令,即可将express安装到项目中使用:

      npm i express@4.17.1
      
    2. 创建基本的Web服务器

      
      
    3. 监听GET请求

      • 通过app.get()方法,可以监听客户端的GET侵权没具体语法如下:

        // 参数一:客户端请求的URL地址
        // 参数二:请求对应的处理函数
        // req:请求对象(包含了与请求相关的属性和方法)
        // res:响应对象(包含了与响应相关的属性和方法)
        app.get('请求URL',function(req,res) => {
        	/*
        		处理函数
        	*/
        })
        
    4. 监听post请求

      通过app.post()方法,可以监听客户端的GET侵权没具体语法如下:

      app.post('请求URL'function(req,res) => {
      	/*处理函数*/
      })
      
    5. 获取URL中携带的查询参数

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

      app.get('/',(req,res) => {
      	// req.query默认是一个空对象
      	// 客户端使用 ?name=zs&age=12 这种查询字符串=形式,发送到服务器的参数
      	// 可以通过 req.query对象访问到
      	console.log(req.query)
          res.send(req.query)
      });
      
    6. 获取URL中的动态参数

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

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

      也可以是两个参数,只要命名合理合法就行

    7. express.static()

      express提供了一个非常好用的函数,叫做 express.static(),通过它,我们就可以非常方便地创建一个静态资源服务器

      app.use(express.static('public'));
      

      注意:Express在指定的静态目录中查找文件,并对外提供资源发访问路径,因此,存放静态文件的目录名不会出现在URL中

    8. 托管多个静态资源目录

      请使用 express.static()函数:

      app.use(express.static('public'));
      app.use(express.static('files'));
      

      访问静态资源文件时,express.static()函数会根据目录的添加顺序查找所需的文件

    9. 挂载路径前缀

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

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

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

    10. nodemon

      • 安装nodemon
        npm install -g nodemo
        
      • 使用 nodemon

        当基于Node.js编写一个网站应用的时候,传统的方式是运行 node app.js 命令,来启动项目。这样做的坏处是:代码被修改之后,需要手动启动项目

        现在,我们可以将node命令替换为nodemon命令,使用 nodemon app.js 来启动项目,这样做的好处是:代码被修改之后,会被 nodemon 监听到,从而实现自动启动项目的效果

        node app.js
        // 改为下面的方式
        nodemo app.js
        

2、Express路由

  1. express中的路由

    在Express中,路由指的是客户端请求与服务器处理函数之间的映射关系

    由三部分组成:请求的类型、请求的URL地址、处理函数

    app.METHOD(PATH,HANDLER)
    

    路由案例

    // 监听客户端的get和post请求,并相应具体的内容
    app.get('/',(req,res) => {
        res.send('Hello World');
    });
    app.post('/',(req,res) => {
        res.send('GET a POST request');
    });
    
  2. 路由的匹配过程

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

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

  3. 最简单的用法

    在Express中使用路由最简单的方式,就是把路由挂载到app上:

    const express = require('express');
    
    const app = express();
    
    // 挂载路由
    app.get('/',(req,res) => {
        res.send("Get Hello World");
    });
    
    app.post('/',(req,res) => {
        res.send("Post Hello World");
    });
    
    app.listen(8080,() => {
        console.log("http://127.0.0.1:8080");
    });
    
  4. 模块化路由

    为了方便路由进行模块化的管理,Express不建议路由直接挂载到app上,而是推荐将路由抽离为单独的模块

    将路由抽离为单独模块的步骤如下:

    1. 创建路由对应的js文件
    2. 调用express.Router()函数创建路由对象
    3. 向路由对象上挂载具体的路由
    4. 使用 module.exports向外共享路由对象
    5. 使用app.use()函数注册路由模块
    创建路由模块
    // 这是路由模块
    
    // 导入 express
    const express = require('express');
    
    // 创建路由对象
    const Router = express.Router();
    
    // 具体的路由
    Router.get('/user/list',(req,res) => {
        res.send("Get user list");
    });
    
    Router.post('/user/add',(req,res) => {
        res.send("add new user");
    });
    
    // 向外导出对象
    module.exports = Router;
    
  5. 注册路由模块
    const express = require('express');
    
    const app = express();
    
    // app.use(express.static('./files'))
    
    // 导入路由模块
    const router = require('./03、router');
    
    // 注册路由模块
    app.use(router)
    // 注意:app.use()函数的作用,就是来注册全局中间件的
    
    app.listen(8080,() => {
        console.log("http://127.0.0.1:8080");
    });
    
  6. 为路由添加访问前缀

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

    // 导入路由模块
    const router = require('./03、router');
    
    // 注册路由模块
    app.use('/api',router)
    // 注意:app.use()函数的作用,就是来注册全局中间件的
    

3、Express中间件

1、初始中间件

  1. Express中间件的调用流程

    当一个请求到达Express的服务器之后,可以连续多个中间件,从而对这次请求进行预处理

  2. Express中间件的格式

    Express的中间件,本质上就是一个function处理函数,Express中间件的格式如下:

    app.get('/',function(req,res,next) => {
    	next();
    });
    

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

  3. next 函数的作用

    next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由

  4. 定义中间件函数
    const express = require('express');
    
    const app = express();
    
    // 定义一个简单的中间件函数
    const num = function(req,res,next){
        console.log("这是最简单的中间件函数");
        // 把流转关系,转交给下一个中间件或路由
        next();
    }
    
    app.listen(8080,() => {
        console.log("http://127.0.0.1:8080");
    });
    
  5. 全局生效的中间件

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

    通过调用 app.use(中间件函数),即可定义一个全局生效的中间件

    // 定义一个简单的中间件函数
    const nw = function(req,res,next){
        console.log("这是最简单的中间件函数");
        // 把流转关系,转交给下一个中间件或路由
        next();
    }
    
    // 全局生效的中间件
    app.use(nw);
    
  6. 定义全局中间件的简化形式
    // 这是定义全局中间件的简化形式
    app.use((req,res,next) =>{
        console.log("这是最简单的中间件函数");
        // 把流转关系,转交给下一个中间件或路由
        next();
    });
    
  7. 中间件的作用

    多个中间件治安,共享同一份req和res,基于这样的特性,我们可以在上游的中间件中,统一为req或res对象添加自定义的属性或方法,供下游的中间件或路由进行使用

    const express = require('express');
    
    const app = express();
    
    // 这是定义全局中间件的简化形式
    app.use((req,res,next) =>{
        // 系统时间
        const time = Date.now();
        // 为req对象,挂载自定义属性,从而把时间共享给后面的所有路由
        req.startTime = time;
        next();
    });
    
    app.get('/',(req,res) => {
        res.send('Home page'+ req.startTime);
    });
    app.get('/user',(req,res) => {
        res.send('User page'+req.startTime);
    });
    
    app.listen(8080,() => {
        console.log("http://127.0.0.1:8080");
    });
    
  8. 定义多个全局中间件

    可以使用app.user() 连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用

    const express = require('express');
    
    const app = express();
    
    // 定义第一个全局中间件
    app.use((req,res,next) => {
        console.log("定义了第一个全局中间件");
        next();
    });
    // 定义第二个全中间件
    app.use((req,res,next) => {
        console.log("定义了第二个全局中间件");
        next();
    });
    // 定义一个路由
    app.get('/user',(req,res) =>{
        res.send('user page');
    });
    
    app.listen(801,() =>{
        console.log("http://127.0.0.1:801");
    });
    /* 终端输出
    定义了第一个全局中间件
    定义了第二个全局中间件
    */
    
  9. 局部生效的中间件

    不使用 app.use() 定义的中间件,叫做局部生效的中间件

    const express = require('express');
    
    const app = express();
    
    // 定义中间件函数
    const nw1 = (req,res,next) => {
        console.log('调用了局部生效的中间件');
        next();
    }
    // 创建路由
    app.get('/',nw1,(req,res) => {
        res.send('Home page'); // 页面输出
        // 终端输出 调用了局部生效的中间件
    });
    app.get('/user',(req,res) => {
        res.send('user page');
    });
    
    app.listen(801,() =>{
        console.log("http://127.0.0.1:801");
    });
    
  10. 定义多个局部中间件

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

    // 定义中间件函数
    const nw1 = (req,res,next) => {
        console.log('调用了第一个局部生效的中间件');
        next();
    }
    const nw2 = (req,res,next) => {
        console.log('调用了第二个局部生效的中间件');
        next();
    }
    // 创建路由
    app.get('/',nw1,nw2,(req,res) => {
        res.send('Home page'); // 页面输出
        // 终端输出 调用了局部生效的中间件
    });
    app.get('/user',(req,res) => {
        res.send('user page');
    });
    
  11. 中间件的五个使用注意事项
    • 一定要在路由之前注册中间件
    • 客户端发送过来的请求,可以连续调用多个中间件进行处理
    • 执行完中间件的业务代码之后,不要忘记调用 next() 函数
    • 为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
    • 连续调用多个中间件,多个中间件之间,共享req和res对象

2、中间件的分类

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

  1. 应用级别的中间件

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

  2. 路由级别的中间件

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

  3. 错误级别的中间件

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

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

    const express = require('express');
    const app = express();
    // 定义路由
    app.get('/',function(req,res) {
        // 人为的制造错误
        throw new Error("服务器内部出现了错误");
        res.send('Home page');
    });
    // 定义错误级别中间件,铺货整个项目的异常错误
    app.use((err,req,res,next) => {
        console.log("发送错误:" + err.message);
        res.send("Errow:"+ err.message);
    });
    app.listen(801,() => {
        console.log("http:127.0.0.1:801");
    });
    
  4. Express内置的中间件

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

    1. express.static 快速托管静态资源的内置中间件,例如:HTML文件、图片、CSS样式(无兼容性)

    2. express.json 解析JSON格式的请求体数据(有兼容性,仅在4.16.0+版本)

    3. express.urlencoded 解析 URL-encode 格式的请求体数据(有兼容性,上同)

    4. 使用Postman请求发送json

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1uago89l-1632108276186)(image\1、请求json.png)]

      const express = require('express');
      const app = express();
      
      // 注意:处理错误级别的中间件,其他的中间件,必须在路由之前进行配置
      app.use(express.json());
      
      // 路由配置
      app.post('/user',(req,res) => {
          // 在服务器,可以使用 req.body这个属性,来接受客户端发送过来的请求体数据
          console.log(req.body); // { name: 'zs', age: 20 }
          // 默认情况下,如果不配置解析表单数据中间件,则req.body默认等于undefined
          res.send('ok');
      });
      
      app.listen(801,() => {
          console.log("http://127.0.0.1:801");
      });
      
    5. 使用Postman请求form-urlencoded

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yFU3Zzo2-1632108276188)(image\2、请求form-urlencoded.png)]

      const express = require('express');
      const app = express();
      
      // 注意:处理错误级别的中间件,其他的中间件,必须在路由之前进行配置
      app.use(express.json());
      app.use(express.urlencoded());
      
      // 路由配置
      app.post('/user',(req,res) => {
          // 在服务器,可以使用 req.body这个属性,来接受客户端发送过来的请求体数据
          console.log(req.body); // { name: 'zs', age: 20 }
          // 默认情况下,如果不配置解析表单数据中间件,则req.body默认等于undefined
          res.send('ok');
      });
      
      app.post('/book',(req,res) => {
          // 在服务器端,可以通过req.body 来获取 json 格式的表单数据和 url-encoded格式数据
          console.log(req.body); // { bookName: '水浒传', author: '施耐庵' }
          res.send('ok');
      });
      
      app.listen(801,() => {
          console.log("http://127.0.0.1:801");
      });
      
  5. 第三方的中间件

    按需求下载并配置第三方中间件,从而提高开发效率

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

在这里插入图片描述

const express = require('express');
const app = express();

// 导入解析表单的中间件
const parser = require('body-parser');
// 使用 app.use() 注册中间件
app.use(parser.urlencoded({extended:false}));

// 路由
app.post('/user',(req,res) => {
    // 如果没有配置任何表单数据,默认等于 空
    console.log(req.body);
    // [Object: null prototype] { name: 'zs', age: '15', gender: '男' }
    res.send('ok');
});

app.listen(801,()=>{
    console.log("http://127.0.0.1:801");
});

注意: Express内置的express.urlencoded中间件,就是基于body-parser这个第三方中间件进一步开发出来的

4、自定义中间件

  1. 描述与实现步骤

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iB5GNgyH-1632108276191)(image\3、第三方中间件.png)]

    自己手动模拟一个类似于 express.urlendcoden 这样的中间件,来解析POST提交到服务器的表单数据

    实现步骤:

    1. 定义中间件

    2. 监听req的data事件

      数据量较大无法一次性发送完毕,客户端会把数据切割后,分批发送到服务区。所以data会触发多次,没触发异常,获取到数据只是完整数据的一部分,需要手动接收的数据进行拼接

      // 2、监听 req的data事件    // 定义一个 str 字符串,专门用来存储客户端发送过来的全球通    let str = "";    // 监听 req 的data 事件    req.on('data', (chunk) => {        str += chunk;    });
      
    3. 监听req的end事件

       // 3、监听req的 red 事件    req.on('end', () => {        console.log(str);        // name=zs&age=15&gender=%E7%94%B7        // 1000:把字符串格式的请求体数据,解析成对象格式    });
      
    4. 使用 querystring 模拟解析请求体数据

      Node.js内置了一个querystring模块,专门用来处理查询字符串。通过这个模块提供的parse()函数,可以轻松把查询字符串解析成对象格式

      // 导入node内置的querystring模块const qs = require('querystring');// 3、监听req的 red 事件    req.on('end', () => {        // console.log(str);        // name=zs&age=15&gender=%E7%94%B7        // 1000:把字符串格式的请求体数据,解析成对象格式        const body =  qs.parse(str);        console.log(body);        // [Object: null prototype] { name: 'zs', age: '15', gender: '男' }    });
      
    5. 将解析出来的数据对象挂载为 req.body

      上游的中间件和下游的中间件及路由之间,共享同一份req和res,因此可以将解析出来的数据,挂载为req的自定义属性,命名为req.body,供下游使用

      // 3、监听req的 red 事件    req.on('end', () => {        // console.log(str);        // name=zs&age=15&gender=%E7%94%B7        // 1000:把字符串格式的请求体数据,解析成对象格式        const body =  qs.parse(str);        // console.log(body);        // [Object: null prototype] { name: 'zs', age: '15', gender: '男' }        req.body = body;        naxt();    });
      
    6. 将自定义中间件封装为模块

      封装为独立的模块

      创建custon-body-parse.js文件

      // 导入node内置的querystring模块
      const qs = require('querystring');
      
      const bodyParser = (req, res, naxt) => {
          // 定义中间件具体的业务逻辑
          // 2、监听 req的data事件
          // 定义一个 str 字符串,专门用来存储客户端发送过来的全球通
          let str = "";
          // 监听 req 的data 事件
          req.on('data', (chunk) => {
              str += chunk;
          });
      
          // 3、监听req的 red 事件
          req.on('end', () => {
              // console.log(str);
              // name=zs&age=15&gender=%E7%94%B7
              // 1000:把字符串格式的请求体数据,解析成对象格式
              const body =  qs.parse(str);
              // console.log(body);
              // [Object: null prototype] { name: 'zs', age: '15', gender: '男' }
              req.body = body;
              naxt();
          });
      }
      
      module.exports = bodyParser;
      

      对自定义模块进行拆分

      const express = require('express');
      const app = express();
      // 导入node内置的querystring模块
      const qs = require('querystring');
      
      // 1、导入自己封装的中间件模块
      const customBodyParser = require('./14、custon-body-parse');
      app.use(customBodyParser);
      
      
      
      // 定义路由
      app.post('/user', (req, res) => {
          res.send(req.body);
      });
      
      app.listen(801, () => {
          console.log('http://127.0.0.1:801');
      });
      

5、使用Express写接口

  1. 创建基本的服务器
    // 导入 express
    const e = require('express');
    const express = require('express');
    // 创建服务器
    const app = express();
    
    // 启动服务器
    app.listen(801,() => {
        console.log("http://127.0.0.1:801");
    });
    
  2. 创建API路由模块
    const express = require('express');
    
    const rounter = express.Router();
    
    // 在这里挂载对应的路由
    
    
    module.exports = rounter;
    
  3. 编写GET接口
    // 在这里挂载对应的路由
    rounter.get('/get',(req,res) => {
        // 通过req.query获取客户端通过查询字符串,发送到服务器的数据
        const query = req.query;
        // 调用 res.send()方法,向客户端响应处理结果
        res.send({
            status:0, // 0表示成功
            msg:"GET请求成功", // 状态描述
            data:query // 客户端响应的数据
        });
    });
    
  4. 编写POST接口
    rounter.post('/post',(req,res) => {
        // 通过req.bodu获取请求体中包含的url-encoded格式的数据,必须配置一个中间件来解析表单的请求体
        const body = req.body;
        res.send({
            status:0,
            msg:'POST请求成功',
            data:body
        });
    });
    
接口的代码部分

15、使用Express编写接口

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

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

// 导入路由模块
const rounter = require('./16、APIRouder');
// 把路由模块注册到app上
app.use('/api',rounter);

// 启动服务器
app.listen(801,() => {
    console.log("http://127.0.0.1:801");
});

16、APIRouder

const express = require('express');

const rounter = express.Router();

// 在这里挂载对应的路由
rounter.get('/get',(req,res) => {
    // 通过req.query获取客户端通过查询字符串,发送到服务器的数据
    const query = req.query;
    // 调用 res.send()方法,向客户端响应处理结果
    res.send({
        status:0, // 0表示成功
        msg:"GET请求成功", // 状态描述
        data:query // 客户端响应的数据
    });
});

rounter.post('/post',(req,res) => {
    // 通过req.bodu获取请求体中包含的url-encoded格式的数据,必须配置一个中间件来解析表单的请求体
    const body = req.body;
    res.send({
        status:0,
        msg:'POST请求成功',
        data:body
    });
});

module.exports = rounter;
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-20 15:42:12  更:2021-09-20 15:43:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 18:54:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码