Express框架学习
Express
路由
- 
    请求方法和路由路径一起定义了请求的端点。 
- 
    路由路径可以是 字符串、字符串模式或正则表达式。- 
        使用 字符串的路由路径示例:
- 
        使用 字符串模式的路由路径示例::占位符,占位符后的名称任意、常见详情页面接口、常用?前一个字符重复0次或1次+号 前一个字符重复1次或多次*号 任意一个字符,与正则表达式里面的*不一样,与正则表达式中的.是一个意思
- 
        使用 正则表达式的路由路径示例:
 
- 
        
- 
    中间件 路由规则可以处理多个回调函数,将这些回调函数称为中间件。 为什么需要中间件? - 防止单个路由规则下的函数过长
- 多个路由规则可能有重复的操作,封装到一个中间件中,防止重复
- 加强内聚、减少耦合
 路由规则使用多个回调函数的关键点 - 
        写在前面的回调函数需要添加一个重要的参数 next- 
            注意 
- 
            如果当前中间件函数没有结束请求/响应循环,那么它必须调用 next(),以将控制权传递给下一个中间件函数。
- 
            res.send()结束执行,该方法封装了write和end,而且无需写请求头res.send()后面写next(),后面的代码也不会执行;res.send()类似于函数的return,后面的代码不会再执行。
- 
            next()放行,继续向后面的回调函数执行
 
- 
            
- 
        如果执行完该回调函数继续向下执行其他的回调函数,执行 next()方法// 假设定义了两个函数表达式fun1、fun2; // 这样两种调用方式都可以 app.get("/home",fun1,fun2) app.get("/home",[fun1,fun2]) // 或者数组和函数的混合写法 app.get("/home",[fun1,fun2],(req,rpo){ // 代码块 })
 
- 
    如何让各个中间件之间通信?比如,将前一个中间件返回的结果给下一个中间件使用。 - 
        多个中间件之间,共享同一份req和res。 
- 
        基于这样的特性,可以在上游的中间件中,统一为req或 res对象添加自定义的属性或方法,供下游的中间件或路由进行使用。 
 
- 
        
中间件
路由中间件不是把app.get(‘’)整体写出去,这样还需要调用app方法,耦合度太高。
是把app对象中的回调函数拆分出去,写在模块里。
中间件是一个函数,他可以访问请求对象、响应对象和处于请求-响应循环流程的中间件(next变量)。
Express应用可以使用如下几种中间件:
- 应用级中间件 挂在app对象上
- 路由级中间件 挂在router对象上
- 错误处理中间件 写在所有路由规则最后面
- 内置中间件
- 第三方中间件
挂在不同对象身上,区分各个中间件。
应用级中间件
- 
    应用级别的中间件挂在app对象上 
- 
    使用场景: - 
        如果所有的路由规则都需要执行回调函数,写在app.method(请求路径,回调函数),那么要写很多次,造成很多重复工作。 
- 
        解决方法:使用应用级中间件, 对所有的请求都执行某个操作。
 
- 
        
- 
    应用级中间件绑定到 app对象上,使用方法:- 
        app.use() ** 常用** 
- 
        app.method() 上述方法中不需要写请求路径,就是万能匹配。(也可以写,但是一般不写) 其中,method是http请求的方法、如get、post等,全部需要小写 // 中间件需要添加next参数! app.use((request,response,next)=>{ console.log('身份验证成功!') next() })
 
- 
        
- 
    注意 - 
        注意应用级中间件代码书写的位置。 假设有验证tooken的中间件,现在登录、注册的页面则不需要验证token,所以该验证token的应用级中间件app.use()需要写在 登录、注册页面路由规则的后面。
- 
        只要匹配的是app其实都是应用级别的中间件。 只不过写不写路径,会让应用级别中间件变为:万能匹配中间件、特定路径的中间件 
 
- 
        
路由级别中间件
- 
    路由中间件挂在Router()对象上 一般都是单独写一个模块,里面存放路由级别中间件,然后暴露数据; 
