Nodejs》》Express、中间件

发布于:2025-08-08 ⋅ 阅读:(89) ⋅ 点赞:(0)

在这里插入图片描述

原生的 Http

http原生
在这里插入图片描述

Node之 Express 框架

npm i express -g -D

在这里插入图片描述

Express

官网

Express 托管静态资源

const express = require('express');
const app = express();
const PORT = 3000;
//托管静态资源 express.static('xxx')  xxx文件夹的作为静态资源
app.use(express.static('public'))
// 比如 根目录下有个public文件夹,里面有个images、css、js  文件夹
//这样 就可以访问  http://域名(IP)/images/1.png
//这样 就可以访问  http://域名(IP)/css/style.css
//这样 就可以访问  http://域名(IP)/js/1.js
// 托管多个静态资源目录
//托管静态资源 express.static('xxx')  xxx文件夹的作为静态资源
app.use(express.static('public'))
app.use(express.static('custpublic'))
//多个静态资源目录
// 访问静态资源文件时,express.static() 函数会根据目录的 添加顺序 查找所需文件

//托管静态资源  挂载路径前缀 通常前缀跟目录名称一样  下面的xxx -》public
app.use(”xxx“,express.static('public'))
//这样  访问静态资源 需要添加 xxx 作为前缀了
//这样 就可以访问  http://域名(IP)/xxx/images/1.png
//这样 就可以访问  http://域名(IP)/xxx/css/style.css
//这样 就可以访问  http://域名(IP)/xxx/js/1.js

// 基础路由
app.get('/', (req, res) => {
  res.send('欢迎来到Express服务器!');
});

// 启动服务器
app.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
});

Express》》app.use() 函数 、中间件

在这里插入图片描述

# app.use() 方法用于指定中间件函数,其基本形式如下所示:
app.use([path], middleware)
其中,[path] 参数是可选的,代表中间件函数所处理的路径,默认为“/”。middleware 参数是中间件函数,可以是一个函数或者是一个由若干个函数组成的数组。如果 middleware 参数是数组,则每个函数都会按照在数组中的顺序依次被执行。

在这里插入图片描述

在这里插入图片描述

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

// 身份验证中间件
function authenticate(req, res, next) {
	if (req.session.user) {
	next(); // 用户已登录,继续处理请求
	} else {
	res.redirect('/login'); // 用户未登录,重定向到登录页面
	}
}
// 将身份验证中间件绑定到所有路由上
app.use(authenticate);
// 处理 GET /home 请求的路由处理器
app.get('/home', function (req, res) {
res.send('欢迎访问主页!');
});
// 处理 GET /profile 请求的路由处理器
app.get('/profile', function (req, res) {
res.send('欢迎访问个人资料页面!');
});

// 启动服务器并监听端口号3000
app.listen(3000);

在这里插入图片描述

1.托管静态资源
#  将 public 目录中的所有静态文件映射到根目录的 /public 路径下
app.use('/public', express.static(__dirname + '/public'));
2.处理Json
app.use(express.json());
# 如果要在处理 JSON 时,限制请求体的大小为 10MB,则可以使用下面的代码:
app.use(express.json({ limit: '10mb' }));
3. 处理 URL 编码数据
  app.use(express.urlencoded({ extended: false }));
4.处理错误
 # 在 Express.js 中,可以使用 app.use() 方法为应用程序添加错误处理中间件。当我们的应用程序发生了错误后,错误处理中间件将会  自动捕获此错误,并采取适当的措施进行处理。
app.use(function (err, req, res, next) {
    console.error(err.stack)
    res.status(500).send('Something broke!')
})

在这里插入图片描述
在这里插入图片描述
》》中间件的作用 路由本质上是一种特殊类型的中间件
多个中间件(含路由)之间,共享 同一份 req、res, 基于这个特性,我们可以在上游的中间件中,统一为 req 或 res 对象添加 自定义 的属性或方法,供下游 的中间件或路由 使用

// 为了方便 演示,把中间件、路由 放在同一个 js 文件下了。  实际开发 会抽离出去。
const express = require('express')
const app = express()
app.use((req,res,next)=>{
   req.x="32"
})
app.use((req,res,next)=>{
   // req 也上面的 x  属性
   req.y="123"
})
app.get('/home',(req,res)=>{
  //此时的req 就有上面自定义的 x、y的属性
})
app.listen(3000),()=>{

});

》》全局中间件 、局部中间件
1…用 app.use() 就是 全局中间件
2。不用 app.use() 就是 局部中间件

