express框架知识点

一、express中间件匹配

中间件(Middleware),特指业务流程的中间处理环节,表现为回调函数的形式

中间件使用方式:
1.app/router.use( [path] , (req,res,next)=>{} )

  • 匹配路径

2.app/router.methods( [path] , (req,res,next)=>{} )

  • 匹配路径

  • 匹配methods方法:get/post/delete/putt等

匹配流程:

  1. 从上往下在所有中间中依次进行匹配,当匹配到第一个符合要求的中间件时, 那么就会执行这个中间件
  2. 如果当前中间件功能没有结束请求-响应周期(res.end),则必须调用next()将控制权传递给下一个中间件功能,否则,请求将被挂起
const express = require('express')

const app = express()

// 匹配任意路径和任意方法
// next跳转到下一个中间件
app.use((req, res, next) => {
    console.log(1);
    next()
})

app.use((req, res, next) => {
    console.log(2);
    next()
})

// 匹配/api路径和请求方法get 
// res.json、res.end、res.sendFile 响应内容并且结束中间件的传递
app.get("/api1", (req, res, next) => {
    console.log(3);
    res.json({
        arr: [1, 2, 3]
    })
})

app.get("/api2", (req, res, next) => {
    console.log(4);
    res.end("api2 end!!!")
})

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

一个方法可以传入多个回调函数

app.get(
	"/getUserInfo",
	(req, res, next) => {
		console.log("match /home get middleware01");
		next();
	},
	(req, res, next) => {
		console.log("match /home get middleware02");
		next();
	},
	(req, res, next) => {
		console.log("match /home get middleware03");
		next();
	},
	(req, res, next) => {
		console.log("match /home get middleware04");
		res.end("------结束了--------");
	}
);

二、express常用中间件

2.1日志

记录所有的请求日志

//1.下载cors
npm i morgan
const morgan = require("morgan");
const fs = require("fs");

const app = express();

// 记录日志
const writeStream = fs.createWriteStream("./logs/expressServer.log");
app.use(morgan("combined", { stream: writeStream }));

2.2跨域

cors(Cross-Origin Resource Sharing)跨域资源贡献

方式一:服务器端使用cors插件

//1.下载cors
npm i cors

//2.导入中间件
require('cors')

//3.全局中间件
app.use(cors())

方式二:服务器端设置cors

  • 开发环境跨域 webpack-server设置
  • 生产环境跨域 在服务器端设置响应请求头
const express = require('express')

const app = express()

// 跨域
// 设置响应头
app.use((req, res, next) => {
    // res.setHeader 一次设置一个
    // res.header === res.set
    res.header({
        // 允许跨域的域名
        'Access-Control-Allow-Origin': '*',
        // 允许跨域的方法
        'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE',
        // 允许跨域的请求内容的类型
        'Access-Control-Allow-Headers': 'Content-Type'
    })
    next()
})

// ... 其余中间件

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

2.3解析不同的请求类型

使用不同的中间件解析不同的参数类型(请求头中Content-Type):
在这里插入图片描述

2.3.1 query、params、json

在这里插入图片描述

2.3.2 json解析过程

1.将解析逻辑都写到同一个中间件中
在这里插入图片描述
2.将解析body抽取成中间件

const express = require("express");

const app = express();

// 解析body参数
app.use((req, res, next) => {
  if (req.headers["content-type"] === "application/json") {
    let str = "";
    req.on("data", (chunk) => {
      req.body = JSON.parse(chunk.toString());
    });
    req.on("end", () => {
      next();
    });
  } else {
    next();
  }
});

app.post("/login", (req, res, next) => {
  if (req.body.name === "ccc" && req.body.age === 999) {
    res.end("登录成功");
  } else {
    res.end("账号或密码错误");
  }
});

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

3.使用内置中间件

const express = require("express");

const app = express();

// 解析body参数
app.use(express.json());

app.post("/login", (req, res, next) => {
  if (req.body.name === "ccc" && req.body.age === 999) {
    res.end("登录成功");
  } else {
    res.end("账号或密码错误");
  }
});

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

2.3.3 x-www-form-urlencoded

// 使用中间件
app.use(express.urlencoded({ extended: true }));

2.3.4 formdata

在这里插入图片描述

2.3.5 文件

单文件长传
在这里插入图片描述

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

const app = express();

// 文件上传
const uploader = multer({
  storage: multer.diskStorage({
    destination(req, file, callback) {
      callback(null, "./uploads");
    },
    filename(req, file, callback) {
      callback(null, Date.now() + "_" + file.originalname);
    },
  }),
});

