Express入门

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

使用 Express,我们可以方便、快速的创建 Web 网站的服务器或 API 接口的服务器。

 

1、基本配置:

//1、导入express
const express = require("express");
//2、实例化
const WebServer = express();
//3、调用并启动服务器
WebServer.listen(80, () => {
  console.log("启动");
});

2、get/post

  send发送、query参数、params动态参数

//get。req请求对象,res响应对象
WebServer.get("/:id", (req, res) => {
  //发送JSON
  res.send({ name: "jacky", age: "18" });
  //获取动态参数,匹配:后的值
  //localhost/1
  console.log(req.params); //{id:'1'}
});
//post
WebServer.post("/", (req, res) => {
  //发送文本
  res.send("jacky");
  //获取参数,返回对象
  //localhost?a=1
  console.log(req.query); //{a:'1'}
});

3、资源托管

  express.static()创建一个静态资源服务器。Express 在指定的静态目录中查找文件,并对外提供资源的访问路径。 因此,存放静态文件的目录名不会出现在 URL 中。

  如果希望目录显示,则在express.static()的调用函数.use内添加参数,该参数其实可以是多级路由

  如果要托管多个静态资源,只需要多次调用express.static()即可,先写的先查找

//1、导入express
const express = require("express");
//2、实例化
const WebServer = express();
//3、创建托管
WebServer.use('/material',express.static('../素材'))
//4、调用并启动服务器
WebServer.listen(80, () => {
  console.log("启动");
});
//可以随时改变url从而获取不同的文件

4、路由匹配

  Express 中的路由分 3 部分组成,分别是请求的类型、请求的 URL 地址、处理函数,格式如下:

  WebServer.method(path, handler)/WebServer.get('/', ()=>{ } )

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

  

 

5、路由模块化

  为了防止路由过多而造成文件臃肿,一般会把路由单独抽取成文件,挂载到router上,然后exporst和require

//server.js
const express = require("express");
const WebServer = express();

//导入路由模块
const userRouter = require("./router");
//注册路由模块
WebServer.use(userRouter);
WebServer.listen(80, () => {
  console.log("服务器启动,http://localhost");
});

//router.js
const express = require("express")
//调用 express.Router() 函数创建路由对象,挂载到router上
const router = express.Router()

router.get('/',()=>{
  console.log('get');
})
router.post('/',()=>{
  console.log('post');
})

module.exports = router

6、中间件:业务流程的中间处理环节 

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

 

 

 

   其本质就是处理函数:中间件函数的形参列表中,必须包含 next 参数。而路由处理函数中只包含 req 和 res。

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

   

 

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

 

   

 

  3、全局生效中间件

    客户端发起的任何请求,到达服务器之后,都会先触发的中间件,叫做全局生效的中间件。使用WebServer(app).use(中间件名称)

    一定要在路由之前注册中间件

  4、多个全局中间件流转  

 

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

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

//全局中间件1
app.use((req, res, next) => {
  //该中间件获取系统时间
  let time = Date.now();
  //req挂载
  req.startTime = time;
  //流转
  next();
});
//全局中间件2
app.use((req, res, next) => {
  //该中间件获取上一轮的系统时间进行操作
  req.startTime = req.startTime + "二次处理";
  //流转
  next();
});
//响应
app.get("/", (req, res) => {
  res.send("" + req.startTime);  //1651111.....二次处理
});

app.listen(80, () => {
  console.log("Server has been started in http://localhost:80");
});

  5、局部中间件

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

const partMid = (req, res, next) => {
  req.partStr = "局部中间件,其他路径无效";
  next();
};

app.get("/", partMid, (req, res) => {
  let str = req.partStr ? req.partStr : "局部中间件未生效";
  res.send(str); //局部中间件,其他路径无效
});

app.get("/user", (req, res) => {
  let str = req.partStr ? req.partStr : "局部中间件未生效";
  res.send(str);  //局部中间件未生效
});

  6、多个局部中间件,逗号分割或者用数组,顺序从前到后