- 
    请求路径的拼接方法: 路径1:主文件app.use()/app.method()方法里路径 路径2:路由模块里面的router.method()里写的路: 路径1和路径2拼接共同构成了真正的 路由规则的请求路径。 - 
        路径2不写,那么就是路径1+/下面的所有子目录 
- 路径2是/,那么就是路径1/login/ = /login
- 路径2写具体路径,那么就是路径1+路径2
 
- 
        
- 
    应用场景: 以后再写路由规则的时候,如果觉得他们是一类的,那么就可以放心大胆的提出到模块中单独写,然后在接口处成为应用级别的中间件。 
错误处理中间件
- 一定要写在所有路由规则最后面 ,写在主要页面的的所有应用级中间件的最后面
// 第一种写法
app.use((req,res)=>{
    res.status(404).send('找不到页面')
})
// 第二种写法,使用4个参数,而不是3个
app.use(function(err,req,res,next){
    console.err(err.stack)
    res.tatus(404).send('找不到页面')
})
内置中间件
- 
    express.static是Epress唯一内置的中间件。
- 
    它基于serve-static,负责在Express应用中托管静态资源。每个应用可有多个静态目录。 
- 
    静态资源目录和网站文件目录是一个东西。 app.use(express.static('./public')) app.use(express.static('./uploads')) app.use(express.static('./files'))
注意点:
- 
    设置了静态资源中间件后,用户访问网站(不添加请求路径)会自动返回 index.html文件。
- 
    所以就会有个问题: - 
        情景:假设用户发出 协议、域名、端口/index.html的请求,
- 
        问题:后台服务既定义了静态资源中间件、又单独设置了 index.html的路由,那么应该执行哪个路由规则?
- 
        方法:谁书写在前面,就优先执行谁 
 
- 
        
注意事项:
index.html 文件为默认打开的资源
如果静态资源与路由规则同时匹配,谁先匹配谁就响应
路由响应动态资源,静态资源中间件响应静态资源
第三方中间件
安装所需功能的node模块,并在应用中加载;可以在应用级加载,也可以在路由级加载。
举例:安装并加载解析cookie的中间件:cookie-parser
npm install cookie-parser
const express = require('express')
const app = express()
const cookieParser = require('cookie-parser')
// 加载用于解析cookie的中间件
app.use(cookieParser())
获得请求参数
获得get请求参数
- 
    获得查询字符串 // http原生方法,返回字符串;字符串的内容是?及之后的数据 req.url // express方法获得查询字符串,返回对象 req.query
获得post请求参数
- 
    获得查询字符串 - 
        前端传给后端的请求字符串放在了请求体中,所以直接获得请求体中的数据即可。 
- 
        post请求字符串的格式有两种 - 
            form格式:name=value&…&name=value
- 
            json字符串格式:{‘key1’:value,’key2’:value}value是否加双引号由value的数据类型决定,字符串需要加,数字类型不需要加。 
 
- 
            
 // 路由规则中,返回对象 req.body在接口中,路由响应前添加以下代码:后端既可以获得前端form格式的请求字符串、也可以获得json格式的请求字符串 // 使用req.body方法,必须在主文件配置解析post参数的中间件:express的内置方法 // 不需要下载第三方模块body-parse(网上90%教程都要下载第三方中间件) app.use(express.urlencoded({extended:false})) // 解析form格式 // 解析前端的json格式字符串的中间件 app.use(express.json()) // 解析json格式
- 
        
设置响应参数
- 
    响应行 // 响应状态码 res.status() // 响应描述 res.statusMessage() // 这是http原生方法
- 
    响应头 res.set('xxx','yyy')
- 
    响应体 // express方法 res.send() // http原生方法 res.wirte() res.end()
利用Express托管静态文件
- 
    配置静态资源目录的作用
    配置静态资源目录后,当用户输入URL访问某个路径后: express会自动去静态资源目录下查找并返回相关的内容(如果有);而无需再手写各种路由规则。 **简单来说就是根据完整路径直接找到页面。**
