function (exports, require, module, __filename, __dirname) {
exports:用于暴露模块
require:用于引入模块
module.exports:用于暴露模块
__filename:当前运行文件的绝对路径
__dirname:当前运行文件的文件夹绝对路径
}
1.node中的this不会指向global,而是指向了一个空的对象
2.global常用的属性
(1)clearImmediate:清空立即执行函数
(2)clearInterval:清空循环定时器
(3)clearTimeout:清空延时定时器
1.timers(计时器)
(1)开始计时
(2)执行定时器回调
2.pending callbacks(系统阶段)
3.idle prepare(准备阶段)
4.poll(轮询阶段)
(1)如果回调队列中有待执行的回调函数,从回调队列中取出回调函数依次执行
(2)如果回调队列为空而且你设置了setImmediate进入下一个check
(3)如果回调队列为空你没有设置setImmediate,在此阶段停留,等待回调函数被插入回调队列(不执行定时器回调),定时器到点,进入check阶段,继续向后到第一阶段
5.check
专业执行立即setImmediate的回调
6.close callbacks(关闭回调阶段)
7.process.nextTick()用于设置立即执行函数("人民币玩家vip,在任意阶段优先执行(主线程先执行)")
1.new Buffer-----性能特别差---在堆里开辟空间,然后清理
2.Buffer.alloc()------性能比new Buffer强点---在堆里开辟空间,这块空间没有用过
3.Buffer.allocUnsafe();-----性能最好,未初始化的 Buffer(随机开辟)
4.Buffer.from()----将数据存入一个buffer
1.简单文件的写入
fs.writeFile(file, data[, options], callback){
--file写入文件路径+文件名
* --data写入的数据
* --options可选
* encoding 默认值: 'utf8'
mode 默认值: 0o666=0o222+0o444; 0o111(可被执行权限.exe.msc) 0o222(可被写入的权限) 0o444(可被读取的权限)
flag 默认值:'w':写入 'a':追加
signal <中止信号>允许中止正在进行的写入文件
* --callback回调
* --err错误(错误优先)
}
——————————————————————————————————————————————————————————————
fs.writeFile(__dirname+'/demo.txt', '你好!', (err) => {
if(err){
console.log('文件写入失败'+err);
} else {
console.log('success');
}
})
2.简单文件的读取
fs.readFile(path[, options], callback)
* --path :读取文件路径
--options 可选对象
encoding 默认值: 'utf8'
withFileTypes 默认值: false
--callback
err 错误
files 读取的文件Buffer
——————————————————————————————————————————————————————————————————————————
fs.readFile(__dirname + '/demo.txt', function (err, files) {
if (err) console.log(err);
else console.log(files.toString());
})
1.创建一个文件流
fs.createWriteStream(path[, options])
--options
--flags 默认值:.'w'
--encoding 默认值: 'utf8'
fd默认值: null(文件统一标识符)
mode 默认值: 0o666
autoClose 默认值: true(自动关闭文件)
emitClose 默认值: true(强制关闭文件)
start 读取文件的起始位(偏移量)
fs 默认值: null
2.一定要检测流的状态(开了就要检测)
________________________________________________________________
let ws = fs.createWriteStream(__dirname + '/demo.txt');
ws.on('open', function () {
console.log('可写流打开了');
}
ws.on('close', function () {
console.log('可写流关闭了');
})
// 使用可写流写入数据
ws.write('你好\n');
//检测流状态关闭可写流
ws.close();
const http = require('http');
let server = http.createServer(function (req, res) {
res.end('ok');
});
server.listen(80, function (err) {
if(!err)console.log('服务器启动成功'+'http://127.0.0.1');
})
1.传统型数据库
(1)数据库(2)数据表(3)数据行(4)字段
(5)每个项目对应一个数据库
(6)不同数据存到不同表中
(7)具体信息由字段决定
(8)表中的行代表每一条具体的数据
1.pk主键
2.NN不能为空
3.UQ值唯一
4.AI值自动增长
sql是一门数据库编程语言,只能在关系数据库中使用
插入: insert into 表名 (列名1,列名2)values('第一个值','第二个值')
查询:select 列名 from 表名 (多个列名用,分割)
删除: delete from 表名 where 列名=唯一标识
修改:update 表名 set 列名 = 新值 where 列名=修改对象id(修改多个值时用,隔开)
where子句限制选择标准 <>不等
and和or同时满足多个条件或满足一个
and:where id < 3 and username = 'zs'
or: where id < 3 or username = 'zs'
order by:order by 要按按照排序的列名 (desc降序)
多重排序: order by status desc, username asc
count(*):查询数据的条数
AS;别名
——————————————————————————————————————————————————————————————————————————————————
-- 通过 * 把 users 表中所有的数据查询出来
-- select * from users
-- 从 users 表中把 username 和 password 对应的数据查询出来
-- select username, password from users
-- 向 users 表中,插入新数据,username 的值为 tony stark password 的值为 098123
-- insert into users (username, password) values ('tony stark', '098123')
-- select * from users
-- 将 id 为 4 的用户密码,更新成 888888
-- update users set password='888888' where id=4
-- select * from users
-- 更新 id 为 2 的用户,把用户密码更新为 admin123 同时,把用户的状态更新为 1
-- update users set password='admin123', status=1 where id=2
-- select * from users
-- 删除 users 表中, id 为 4 的用户
-- delete from users where id=4
-- select * from users
-- 演示 where 子句的使用
-- select * from users where status=1
-- select * from users where id>=2
-- select * from users where username<>'ls'
-- select * from users where username!='ls'
-- 使用 AND 来显示所有状态为0且id小于3的用户
-- select * from users where status=0 and id<3
-- 使用 or 来显示所有状态为1 或 username 为 zs 的用户
-- select * from users where status=1 or username='zs'
-- 对users表中的数据,按照 status 字段进行升序排序
-- select * from users order by status
-- 按照 id 对结果进行降序的排序 desc 表示降序排序 asc 表示升序排序(默认情况下,就是升序排序的)
-- select * from users order by id desc
-- 对 users 表中的数据,先按照 status 进行降序排序,再按照 username 字母的顺序,进行升序的排序
-- select * from users order by status desc, username asc
-- 使用 count(*) 来统计 users 表中,状态为 0 用户的总数量
-- select count(*) from users where status=0
-- 使用 AS 关键字给列起别名
-- select count(*) as total from users where status=0
-- select username as uname, password as upwd from users
// 1.导入数据库
const mysql = require('mysql');
// 2.建立数据库连接
const db = mysql.createPool({
host: '127.0.0.1',//数据库的ip地址
user: 'root',//数据库名
password: 'admin123',//数据库密码
database: 'my_db_01'//指定要操作的数据库
});
// 测试mysql模块是否可以正常工作
db.query('SELECT 1', (err, results) => {
//mysql模块工作期间报错
if (err) return console.log(err.message);
//能够成功执行sql语句
console.log(results);
}
// 查询数据
db.query('select * from users', (err, results) => {
if (err) return console.log(err.message);
console.log(results); //执行语句是select查询语句,返回值是一个数组
})
//插入数据
const user = { username: 'sx12', password: 147258 };
// const sqlInsert = 'insert into users (username,password) values (?,?)'//?占位符
// 插入数据的简写
const sqlInsert = 'insert into users set ?';
db.query(sqlInsert, user, (err, results) => {//简写只有数组名
//执行sql语句
// db.query(sqlInsert, [user.username, user.password], (err, results) => {//通过数组为占位符填充数据
//执行失败
if (err) return console.log(err.message);
//成功
if (results.affectedRows === 1) console.log('插入数据成功');
//执行insert语句返回的是一个对象,可以通过affectedRows语句来判断是否插入成功
})
// 更新数据
const user1 = { id: 3, username: 'sa1', password: '000' };
//定义sql语句
// const sqlUpdate = 'update users set username=?,password=? where id=?';
// 更新数据sql语句的简写
const sqlUpdate ='update users set ? where id=?'
//执行的简写
db.query(sqlUpdate,[user1,user1.id],(err,results)=>{
// db.query(sqlUpdate, [user1.username, user1.password, user1.id], (err, results) => {
if (err) return console.log(err.message);
if (results.affectedRows === 1) console.log('更新成功');
//执行update语句返回的是一个对象,可以通过affectedRows语句来判断是否更新成功
})
//删除数据
const sqlDelete = 'delete from users where id=?';
// 执行sqL语句
db.query(sqlDelete, 8, (err, results) => {
if (err) console.log(err.message);
if (results.affectedRows === 1) console.log('删除数据成功');
//执行delete语句返回的是一个对象,可以通过affectedRows语句来判断是否删除成功
})
//标记删除(直接删除危险)
const sqlBJDelete = 'update users set status =? where id=?'
db.query(sqlBJDelete, [1, 2], (err, results) => {
if (err) console.log(err.message);
if (results.affectedRows === 1) console.log('标记删除数据成功');
})
————————————————————————————————————————————————————————————————————————————
2.db连接池
//数据库连接模块
// 1.安装数据库 npm i [email protected]
const mysql = require('mysql');
//创建数据库连接
const db = mysql.createPool({
host: '127.0.0.1',
user: 'root',
password: 'admin123',
database:'my_db_01',
})
//向外共享数据库连接
module.exports = db;
/**
* 非关系:对象文档模型ODM
* 关系:对象关系模型ORM,Node平台更加简单高效操作数据库
*
*
* 连接数据库
*/
let mongoose = require('mongoose');
// mongoose.set('Use createIndexxes', true); 后面的版本不需要
// 连接数据库
mongoose.connect('mongodb://localhost:27017/stu');
//绑定数据库连接的监听
mongoose.connection.on('open', function (err) {
if (err) console.log('数据库连接失败' + err);
else {
console.log('数据库连接成功!');
// 1.请校检(保安)---引入模式对象
let Schema = mongoose.Schema;
// 2.进入规则---创建约束对象
// type:类型
//(1)[String]数组字符串,
//(2)Schema.Types.Mixed接收所有类型
//(3)Date 日期类型
//(4)Date.now() 现在时间
// default:默认值
let stuInfo = new Schema({
name: {
type: String,//限制姓名为字符串
required: true,//姓名是必填项
unique: true // 限制是唯一的(要求重建这个库)
},
age: {
type: Number,
required: true,
}
})
//3.告诉规则 mongoose.model(集合名,规则)---创建模型对象
let stuModel = mongoose.model('students', stuInfo);
//-----新增
// stuModel.create({
// name: 'wz',
// age:18
// }, function (err,data) {
// if (!err) console.log(data);
// else console.log(err);
// })
//-----查询(返回的一定是一个数组)findOne(查找一个就停止)
// stuModel.find({name:'wz'}, function (err,data) {
// if (!err) console.log(data);
// else console.log(err);
// })
//-----更新(update被弃用了)updataMany(匹配多个更新)
// stuModel.updateOne({ name: 'wz' }, { age: 20 }, function (err, data) {
// if (!err) console.log(data);
// else console.log(err);
// })
//-----删除deleteOne(删除一个)deleteMany(删除多个)
stuModel.deleteOne({ age: 18 }, function (err, data) {
if (!err) console.log(data);
else console.log(err);
})
}
})
——————————————————————————————————————————————————————————————————————————————————
mongobd数据库连接池
let mongoose = require('mongoose');
const mongodb = new Promise((resolve, reject) => {
// 1.连接数据库(绑定数据库的监听)
mongoose.connect('mongodb://localhost:27017/stu')
.then(() => resolve("数据库连接成功"))
.catch(() => reject("数据库连接失败"))
})
module.exports = mongodb;
const express = require('express');
// 2.创建服务员(app服务对象)
const app = express();
//禁止服务器返回x-powered-by(什么搭建的服务器)
app.disable('x-powered-by')
// 配置路由---对url请求进行分类(一组组key-value的组合,get+url(/user)和回调函数)
//根据路由定义的顺序,依次定义好路由,随后放入一个类型与数组的结构,请求时依次取出匹配,匹配成功就不再匹配
app.get('/user', function (req, res) {//---/user URI或虚拟路径
// req.query可以获取将查询字符串转换成对象
res.send(req.query.name+'你发送了GET请求!');
})
app.post('/userinfo',function (req,res) {
res.send('你发送了POST请求!')
})
// 3.干活,指定服务器运行的端口
app.listen(80, () => {
console.log('服务器启动成功 http://127.0.0.1');
})
应用层 运输层 网络层 数据链路层 物理层
HTTP超文本传输协议基于tcp/ip协议(UDP面向报文)
请求报文:请求头+请求体
响应报文:响应头+响应体
特定:无状态,cookie和session解决了无状态的问题(无记忆)
报文:
1.报文首
2.报文头
3.空行
4.报文体
问题:从用户输入url按下回车,一直到用户看到页面,期间经历了什么
1.DNS解析
(1)找浏览器dns缓存
(2)找本机dns缓存
(3)找到路由器 DNS 缓存;
(4)找到查询 DNS 缓存 (80% 的 DNS 在查找, 到这一步就结束了)
(5) 递归查询,(查的是全球 13 台 DNS 根服务器的其中一个)
2.运行TCP协议(三报文握手协议)
(1)第一次握手:由浏览器发给服务器(我想给你说话,你能听见吗)
(2)第二次握手:由服务器发给浏览器(我能听见你说吧)
(3) 第三次握手:由浏览器发给服务器(好,开始通讯)
3 发送请求:
4 响应请求:
5.浏览器开始解析html
6.断开TCP连接,四次挥手(确保数据的完整性)
(1)第一次挥手:由浏览器发给服务器(我的东西接受完了。要断开吗)
(2)第二次挥手:由服务器发给浏览器( 我还由一些东西没有接受完,你等一会,我接受完了告诉你,接收完验证数据的完整性)
(3)第三次挥手:由服务器发浏览器(我接收完了,你断开吧)
(4)第四次握手:由浏览器发给服务器(好的,那我断开了)
* 备注:为啥握手3次,挥手4次
* 握手之前还没进行数据传输,确保握手就行了
* 挥手之前,正在进行数据传输,为了确保数据的完整性,必须经历一次验证(继续接收)
200成功
301 重定向:被请求的旧资源已经被永久移除,搜索引擎抓取新内容也将旧的网址替换成重定向之后的网址
302被请求的资源还在,但是会临时跳转一个新资源(必须有前序操作,访问必须登录)
304请求资源重定向到缓存
404请求资源未找到
500服务受到了请求,但是内部发送错误
502连接服务器失败
(1)服务端跳转 1次请求 1次响应
(2)客户端跳转 2次请求 2次响应(重定向)
1.req:
req.query 获取查询字符串参数拿到对象(post和get都行,一般post请求不带查询字符串参数)
req.params 获取get请求参数路由的参数,拿到是一个对象
req.body 获取post请求体参数,拿到的是一个对象(不可以直接用要借用中间件,配置解析json格式中间件)
req.get 获取请求头中指定的key对应的value
2.res:
res.send给浏览器做出响应
res.end给浏览器做出响应(不会追加响应头)
res.dowload告诉浏览器下载一个文件
res.sendFile给浏览器发送文件
res.redirect重定向到新的地址
res.set自定义响应头内容
res.get或者响应头指定的key对应的value
res.status 设置响应状态码
中间件:-------自己在写路由器模块是将要把其整理成一个函数
本质:就是一个函数包含三个参数:req,res,next
作用:
--执行任何代码
--修改请求和响应对象
--终结请求
--调用堆栈中的下一个路由和中间件
1.body-parser(解析的中间件可以解析JSON,Raw,文本,URL-encoded格式的请求体)
2.cors(用于跨域请求的中间件)
3.multer 解析 multipart/form-data
4.cookie-parser解析cookie中间件
1.密码加密模块 bcrypyjs md5 sha1
2.连接关系数据库mysql
3.连接非关系数据库mongoose
4.jsonwebtoken加密jwt
5.connect-mongo将session存入数据库
6.解析token的中间件express-jwt
1.session的简单介绍
session是一种保存上下文信息的机制,保存的是对象,它的值是存放在服务器端,它通过sessionId来区分不同的客户端,
而sessionId是保存在客户端的,做为客户端与服务器的验证标识,它是一个24位的随机字符串,用户每次提交页面时,
浏览器都会把这个sessionId包含在HTTP头中提交给WEB服务器,session的持久化(存带硬盘中,数据库)
2.session的产生过程
当服务器接收到客户端的请求,要求产生一个session时,服务器会先检查下,客户端的cookies中是否有sessionId,
并且判断它是否过期。若有sessionId且还没有过期,则会根据该sessionId值将服务器中的session检索出来;否则,
将产生一个新的session,当创建一个新session后,服务器也会产生一个sessionId号,回写客户端的cookies当中。
3.cookies的主要组成
cookies主要由cookies名,cookies值,过期时间和域,路径等组成。若对过期时间进行设置,则cookies会被保存在硬盘上;
若没有,则cookies被保存在浏览器内存中。
4.主要区别
a.session 是保存在服务器端,客户端无法知道其中的信息;而cookies是保存在客户端的,服务器端可以知道其中的信息;
b.session保存的是对象,而cookies保存的是字符串;
c.session不区分路径,同一个用户在同一个网站期间,所有的session在任何一个地方都可以访问到。而cookies是区分路径的,
如果设置了路径参数,那么同一个网站不同路径下的cookies是互相访问不到的
,要求产生一个session时,服务器会先检查下,客户端的cookies中是否有sessionId,
并且判断它是否过期。若有sessionId且还没有过期,则会根据该sessionId值将服务器中的session检索出来;否则,
将产生一个新的session,当创建一个新session后,服务器也会产生一个sessionId号,回写客户端的cookies当中。
3.cookies的主要组成
cookies主要由cookies名,cookies值,过期时间和域,路径等组成。若对过期时间进行设置,则cookies会被保存在硬盘上;
若没有,则cookies被保存在浏览器内存中。
4.主要区别
a.session 是保存在服务器端,客户端无法知道其中的信息;而cookies是保存在客户端的,服务器端可以知道其中的信息;
b.session保存的是对象,而cookies保存的是字符串;
c.session不区分路径,同一个用户在同一个网站期间,所有的session在任何一个地方都可以访问到。而cookies是区分路径的,
如果设置了路径参数,那么同一个网站不同路径下的cookies是互相访问不到的