抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

fs文件系统

读取文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const fs = require("fs");

// 异步读取
fs.readFile('input.txt','utf8', function (err, data) {
//如果读取成功,则err的值为null
//如果读取失败,则err的值为错误对象,dataStr的值为undefined
if (err) {
return console.error(err);
}
console.log("异步读取: " + data.toString());
});

// 同步读取
var data = fs.readFileSync('input.txt');
console.log("同步读取: " + data.toString());

console.log("程序执行完毕。");



//执行结果
同步读取: 文件读取实例

程序执行完毕。
异步读取: 文件读取实例

写入文件内容

1
2
3
4
5
6
7
const fs = require("fs");

fs.writeFile('input.txt', '我是通 过fs.writeFile 写入文件的内容', function(err) {
if (err) {
return console.error(err);
}
})

处理路径问题

__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
2
3
4
5
6
7
8
9
const http = require('http')
const server = http.createServer()
server.on('request', function (req, res) {
console.log('Someone visit our web server.')
})

server.listen(8080, function () {
console.log('服务器启动了,运行在http://127.0.0.1:8080')
})
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
2
3
4
5
6
7
8
9
10
11
12
13
14
//1.导入 express
const express = require('express')
//2.创建 web 服务器
const app = express()
app.get('/user', (req, res) => {
res.send({ name: 'hzx', age: 20, gender: '男' })
})
app.post('/user', (req, res) => {
res.send('请求成功')
})
//3. 启动 web 服务器
app.listen(80, () => {
console.log('express server running at http://127.0.0.1')
})

获取请求参数

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))

模块化路由

为了方便对路由进行模块化的管理,推荐将路由抽离为单独的模块

  1. 创建路由模块对应的.js文件
  2. 调用express.Router()函数创建路由对象
  3. 向路由对象上挂载具体的路由
  4. module.exports向外共享路由对象
  5. 使用app.use()函数注册路由模块

示例代码

1
2
3
4
5
6
7
8
9
10
//router.js
const express = require('express')
const router = express.Router()
router.get('/user/list', (req, res) => {
res.send('Get user list.')
})
router.post('/user/add', (req, res) => {
res.send('Add new user.')
})
module.exports = router
1
2
3
4
5
6
7
8
9
10
11
12
13
//index.js
//1.导入 express
const express = require('express')
//2.创建 web 服务器
const app = express()
//注册路由模块
const router = require('./router')
app.use(router)
//3. 启动 web 服务器
app.listen(80, () => {

console.log('express server running at http://127.0.0.1')
})

中间件

作用:对请求进行预处理

中间件的格式

1
2
3
app.get('/',function(req,res,next){
next()//把流转关系转交给下一个中间件或者路由
})

全局生效的中间件

1
2
3
4
5
6
7
8
9
10
11
12
const app = express()
const mw = function (req,res,next){
console.log('这是最简单的中间件函数')
next()
}
app.use(mw)
app.get('/',(req,res)=>{
res.send('Home Page.')
})
app.get('/user',(req,res)=>{
res.send("User Page")
})

局部生效的中间件

1
2
3
4
5
6
7
8
const app = express()
const mw = function (req,res,next){
console.log('这是最简单的中间件函数')
next()
}
app.get('/',mw,(req,res)=>{
res.send('Home Page.')
})

多个局部生效的中间件

1
2
3
4
5
6
app.get('/',mw1,mw2,(req,res)=>{
res.send('Home Page.')
})
app.get('/',[mw1,mw2],(req,res)=>{
res.send('Home Page.')
})

注意事项

  • 在路由之前注册中间件
  • 客户端发送的请求,可以连续调用多个中间件进行处理
  • 执行完中间件后,要调用next()函数
  • 调用next()函数后,不要再写业务逻辑
  • 多个中间件共享req、res对象

中间件的分类

  1. 应用级别:app.use(),app.get(),app.post()

  2. 路由级别:绑定在express.Router()实例上

  3. 错误级别:function处理函数中必须有4个形参,分别是(err,req,res,next)。必须注册在所有路由之后!

  4. Express内置

    1. express.static快速托管静态资源的内置中间件

    2. express.json解析JSON格式的请求体数据

      1
      2
      3
      4
      5
      app.use(express.json())
      app.post('/user', function (req, res) {
      console.log(req.body)
      res.send('ok')
      })
    3. express.urlencoded({extended:false})解析URL-encoded格式的请求体数据

  5. 第三方

    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