const express = require('express')
const app = express()
//定义一个中间件
const mv = (req,res,next)=>{
   req.x="32"
})
//此时mv  就是 局部中间件
// 可以在路由中 定义多个局部中间件
//app.get('/home',mv1,mv2,(req,res)=>{})
//app.get('/home',[mv1,mv2],(req,res)=>{})
app.get('/home',mv,(req,res)=>{
  
})
app.get('/about',(req,res)=>{
  
})
app.listen(3000),()=>{

});

中间件的注意事项 和 分类

中间件使用注意事项

  1. 一定要在路由之前注册中间件——》因nodejs 中间件(含路由)是自上而下的顺序执行的
  2. 客户端发来的请求,可以连续调用多个中间件 (鉴权、授权、日志等)
  3. 执行完中间件的业务代码后, 切记 不要忘记 使用 next() 函数。
  4. 为了防止代码逻辑混乱,调用 next() 函数后不要再写额外的代码
  5. 连续调用多个中间件,共享 req 和 res 对象

》》中间件的分类

// 1. 应用级别  
     //  通过app.use()、app.get()、app.post()  绑定到  app实例上的 中间件,就叫应用级别中间件 
	     app.use((req,res,next)=>{ ... next()}) 应用级别中间件(全局中间件)
	     app.get('/' , mv1,(req,res)=>{ ... }) 应用级别中间件(局部中间件)  mv1 是中间件函数
// 2. 路由级别
     // 绑定到路由实例上的中间件,叫 路由级别中间件。
         // 路由文件                
				const express = require('express')				
				const router = express.Router()	
				router.use((req,res,next)=>{
                   ...
                   next()
                })
				router.get('/xx',(req,res)=>{
				  res.send('路由模块  get')
				})
				router.post('/xx',(req,res)=>{
				    res.send('路由模块  post')
				})
				// 暴露
				module.exports=router
// 3. 错误级别    注册要在所有路由的后面
   // 专门用来捕获 整个项目 中的异常错误的,防止项目崩溃的
   // 错误中间 必须 必须 必须 有四个参数, 顺序不能改变  (err,req,res,next)
      app.get('/',(req,res)=>{
          //为了方便演示 人为抛出一个异常
          throw new Error('xxxxxx')
          res.send('nnnnnn') //因为上面异常了,此处不会执行了          
      })
      。。。。
      //错误中间件  用于捕获项目的错误、异常
      app.use((err,req,res,next)=>{
         console.log(err.message)
         res.send(err.message)
     })
// 4. Express内置
     1 express.static  托管静态资源(html文件、图片、css)无兼容性
     2 express.json    解析Json格式的  请求体数据  (有兼容性  Express版本 4.16.0+可用)
     3 express.urlencoded  解析URL-encoded 格式的  请求体数据  (有兼容性  Express版本 4.16.0+可用)
         // 配置解析  application/json 格式的请求数据    
         app.use(express.json())
         app.post('/user',(req,res)=>{
            // 在服务器,可用使用 req.body 这个属性  来接受客户端发送过来的请求数据 (JSON 格式、  url-encoded格式)
            // 默认情况下,如果不配置解析表单(app.use(express.json()))数据的中间件,则 req.body   默认等于  undefined
            console.log(req.body)
            res.send('xxx')
         })
         // 配置解析 application/x-www-form-urlencoded  格式数据 
         app.use(express.urlencoded({ extended : false }))
         app.post('/user',(req,res)=>{
            // 在服务器,可用使用 req.body 这个属性  来接受客户端发送过来的请求数据 (JSON 格式、  url-encoded格式)
            // 默认情况下,如果不配置解析表单(app.use(express.urlencoded({ extended : false })))数据的中间件,则 req.body   默认等于  undefined
            console.log(req.body)
            res.send('xxx')
         })
// 5. 第三方中间件
    // 非Express官方内置的 ,都是第三方中间件
    // 在 Express版本 4.16.0之前的版本  服务器解析 JSON、url-encoded 格式数据  需要引入 第三方中间件  即  body-parser
    //   Express版本 4.16.0之后的版本 内置的  express.urlencoded 、express.json  中间件,就是基于 body-parser 这个第三方中间件进一步封装的
       // 使用步骤 如下
           1 安装   npm i body-parser 
           2 使用   require 引入中间件
           3 调用   app.use()  注册并使用中间件
                 const bodyParser = require('body-parser')
                 app.use(bodyParser.json())
                 app.use(bodyParser.urlencoded({extended:false}))

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

Express 》》自定义中间件

在这里插入图片描述

const express = require('express');

const qs = require('querystring')

