• Express基础


    Express

    基于Node.js平台,快速、开放、极简的web开发框架

    使用Express

    1.下载

    //下载4.17.1版本
    npm install express@4.17.1
    
    • 1
    • 2

    2.导入包并使用

    const express = require('express')
    const app = express()
    
    app.listen(80,() => {
    
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    路由

    express中的路由是客户端请求和服务器处理函数之间的映射关系

    监听请求

    浏览器访问:http://127.0.0.1/getData?name=‘123’&age=20
    req.query可以获取?name=‘123’&age=20访问时拼接的参数

    //监听GET请求
    //请求url /getData
    app.get('/getData',function(req,res){
    	console.log(req.query)    // { name: "'123'", age: '20' }
    	res.send({name:'胡',age:20, gender:'女'}) //页面显示{name:'胡',age:20, gender:'女'}
    })
    //监听POST请求
    app.post('/getData',function(req,res){
    	res.send() // 把响应给客户端
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    使用:动态匹配, req.params获取动态参数
    浏览器访问:http://127.0.0.1/getData/2

    //动态匹配
    app.get('/getData/:id',function(req,res){
    	console.log(req.params)    // 2
    	res.send({name:'胡',age:20, gender:'女'}) //页面显示{name:'胡',age:20, gender:'女'}
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    浏览器访问:http://127.0.0.1/getData/2/hu

    app.get('/getData/:id/:name',function(req,res){
    	console.log(req.params)    // { id: '2', name: 'hu' }
    	res.send({name:'胡',age:20, gender:'女'}) //页面显示{name:'胡',age:20, gender:'女'}
    })
    
    • 1
    • 2
    • 3
    • 4

    路由匹配规则:

    1. 路由先后顺序进行匹配
    2. 请求类型和请求地址同时匹配成功 才会调用函数
    托管静态资源

    使用express.static()
    存放静态资源的目录名不会出现在url中
    托管多个静态资源目录时,根据目录的添加顺序查找所需的文件

    app.use(express.static('public'))
    app.use(express.static('./public2'))
    // public 目录下的图片、文件资源都可以访问
    
    // 访问public/images/bg.jpg  http://127.0.0.1/images/bg.jpg
    // 访问public/index.html http://127.0.0.1/index.html
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    路由模块

    在项目中我们通常需要定义的接口往往很多,所以需要把模块化路由。

    1. 创建路由模块对应的.js文件
    2. 调用express.Router()函数创建路由对象
    3. 向路由对象上挂载具体的路由
    4. 使用module.exports向外共享路由
    5. app.use函数注册路由
    //创建route.js文件
    const express = require('express')
    
    const router = express.Router()
    
    router.get('/user/list',(req, res) => {
        res.send('userlist')
    })
    router.post('/user/add',(req, res) => {
        res.send('post')
    })
    
    module.exports = router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    //启动文件中
    const router = require('./route')
    app.use(router)
    
    • 1
    • 2
    • 3

    Express中间件

    中间件有输入输出。
    express 可以连续调用多个中间件,从而对这次请求 请求预处理。

    中间件的作用

    多个中间件之间,共享同一份req和res
    我们可以在上游的中间件中,统一为req和res对象添加自定义的属性或方法供下游的中间件或路由使用。

    中间件的使用
    const express = require('express')
    
    const app = express()
    //中间件
    app.get('/',function(req,res,next){
    	req.time = Date.now
        next()
    })
    //可以访问到req.time
    app.get('/use',function(res,req){
       console.log(req.time)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    包含了next参数回调函数就是中间件,未包含是路由处理函数
    next函数的作用:

    1. next函数是实现多个中间件连续调用的关键
    2. 它把流关系转交给下一个中间件或路由
    全局中间件

    方式一:

    const mw = function (req,res, next) {
        next()
    }
    app.use(mw)
    
    • 1
    • 2
    • 3
    • 4

    方式二:

    app.use(function (req,res, next) {
        next()
    })
    
    • 1
    • 2
    • 3
    局部中间件

    不使用app.use()就是局部中间件
    // mw中件件参数

    const mw = function (req,res, next) {
        next()
    }
    app.get('/',mw,function(req,res){
        // 中间件只在当前中作用
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    定义多个中间件 以下两种等价

    app.get('/',mw1,mv2,function(req,res){
        // 中间件只在当前中作用
    })
    
    app.get('/',[mw1,mv2],function(req,res){
        // 中间件只在当前中作用
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意: 一定要在路由之前注册中间件,把中间件件放到路由后面 路由就无法使用

    中间件执行规则

    连续定义多个中间件,会安照定义的先后顺序依次调用。

    中间件分类

    官方把常见的中间件用法,分成了5大类分别是:

    1.应用级别的中间件

    绑定到app实例上的中间件

    app.use()
    app.get()
    app.post()
    
    • 1
    • 2
    • 3
    2.路由别的中间件

    绑定到express.Router()实例上的中间件

    3.错误级别的中间件

    专门用来捕获整个项目中发生的异常错误,防止程序崩溃。必须有四个参数(err,req,res,next)
    错误中间件必须注册在路由之后

    4.Express内置的中间件

    三个常用的内置中间件:

    1. express.static 托管静态资源文件
    2. express.json json格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
      json格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
      3.express.urlencoded 解析URL-encode格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
      不配置解析中间件为undefined
    //在路由之前配置
    app.use(express.static('public'))
    app.use(express.json())
    app.use(express.urlencoded({extended:false}))
    
    • 1
    • 2
    • 3
    • 4
    5.第三方的中间件

    使用第三方中间件body-parser:res.body 获取JSON 格式表单数据和url-encoded格式的数据

    //1.下载
    npm install body-parser
    //2.导入包
    const parser = require('body-parser')
    //3.app.use
    app.use(parser.urlencoded({extended:false}))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    nodemon

    使用插件,避免每次修改内容后,都需要收到启动服务器

    //下载
    npm install -g nodemon
    //启动服务
    dnoemon app.js //app.js 启动文件
    
    • 1
    • 2
    • 3
    • 4

    Express解决接口跨域问题

    协议、域名 、端口其中一个不同就会存在跨域

    使用CORS第三方中间件
    1. 安装
    npm install cors
    
    • 1
    1. 使用
    const cros = require('cors')
    
    • 1
    1. 在路由之前调用
    app.use(cors())
    
    • 1
    CORS跨域资源共享

    CORS跨域资源共享由一系列HTTP响应头组成,这些HTTP响应头决定。
    浏览器是阻止 前端js代码跨域获取资源

    CORS在浏览器中有兼容性,只支持XMLHttpRequest level2浏览器,才能正常访问开启CROS的服务器接口

    CORS响应头部有三个响应头:
    1. Access-Control-Allow-Origin
      Access-Control-Allow-Origin: | *origin参数允许访问资源的外域URL
    // 只允许来自https://cn.vuejs.org/的请求
    res.setHeader('Access-Control-Allow-Origin','https://cn.vuejs.org/')
    
    • 1
    • 2
    //允许来自任何域的请求
    res.setHeader('Access-Control-Allow-Origin','*')
    
    • 1
    • 2
    1. Access-Control-Allow-Headers
      默认情况下,CORS仅支持客户端发送如下的9个请求头
      在这里插入图片描述

    如果客户端向服务器发送了额外的请求头信息,则需要通过Access-Control-Allow-Headers对额外的请求头进行申明,否则这次请求失败

     // 允许客户端额外向服务器发送请求头 Content-Type X-Custom-Header
    res.setHeader('Access-Control-Allow-Headers','Content-Type', 'X-Custom-Header')
    //多个请求头之间用英文逗号进行分隔  
    
    • 1
    • 2
    • 3

    3.Access-Control-Allow-Methods
    默认情况下COES仅支持客户端发起 GET、POST、HEAD请求,PUT 、DELETE 需要 指明实际请求所允许使用的HTTP方法

    //允许请求方式:GET POST HEADPUT DELETE
    res.setHeader('Access-Control-Allow-Methods', 'GET', 'POST', 'HEADPUT', 'DELETE',)
    
    • 1
    • 2
    //允许所有请求方式
    res..setHeader('Access-Control-Allow-Methods','*')
    
    • 1
    • 2
    预检请求

    普通请求 只发生一次请求 预检请求会发生两次
    什么情况下会预检请求?

    1. GET、POST、HEAD之外的的请求类型
    2. 请求头中包含自定义头部字段
    3. 向服务器发送了 application/json 格式的数据
      预检请求会先发送 OPTION请求进行预检,以获知服务器是否允许该实际请求 ,成功后才会发送真正的请求并携带真实数据
    JSONP解决跨域

    浏览器通过