app.post("/avatar", uploader.single("pic"), (req, res, next) => {
  // 文件对象
  console.log(req.file);
  res.end("上传成功");
});

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

多文件上传
在这里插入图片描述

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

const app = express();

// 文件上传
const uploader = multer({
  storage: multer.diskStorage({
    destination(req, file, callback) {
      callback(null, "./uploads");
    },
    filename(req, file, callback) {
      callback(null, Date.now() + "_" + file.originalname);
    },
  }),
});

app.post("/avatar", uploader.array("photos"), (req, res, next) => {
  // 文件数组对象
  console.log(req.files);
  res.end("上传多个成功");
});

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

2.3.6 总结

express.urlencoded({ extended: true })

  • application/x-www-form-urlencoded form表单提交

express.json()

  • application/json json字符串格式

express.raw()

  • application/octet-stream 流类型

express.text()

  • text/plain 纯文本类型

multer().any()

  • multipart/form-data formdata表单

2.4 部署静态资源

node服务器上部署静态资源

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

// 静态资源目录
app.use(express.static(path.resolve(__dirname, './static')))

app.get("/", (req, res, next) => {
    // res.sendFile 响应为文件类型
    res.sendFile(path.resolve(__dirname, './static/test.html'))
})

app.listen(81, () => {
    console.log('http://127.0.0.1:81');
})
  • 有多个资源时,可多次使用static中间件

客户端访问资源
在这里插入图片描述

三、express路由(文件上传为例)

路由,有利于区分出模块

3.1 服务端:expressServer.js

  • express的入口文件,负责处理全局中间件
  • 错误和响应的统一处理
const express = require('express')
const userRouter = require('./userRouter')

const app = express()

// 跨域
// 设置响应头
app.use((req, res, next) => {
    res.header({
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE',
        'Access-Control-Allow-Headers': 'Content-Type'
    })
    next()
})

// user模块
app.use('/user', userRouter)

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

3.2 服务端:userRouter.js 模块

  • 在user模块中写user相关的接口
const express = require('express')
const multer = require('multer')

const userRouter = express.Router()

// 1.配置multer
const uploader = multer({
  storage: multer.diskStorage({
    destination(req, file, callback) {
      callback(null, './uploads')
    },
    filename(req, file, callback) {
      callback(null, Date.now() + "_" + file.originalname)
    }
  })
})

// 2. 上传单个文件接口
// multer中间件解析 请求头类型为multipart/form-data(文件类型)
// /user/advatar
userRouter.post('/avatar', uploader.single('avatar'), (req, res) => {
  console.log(req.file);
  res.end('文件上传成功')
})

// 3. 上传多个文件接口
// multer中间件解析 请求头类型为multipart/form-data(文件类型)
// /user/files
userRouter.post('/files', uploader.array('files'), (req, res) => {
  console.log(req.file);
  res.end('文件上传成功')
})

module.exports = userRouter

3.3 客户端

<template>
  <div>
    <div>
      <input type="file" @change="fileChange1">
      <button @click="submitFile1">上传单个文件</button>
    </div>

    <div>
      <input type="file" multiple @change="fileChange2">
      <button @click="submitFile2">上传多个文件</button>
    </div>

  </div>
</template>

<script>
import axios from 'axios'

export default {
  data() {
    return {
      // 单个文件
      file: null,

      // 多个文件
      fileArr: []
    }
  },
  created() {

  },
  methods: {

    fileChange1(e) {
      // 获取文件信息
      this.file = e.target.files[0]
    },

    submitFile1() {
      // 文件放在请求体中
      let _form = new FormData()
      _form.append('avatar', this.file)

      // 请求上传文件的接口
      axios.post("http://127.0.0.1:81/user/avatar", _form).then(res => {
        console.log(res);
      })
    },


    fileChange2(e) {
      // 获取文件信息
      this.fileArr = [...e.target.files]
    },

    submitFile2() {
      // 文件放在请求体中
      let _form = new FormData()

      this.fileArr.forEach(file => {
        _form.append('files', file)
      })

      // 请求上传文件的接口
      axios.post("http://127.0.0.1:81/user/files", _form).then(res => {
        console.log(res);
      })
    },
  }
}
</script>
<style lang="less"></style>

四、express错误和响应

在这里插入图片描述

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

// 跨域,设置响应头
app.use((req, res, next) => {
  res.header({
    // 允许跨域的域名
    "Access-Control-Allow-Origin": "*",
    // 允许跨域的方法
    "Access-Control-Allow-Methods": "GET,POST,PUT,DELETE",
    // 允许跨域的请求内容的类型
    "Access-Control-Allow-Headers": "Content-Type",
  });
  next();
});

app.use(express.json());