const app = express();
const PORT = 9090;
//除错误中间件要放在路由后面,其它的中间件一律要放在路由之前
// 自定义 应用级别(全局中间件)
//定义变量  ,用来存储 客户端发送过来的请求数据
let req_data=''
app.use((req,res,next)=>{
    //在中间件中,要监听 req 对象的 data 事件,来获取客户端发送到服务器的数据
    // 如果数据量比较大,无法一次性发送完毕,则客户端会数据切割后,分批发送到服务器。
    // 所以data事件可能会会触发多次,每次触发data事件时,  获取到数据只是完整数据的一部分,
    // 需要手动对接收到的数据进行拼接
    req.on('data',(chunk)=>{
      // 拼接请求体数据,隐式转换为字符串
      req_data+=chunk
    })
    // 监听 req 对象的 end 事件 (请求体发送完毕后自动触发)
    req.on('end',()=>{
        // 打印完整的请求体数据
        console.log(req_data)
        // 把字符串格式的请求体数据,解析成对象格式   JSON
        // Node.js 内置一个 querystring模块,专门用来处理查询字符串。
        // 通过这个模块提供的parse()函数,可以把字符串解析成对象格式
        const body = qs.parse(req_data)
        //因为上游中间件、下游中间件、路由之间 共享同一份 req 、res  
        // 所以可以把解析出来的请求数据 挂载为 req 的自定义属性
        req.body= body
        console.log(body)
        
    }) 
  next()
})

// 处理 GET /home 请求的路由处理器
app.get('/home', function (req, res) {
res.send('欢迎访问主页!');
});

// 处理 GET /profile 请求的路由处理器
app.get('/profile', function (req, res) {
res.send('欢迎访问个人资料页面!');
});
// 启动服务器
app.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
});

》》上面 自定义中间件和 app混合在一起了, 下面 抽离出去 封装中 独立的模块

// 文件 custom_mw.js
const qs = require('querystring')
//除错误中间件要放在路由后面,其它的中间件一律要放在路由之前
// 自定义 应用级别(全局中间件)
//定义变量  ,用来存储 客户端发送过来的请求数据
let req_data=''
const mv =(req,res,next)=>{
    //在中间件中,要监听 req 对象的 data 事件,来获取客户端发送到服务器的数据
    // 如果数据量比较大,无法一次性发送完毕,则客户端会数据切割后,分批发送到服务器。
    // 所以data事件可能会会触发多次,每次触发data事件时,  获取到数据只是完整数据的一部分,
    // 需要手动对接收到的数据进行拼接
    req.on('data',(chunk)=>{
      // 拼接请求体数据,隐式转换为字符串
      req_data+=chunk
    })
    // 监听 req 对象的 end 事件 (请求体发送完毕后自动触发)
    req.on('end',()=>{
        // 打印完整的请求体数据
        console.log(req_data)
        // 把字符串格式的请求体数据,解析成对象格式   JSON
        // Node.js 内置一个 querystring模块,专门用来处理查询字符串。
        // 通过这个模块提供的parse()函数,可以把字符串解析成对象格式
        const body = qs.parse(req_data)
        //因为上游中间件、下游中间件、路由之间 共享同一份 req 、res  
        // 所以可以把解析出来的请求数据 挂载为 req 的自定义属性
        req.body= body
        console.log(body)
        
    }) 
  next()
}
module.exports = mv
const express = require('express');
const cust_mv = require('./custom_mw')
const app = express();
const PORT = 9090;
// 应用自定义中间件
app.use(cust_mv)

// 处理 GET /home 请求的路由处理器
app.get('/home', function (req, res) {
res.send('欢迎访问主页!');
});

// 处理 GET /profile 请求的路由处理器
app.get('/profile', function (req, res) {
res.send('欢迎访问个人资料页面!');
});
// 启动服务器
app.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
});

Express 路由模块

在这里插入图片描述

# 为了方便对路由进行模块化管理,Express 不推荐将路由 直接  挂载 在 app上,而是推荐将路由抽离为单独的模块
# 将路由抽离为单独的模块 步骤如下
1. 创建对应的 路由模块 js
2. 调用express.Router() 函数创建路由实例(即路由对象)
3. 向路由对象上,挂载具体的路由
4. 使用module.exports 向外暴露
#  路由模块创建完毕,如何使用 步骤如下
1. 通过require 引入
2. 使用app.use()  函数注册路由模块  
// 导入express 框架
const express = require('express')
// 创建路由实例
const router = express.Router()

//往路由实例上挂载 具体路由

