fs文件系统
读取文件内容
1 | const fs = require("fs"); |
写入文件内容
1 | const fs = require("fs"); |
处理路径问题
__dirname表示当前文件所处目录
path路径模块
1 | const path = require("path") |
| 方法 | 描述 |
|---|---|
| path.join([path1][, path2][, …]) | 用于连接路径。 |
| path.basename() | 获取路径中的文件名 |
| path.extname(p) | 获取文件的扩展名 |
| path.dirname(p) | 返回路径中代表文件夹的部分 |
| path.resolve([from …], to) | 将 to 参数解析为绝对路径 |
| path.relative(from, to) | xxxxxxxxxx import requestInstance from ‘./http’export { requestInstance as http }typescript |
http
创建服务器
1 | const http = require('http') |
| req请求对象属性 | 描述 |
|---|---|
| req.url | 客户端请求的url地址 |
| req.method | 客户端请求方式 |
| req.session | 访问和使用session对象,需要配置express-session中间件 |
| req.session.destroy() | 清空session对象 |
| res响应对象属性 | 描述 |
|---|---|
| res.end() | 向客户端响应内容 |
| res.writeHead(200, { “Content-Type”: “text/html; charset=utf-8” }) | 写入响应头 |
| res.setHeader(“Content-Type”,”text/html; charset=utf-8”) | 设置响应头的内容类型,解决中文乱码 |
模块化
模块作用域
自定义模块中定义的方法、变量等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
module对象
在每一个.js自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息
- module.exports可以将模块内的成员共享出去,供外界使用。外界用require()方法导入自定义模块时,得到的就是module.exports所指向的对象(也可写成exports)
npm命令
- npm init -y:新建包管理配置文件
- npm uninstall:卸载包
- npm install -D:安装包到开发环境中,这些包只在项目开发环境中用到,如sass,记录在devDependencies节点中
- npm install:安装到开发和生产环境中,记录在dependencies节点中
- npm install -g:安装为全局包
Express
封装的http模块
安装
1 | npm i express |
创建基本的Web服务器
1 | //1.导入 express |
获取请求参数
req.query 通过?匹配到的参数
req.params 通过:匹配到的动态参数
req.body 请求体数据,需要调用express.json()和express.urlencoded({extended:false})中间件
托管静态资源
app.use(express.static(‘public’))
如果要托管多个静态资源目录,多次调用express.static()函数,访问静态资源函数时,根据目录的添加顺序查找所需的文件
挂载路径前缀:app.use(“/public”,express.static(‘public’))
nodemon
nodemon能够监听项目文件的变动,当代码被修改后,nodemon会自动帮我们重启项目。
安装
npm install -g nodemon
使用
nodemon test.js
路由
Express中的路由分3部分组成,分别是请求的类型、请求的URL地址、处理函数
1 | app.METHOD(PATH,HANDLER(req,res)) |
模块化路由
为了方便对路由进行模块化的管理,推荐将路由抽离为单独的模块
- 创建路由模块对应的.js文件
- 调用express.Router()函数创建路由对象
- 向路由对象上挂载具体的路由
- module.exports向外共享路由对象
- 使用app.use()函数注册路由模块
示例代码
1 | //router.js |
1 | //index.js |
中间件
作用:对请求进行预处理
中间件的格式
1 | app.get('/',function(req,res,next){ |
全局生效的中间件
1 | const app = express() |
局部生效的中间件
1 | const app = express() |
多个局部生效的中间件
1 | app.get('/',mw1,mw2,(req,res)=>{ |
注意事项
- 在路由之前注册中间件
- 客户端发送的请求,可以连续调用多个中间件进行处理
- 执行完中间件后,要调用next()函数
- 调用next()函数后,不要再写业务逻辑
- 多个中间件共享req、res对象
中间件的分类
应用级别:app.use(),app.get(),app.post()
路由级别:绑定在express.Router()实例上
错误级别:function处理函数中必须有4个形参,分别是(err,req,res,next)。必须注册在所有路由之后!
Express内置
express.static快速托管静态资源的内置中间件
express.json解析JSON格式的请求体数据
1
2
3
4
5app.use(express.json())
app.post('/user', function (req, res) {
console.log(req.body)
res.send('ok')
})express.urlencoded({extended:false})解析URL-encoded格式的请求体数据
第三方
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17//定义中间件
const bodyParser = (req, res, next) => {
let str = ''
req.on('data', (chunk) => {
str += chunk
})
req.on('end', () => {
req.body = querystring.parse(str)
})
next()
}
module.exports = bodyParser
------------------------------------
//使用中间件
const bodyParser = require('./bodyParser')
app.use(bodyParser)
基于CORS解决跨域问题
安装
1 | npm install cors |
导入并配置
1 | const cors = require('cors') |
注意:先配置cors(跨域资源共享)再配置路由
原理:CORS由一系列HTTP响应头组成,这些响应头决定浏览器是否阻止前端JS代码跨域获取资源。浏览器的同源安全策略(协议、ip地址、端口号必须相同)默认会阻止网页”跨域“获取资源。但是如果接口服务器配置了CORS相关的HTTP响应头,就可以解除浏览器端的跨域访问限制。
| CORS响应头部 | 描述 |
|---|---|
| res.setHeader(‘Access-Control-Allow-Origin’,’*’) | 设置允许访问该资源的外域URL |
| res.setHeader(‘Access-Control-Allow-Headers’,’X-Custom-Header’) | 对额外的请求头进行声明 |
| res.setHeader(‘Access-Control-Allow-Methods’,’*’) | 设置实际请求所允许使用的HTTP方法 |
预检请求
只要符合以下任何条件之一,都需要进行预检请求:
- 请求方式为GET、POST、HEAD之外的请求Method类型
- 请求头中包含自定义头部字段
- 向服务器发送了application/json格式的数据
在浏览器与服务器正式通信之前,浏览器会先发送OPTION请求进行预检,以获知服务器是否允许该实际请求,所以这一次的OPTION请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并携带真实数据。
JSONP接口
浏览器通过<script>标签的src属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做JSONP
JSONP不属于真正的Ajax请求,没有使用XMLHttpRequest这个对象。JSONP仅支持GET请求,不支持POST、PUT、DELETE请求。
JSONP接口要声明在CORS接口之前
操作MySQL
- 安装mysql2模块
1 | npm i mysql2 |
配置mysql模块
1
2
3
4
5
6
7const mysql = require('mysql2')
const db = mysql.createPool({
host: '127.0.0.1',
user: 'root',
password: '123456',
database: 'my_db_01'
})测试mysql模块是否正常工作
1
2
3
4db.query('SELECT 1',(err,results)=>{
if(err) return console.log(err.message)
console.log(results)
})
xxxxxxxxxx import create from ‘zustand’// 导入核心方法import { mountStoreDevtool } from ‘simple-zustand-devtools’// 省略部分代码…// 开发环境开启调试if (process.env.NODE_ENV === ‘development’) { mountStoreDevtool(‘channelStore’, useChannelStore)}export default useChannelStorejavascript
1 | const user = { username:'spider-man', password:'pcc123'} |
1 | const user = { id: 5, username: 'aaa', password: '000123' } |
1 | const sqlStr = 'delete from users where id=?' |
前后端的身份认证
Session认证机制
http的无状态性
客户端的每次HTTP请求都是独立的,服务器不会主动保留每次HTTP请求的状态
突破http的无状态性
设置cookie
Cookie
Cookie是存储在用户浏览器中一段不超过4KB的字符串。它由一个名称、一个值和其他几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。
客户端第一次请求服务器时,服务器通过响应头的形式,向客户端发送一个身份认证的Cookie。当客户端每次请求服务器时,浏览器自动将身份认证相关的Cookie,通过请求头的形式发送给服务器,服务器即可验明客户端的身份。
使用
1 | npm install express-session |
1 | const express = require('express') |
JWT认证机制
session不支持跨域访问,当前端请求后端接口不跨域时,推荐使用session。当前端请求后端接口跨域时,推荐使用JWT(JSON Web Token)
JWT组成成分
Header.Payload.Signature
- Payload是真正的用户信息,是用户信息经过加密后生成的字符串
- Header和Signature是安全性相关的部分,只是为了保证Token的安全性
JWT使用方式
客户端收到服务器返回的JWT后,通常将它存储在localStorage和sessionStorage中
客户端把JWT放在HTTP请求头的Authorization字段中,此后每次通信都要带上这个JWT的字符串,格式如下
1 | Authorization: Bear <token> |
安装及使用
1 | npm install jsonwebtoken express-jwt |
1 | // 1.导入用于生成JWT字符串的包 |
1 | //登录获取token |
1 |
|
密码加密
1 | npm i bcryptjs |
加密存储密码:
1 | var bcrypt = require('bcryptjs'); |
检测密码:
1 | // 从数据库中获取加密密码 |
自动生成随机盐和哈希值:
1 | // bcrypt.hashSync(明文密码,随机盐的长度) |