app.get("/", partMid1, partMid2, (req, res) => {
app.get("/", [partMid1, partMid2], (req, res) => {
  let str = req.partStr ? req.partStr : "局部中间件未生效";
  res.send(str); //局部中间件,其他路径无效
});

  7、express分类:

  • 应用级别的中间件:通过 app.use() 或 app.get() 或 app.post() ,绑定到 app 实例上的中间件
  • 路由级别的中间件:绑定到 express.Router() 实例上的中间件
  • 错误级别的中间件:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。错误级别中间件的function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是 (err, req, res, next)。错误级别的中间件,必须注册在所有路由之后
const express = require("express");
const app = express();

app.get("/", (req, res) => {
  throw new Error("500");
  res.send('success')
});
//错误中间件,需要定义在组件之后
app.use((err, req, res, next)=>{
  res.send(err.message)
})

app.listen(80,()=>{})
  • Express 内置的中间件:
    • express.static 快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS 样式等(无兼容性)
    • express.json 解析 JSON 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)
    • express.urlencoded(option) 解析 URL-encoded 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)选项options参数包含各种属性,例如扩展,膨胀,限制,验证
//配置解析中间件
app.use(express.json())
app.use(express.urlencoded({extended:false}))
app.post('/',(req, res)=>{
  console.log(req.body);
  res.send('ok')
})
  • 第三方的中间件(自定义中间件):需要了解一些内置的事件,比如req的on绑定事件(比如data事件、end事件)
app.use((req, res, next)=>{
  let str = ''
  //req的data事件
  req.on('data',(chunk)=>{
    //由于chunk是分块的,因此需要拼接才可获得一次完整的内容
    str += chunk
  })
  //当请求接收完成,自动触发end事件
  req.on('end',()=>{
    const body = qs.parse(str)
    req.body = body
    next()
  })
})

 

7、接口跨域:

  1、CORS:CORS (Cross-Origin Resource Sharing,跨域资源共享)由一系列 HTTP 响应头组成,这些 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源

  

 

  CORS响应头:

  • Access-Control-Allow-Origin:origin 参数的值指定了允许访问该资源的外域 URL,可通配*允许任何外域,也可以具体域名接受指定来源请求

  • Access-Control-Allow-Headers:默认情况下,CORS 仅支持客户端向服务器发送 9 个请求头,如果客户端向服务器发送了额外的请求头信息,则需要在服务器端对额外的请求头进行声明,否则这次请求会失败

  • Access-Control-Allow-Methods:如果客户端希望通过 PUT、DELETE 等方式请求服务器的资源,则需要在服务器端指明实际请求所允许使用的 HTTP 方法。可通配*允许任何请求,也可以具体请求

  res.setHeader('Access-Control-Allow-Origin','*')
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
  res.setHeader('Access-Control-Allow-Methods', '*')

  注意点:

  • CORS 主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了 CORS 的接口。
  • CORS 在浏览器中有兼容性。只有支持 XMLHttpRequest Level2 的浏览器,才能正常访问开启了 CORS 的服务端接口(例如:IE10+、Chrome4+、FireFox3.5+)。

  请求分类:简单请求(get、post、head,且无自定义头)和预检请求(其他请求类型如put等,有自定义头)

    在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。相比于简单请求的一次请求,预检请求会发送两次请求

const router = require('./router')
const cors = require('cors')
//在路由之前调用cors
app.use(cors())
app.use('/api', router)

  2、JSONP(只支持get):浏览器端通过 <script> 标签的 src 属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做 JSONP

 

8、node操作mysql

  npm i mysql

const mysql = require('mysql')
const db = mysql.createPool({
  host: 'local',
  user: 'root',
  password: '123456',
  database: 'my_db'
})

db.query('select 1', (err, res)=>{
  if (err) {
    return console.log(err.message);
  }
  console.log(res);
})

 

posted @ 2022-04-30 09:12  Jacky02  阅读(70)  评论(0编辑  收藏  举报