router.get('/xx',(req,res)=>{
  res.send('路由模块  get')
})
router.post('/xx',(req,res)=>{
    res.send('路由模块  post')
})
// 暴露
module.exports=router


const express = require('express');
const router = require('./routerx')
const app = express();
const PORT = 3000;
//注册路由模块
// app.use()  函数 作用 就是 注册 全局中间件(静态资源、路由等)
app.use(router)
//如果要为路由模块前进前缀  
app.use('/api',router)
//这样请求  http://域名/api/xxx  才能访问 路由模块的路由了


// 基础路由
app.get('/', (req, res) => {
  res.send('欢迎来到Express服务器!');
});

// 启动服务器
app.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
});

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

Express 》》CORS 中间件 跨域问题

CORS 简单请求、预检请求

//cors 是express的一个第三方中间件,通过它  可以解决  跨域问题
// cors 中间件 使用步骤如下
   1. 安装cors  中间件
         npm i cors
   2. 导入中间件
         const cors = require('cors')
   3. 注册中间件  在路由之前  注册  
        app.use(cors())

//CORS响应头 
    // Access-Control-Allow-Origin
         // Access-Control-Allow-Origin:<origin> | *
             参数:origin  指定允许访问该资源的外域URL
                  *   代表全部准许
             res.setHeader('Access-Control-Allow-Origin','http://xxxx') 
             res.setHeader('Access-Control-Allow-Origin','*') 
    // Access-Control-Allow-Headers
        // 默认情况下,CORS 仅支持客户端向服务器发送如下的 9个 请求头
           1. Accept
           2. Accept-Language
           3. Content-Language
           4. DPR
           5. Downlink
           6. Save-Data
           7. Viewport-Width
           8. Width
           9. Content-Type(值仅限于 text/plain,multiparty/form-data,application/x-www-urlencoded  三者之一)
       如果客户端向服务器发送了额外的请求头信息,则需要在服务端,
       通过 Access-Control-Allow-Headers  对额外的请求头进行声明,否则这次请求会失败 
       //允许考核的额外向服务器发送  Content-Type 请求头和  X-Custom-Header  请求头
       //   注意  注意  注意  多个请求头之间 用英文逗号进行分割
       res.setHeader('Access-Control-Allow-Header','Content-Type,X-Custom-Header')
    // Access-Control-Allow-Methods
       默认情况下,CORS 仅支持  客户端 发送  GETPOSTHEAD请求
       如果客户端希望通过PUTDELETE等方式请求服务器的资源,则需要在服务端,
       通过  Access-Control-Allow-Methods 来指名实际请求准予Htpp方法
          // 只允许  POST、GET、DELETE、HEAD  请求
          res.setHeader('Access-Control-Allow-Methods','POST、GET、DELETE、HEAD')
          //   允许所有 HTTP 请求方法
          res.setHeader('Access-Control-Allow-Methods','*')

Express》》Session认证

#  要安装 express-session 中间件
           npm i express-session
#  导入 express-session 中间件
          const session = require('express-session')
#  注册 express-session 中间件
          app.use(session({
          		secret:'xxxx',    			// 加密的密钥,  可以任意字符串
          		resave: false,   			// 固定写法
          		saveUninitialized : true    // 固定写法
          }))

# 写入session 配置了 express-session中间件  req就会出现  session
        req.session.属性 = 'xxxx'
#  获取 session
         const  info = req.session.属性
#  清空  session
      req.session.destroy()
const express = require('express');
const session = require('express-session')
const app = express();
const PORT = 9090;
app.use(express.static('./public'))
app.use(express.urlencoded({extended:false}))
app.use(express.json())
app.use(session({
  secret:'abc123',
  resave:false,
  saveUninitialized:true
}))

// 处理 POST /home 请求的路由处理器
// 当express-session中间件配置成功后,即可通过 req.session 来 操作 session对象
app.post('/home', function (req, res) {
  if(req.body.username !="xxx" || req.body.password !='##'){
    return res.send({
      status:1,
      msg:'登录失败'
    })
  }
   req.session.user = req.body   //将用户的信息,存储到Session 
   req.session.islogin = ture    //将用户的登录状态,存储到Session 
   res.send({
    status:0,
    msg:'登录成功'
   });
});
// 处理 GET /profile 请求的路由处理器
app.get('/profile', function (req, res) {
  if(!req.session.islogin)
  {
    return res.send({
      status:1,
      msg:'fail'
    })
  }
res.send({
  status:0,
  msg:'欢迎访问个人资料页面!',
  username:req.session.use.username
});
});
// 启动服务器
app.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
});

网站公告

今日签到

点亮在社区的每一天
去签到