2
const cors = require('cors')
app.use(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方法

预检请求

只要符合以下任何条件之一,都需要进行预检请求:

  1. 请求方式为GET、POST、HEAD之外的请求Method类型
  2. 请求头中包含自定义头部字段
  3. 向服务器发送了application/json格式的数据

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

JSONP接口

浏览器通过<script>标签的src属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做JSONP

JSONP不属于真正的Ajax请求,没有使用XMLHttpRequest这个对象。JSONP仅支持GET请求,不支持POST、PUT、DELETE请求。

JSONP接口要声明在CORS接口之前

操作MySQL

  1. 安装mysql2模块
1
npm i mysql2
  1. 配置mysql模块

    1
    2
    3
    4
    5
    6
    7
    const mysql = require('mysql2')
    const db = mysql.createPool({
    host: '127.0.0.1',
    user: 'root',
    password: '123456',
    database: 'my_db_01'
    })
  2. 测试mysql模块是否正常工作

    1
    2
    3
    4
    db.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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const user = { username:'spider-man', password:'pcc123'}
const sqlStr = 'insert into users (username,password) values (?,?)'
db.query(sqlStr,[user.username,user.password],(err,results)=>{
if(err) return console.log(err.message)
//insert into 的返回结果为对象,select 的结果为数组
if(results.affectedRows === 1) console.log('数据插入成功!')
})


//若对象的属性值与数据表的字段一一对应
const sqlStr = 'insert into users set ?'
db.query(sqlStr, user, (err, results) => {
if (err) return console.log(err.message)
if (results.affectedRows === 1) console.log('数据插入成功!')
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const user = { id: 5, username: 'aaa', password: '000123' }
const sqlStr = 'update users set username=?,password=? where id=?'
db.query(sqlStr, [user.username, user.password, user.id], (err, results) => {
if (err) return console.log(err.message)
//update 的返回结果为对象
if (results.affectedRows === 1) console.log('数据修改成功!')
})


//若对象的属性值与数据表的字段一一对应
const sqlStr = 'update users set ? where id=?'
db.query(sqlStr, [user, user.id], (err, results) => {
if (err) return console.log(err.message)
//update 的返回结果为对象
if (results.affectedRows === 1) console.log('数据修改成功!')
})
1
2
3
4
5
6
const sqlStr = 'delete from users where id=?'
db.query(sqlStr, 5, (err, results) => {
if (err) return console.log(err.message)
//update 的返回结果为对象
if (results.affectedRows === 1) console.log('数据删除成功!')
})

前后端的身份认证

Session认证机制

http的无状态性

客户端的每次HTTP请求都是独立的,服务器不会主动保留每次HTTP请求的状态

突破http的无状态性

设置cookie

Cookie是存储在用户浏览器中一段不超过4KB的字符串。它由一个名称、一个值和其他几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。

客户端第一次请求服务器时,服务器通过响应头的形式,向客户端发送一个身份认证的Cookie。当客户端每次请求服务器时,浏览器自动将身份认证相关的Cookie,通过请求头的形式发送给服务器,服务器即可验明客户端的身份。

使用

1
npm install express-session
1
2
3
4
5
6
7
8
const express = require('express')
const session = require('express-session')
const app = express()
app.use(session({
secret: 'keyboard cat',//可以为任意字符串
resave: false,
saveUninitialized: true
}))

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 1.导入用于生成JWT字符串的包
const jwt = require('jsonwebtoken')
// 2.导入将JWT字符串还原成JSON对象的包
const {expressjwt} = require('express-jwt')

//错误级别的中间件
app.use((err, req, res, next) => {
//token解析失败
if (err.name === "UnauthorizedError") {
return res.send({
status: 401,
message: "无效的token",
})
}
res.send({
status: 500,
message: "服务端错误",
})
})

//.unless({})用来指定哪一些接口不需要访问权限,以下匹配/api/开头的路径
const secretKey = 'Sherlock Holmes ^_^'
app.use(expressjwt({secret:secretKey,algorithms:['HS256']}).unless({path:[/^\/api\//]}))
1
2
3
4
5
6
7
8
9
//登录获取token
app.post('/api/login',function(req,res){
res.send({
status:200,
message:'登录成功!',
//参数1:用户的信息对象,参数2:加密的密钥,参数3:配置对象:可以配置当前token的有效期
token:jwt.sign({username:userinfo.username},secretKey,{expiresIn:'30s'})
})
})
1
2
3
4
5
6
7
8

app.get('/admin/getinfo', function (req, res) {
res.send({
status: 200,
message: "获取用户信息成功!",
data: req.auth
})
})

密码加密

1
npm i bcryptjs

加密存储密码:

1
2
3
4
5
6
var bcrypt = require('bcryptjs');
//生成随机盐
var salt = bcrypt.genSaltSync(10);
//生成加密密码
var hash = bcrypt.hashSync("B4c0/\/", salt);
// 存入数据库

检测密码:

1
2
3
// 从数据库中获取加密密码
bcrypt.compareSync("B4c0/\/", hash); // true
bcrypt.compareSync("not_bacon", hash); // false

自动生成随机盐和哈希值:

1
2
// bcrypt.hashSync(明文密码,随机盐的长度)
var hash = bcrypt.hashSync('bacon', 8);

评论