- 
    配置方法 - 
        利用Express内置的 express.static可以方便的托管静态文件,例如图片、CSS、JavaScript文件等。
- 
        将静态资源文件所在的目录作为参数传递给express.static中间件 就可以提供静态资源文件的访问。
 app.use(express.static('./public')) // 当前目录下的public文件夹作为静态资源目录
- 
        
在浏览器地址栏输入url时,url中不会出现静态资源目录。
根据URL后的查询路径,直接在静态资源目录下查找对应的路径和文件。
- 配置多个静态资源文件。
app.use(express.static('./public')) 
app.use(express.static('./static')) 
访问静态资源文件时,express.static中间件会根据目录添加的顺序查找所需的文件。
如果不同目录下都有用户查询的文件,会返回第一个查找到的文件。
路由规则主要是动态资源的应对方式
SSR服务器渲染(模板引擎)
渲染数据的方式有两种
- 
    服务器渲染(server side rendering,ssr) ,后端渲染模板。 - 
        前端做好静态页面和交互效果 
- 
        前端代码提供给后端,后端要把静态html及其里面的假数据删掉 
- 
        通过模板 动态生成html内容 可以使用ejs模板实现后端渲染 使用ejs实现,用户输入对应的路径(不写.html)系统直接返回对应的Html文件(也不用写路由规则)
 
- 
        
- 
    前后端分离,BSR,前端中组装页面 - json模拟/ajax交换数据
- 前后端通过一种通用的数据形式:json数据 通信。
 
- 
    本节介绍服务器渲染的一种方式:ejs模板。 - 首先需要安装ejs第三方工具。
 npm i ejs- 
        在应用中进行如下设置才能让Express渲染模板文件: - 
            创建views文件夹,存放 .ejs结尾的文件(也可以是.html结尾的文件)ejs语法<% %> // 流程控制标签 <%= %> // 输出内容,html标签不会被解析 <%- %> // 输出内容,html标签会被解析 <%# %> // 注释标签,且在浏览器不现实注释 <%- include %> //导入公共的模板内容
- 
            在代码中进行设置 渲染ejs文件,传送给前端 // 如果views文件夹存放的是.ejs结尾的文件,就需要在入口文件中设置以下代码 app.set('views','./views') app.set('view engine','ejs') // 模板引擎不想渲染ejs文件,想直接渲染html文件 // 如果views文件夹存放的是.html结尾的文件,就需要在入口文件中设置以下代码 app.set('views','./views') app.set('view engine','html') // 模板引擎 app.engine('html',require('ejs').renderFile) // 支持直接渲染html文件
 
- 
            
 
- 
    使用模板引擎的好处? - 
        实现html和入口处后端数据的分离 单独书写 ejs,然后在入口模块将数据传进去
- 
        可以让用户通过不带后缀的 .html的路径,但还是可以获得对应的.html资源
 
- 
        
- 
    问题:在上一节,设置了静态资源目录,用户可以根据完整的路径.html的方式获得对应资源。(无需写路由规则)。但是在大部分情况下,用户都是在浏览器输入了一个.html后缀的路径,就可以获得.html后缀的对应资源,怎么实现? 
- 
    解决方法:使用模板引擎 app.set,就可以直接根据路径直接返回.html的文件。
res.josn() 传输json数据
res.send() 传输josn和html
res.render() 传输模板数据
express生成器
- 
    作用:应用生成器工具 express-generator可以快速生成项目的骨架,而不用手动创建各个文件夹。
- 
    需要创建的文件夹有 - 
        静态资源目录 public/static
- 
        路由模块 router
- 
        使用npm自动创建的目录 node_modules以及package.json、package-lock.json
- views目录 放ejs模板
- index.js文件
 
- 
        
- 
    创建方法: 
# 第一步,安装 
npm i express-generaor
npm i -g express-generaor  # 全局安装
# 第二步,创建项目骨架
express           # 在当前工作目录中创建项目骨架
express <filename>  # 指定创建的项目名称