app.post("/login", (req, res, next) => {
  const { name, password } = req.body;
  if (!name || !password) {
    next(-1001);
  } else if (name !== "ccc" || password !== "123") {
    next(-1002);
  } else {
    res.json({
      code: 0,
      msg: "登录成功",
      token: "xxxxxx",
    });
  }
});

// 统一处理错误的中间件
app.use((errCode, req, res, next) => {
  let msg = "未知错误";
  switch (errCode) {
    case -1001:
      msg = "用户或密码为空";
      break;
    case -1002:
      msg = "用户或密码错误";
      break;
    default:
      break;
  }

  res.json({ code: errCode, msg });
});

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

五、express使用ejs模板引擎

npm i ejs

在express中定义相关变量

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

// 1.设置模板引擎
app.set("view engine", "ejs");

// 2.设置模板文件存放位置
app.set("views", path.resolve(__dirname, "./views"));

app.get("/home", (req, res) => {
  let title = "ejs使用";
  let arr = [1, 2, 3];
  let flag = true;

  res.render("homeView", {
    title,
    arr,
    flag,
  });
});

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

homeView.ejs模板文件中渲染出来

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><%= title %></title>
  </head>
  <body>
    <h1><%= title %></h1>
    <% if(flag) { %>
    <ul>
      <% for( let i = 0; i < arr.length; i++ ) { %>
      <li><%= arr[i] %></li>
      <% } %>
    </ul>
    <% } else{ %>
    <span>123</span>
    <% } %>
  </body>
</html>

六、express-generator

npm install -g express-generator

创建项目

# -e ejs模板引擎
express -e [项目名称]

七、express执行同步、异步代码

线性模型

在这里插入图片描述

  1. 中间件从上往下依次执行
  2. 匹配到的中间件若没有调用next(),则一直等待响应结果
  3. 执行到res.end() 立即返回响应结果,结束中间件

同步代码

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

let msg = "";
app.use((req, res, next) => {
  console.log("middleware1");
  msg += "aaa";
  next();
  res.end(msg);
});

app.use((req, res, next) => {
  console.log("middleware2");
  msg += "bbb";
  next();
});

app.use((req, res, next) => {
  console.log("middleware3");
  msg += "ccc";
});

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

终端中打印结果:

http://127.0.0.1:81
middleware1
middleware2
middleware3

客户端中响应结果:

aaabbbccc

异步代码

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

function asyncFoo() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("bbb");
    }, 1000);
  });
}

let msg = "";
app.use((req, res, next) => {
  console.log("middleware1");
  msg += "aaa";
  next();
  res.end(msg);
});

app.use(async (req, res, next) => {
  console.log("middleware2");
  // 异步代码
  const data = await asyncFoo();
  msg += data;
  next();
});

app.use((req, res, next) => {
  console.log("middleware3");
  msg += "ccc";
});

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

终端中打印结果:

http://127.0.0.1:81
middleware1
middleware2
middleware3

客户端中响应结果:

aaa
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Node.js是一个基于Chrome V8引擎的JavaScript运行环境,用于构建高性能、可扩展的网络应用程序。它允许我们在服务器端使用JavaScript编写和运行代码,并且具有以下重要的知识点: 1. 异步编程:Node.js采用非阻塞I/O模型,通过事件驱动和回调函数实现异步编程。这使得可以处理大量并发请求而不会阻塞应用程序。 2. 模块化:Node.js支持模块化开发,通过模块系统可以将代码分割成小的、可复用的模块。内置的模块系统提供了大量的核心模块,同时也可以使用第三方模块。 3. 事件驱动:Node.js使用事件驱动的架构,通过触发和监听事件来实现异步处理。核心模块`events`提供了事件的处理能力。 4. 文件系统操作:Node.js提供了对文件系统的操作能力,可以读写文件、创建和删除目录等。核心模块`fs`用于处理文件系统相关操作。 5. 网络通信:Node.js可以创建网络服务器和客户端,通过核心模块`http`和`https`实现HTTP和HTTPS协议的通信。 6. 第三方库和框架:Node.js拥有庞大的第三方库和框架生态系统,如Express.js、Koa.js、Socket.io等,可以加速开发过程。 7. 数据库连接:Node.js可以连接各种数据库,如MySQL、MongoDB、PostgreSQL等。通过相应的驱动程序或ORM框架,可以实现与数据库的交互。 8. 安全性:Node.js有一些内置的安全机制,如防止跨站脚本攻击(XSS)和SQL注入攻击。同时也可以使用第三方模块增强安全性。 这些是Node.js的一些重要知识点,希望对你有帮助!如果你还有其他问题,可以继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值