nodejs介绍
nodejs是js的一个独立的运行环境,有着其内置的API(没有浏览器的dom,bom)
npm指令
npm init -y-- 对package.json进行初始化npm i-- 安装dependencies中所有的依赖npm i 包名-- 安装指定包npm i 包名 -S-- 安装到dependencies中npm i 包名 --save-- 安装到dependencies中npm i 包名 -D-- 安装到devDependencies中npm i 包名 -g-- 全局安装npm uninstall 包名-- 卸载包npm uninstall 包名 -g-- 卸载全局包npm i 包名@版本号-- 安装指定版本的包npm i 包名@版本号 -g-- 安装指定版本的包npm i 包名@版本号 -S-- 安装指定版本的包到dependencies中npm i 包名@版本号 -D-- 安装指定版本的包到devDependencies中npm list -g --depth=0-- 查看全局第三方包npm config set registry <镜像地址>-- 切换下载第三方包镜像
devDependencies中的依赖包不会直接影响生产环境,但在开发过程中非常有用. 例如:nodmeondependencies用于于表示项目运行时需要的依赖。这些依赖项直接影响生产环境,通常包括项目的主要功能和库, 例如:axios
require()导入
基本使用
const fs = require("fs");当使用require导入不写扩展名时, 会分别尝试加载文件后缀
- 按照确切文件名加载
- 补全
.js - 补全
.json - 补全
.node - 加载失败
fs文件操作模块
fs模块是nodejs内置的模块, 可以直接使用require导入
const fs = require("fs");下面会介绍它的方法以及使用
readFile
- 作用: 读取文件
- 声明:
readFile(path, BufferEncoding, (err, data) => void): void path: 路径BufferEncoding: 字符集, 通常是utf-8err: 错误信息data: 读到的数据
//path can use relative path or absolute path
fs.readFile("../成绩.txt", "utf-8", (err, data) => {
if(err) throw err;
console.log(data);
})
//使用绝对路径
fs.readFile(path.join(__dirname, "../", "/成绩.txt"), "utf-8", (err, data) => {
if(err) throw err;
console.log(data);
})假设
file.js为当前文件所处目录, 例如: 当前路径为C:\Users\wang\Desktop\nodeJs\axios\file.js,
__dirname--->C:\Users\wang\Desktop\nodeJs\axios__filename--->C:\Users\wang\Desktop\nodeJs\axios\file.js
writeFile
- 作用: 写入文件
- 声明:
writeFile(path, data, (err) => void): void path: 路径, 可以是绝对路径, 也可以是相对路径data: 需要写入到文件的数据err: 错误信息
- 方法只能用来创建文件,不能创建路径。
- 重复用此方法写入同一文件,新写的内容会覆盖之前旧的内容
//写入内容 "123"
fs.writeFile("../成绩.txt", "123", (err) => {
if(err) throw err;
console.log("ok");
})mkdir和rmdir
- 作用: 创建文件夹和删除文件夹
- 声明:
mkdir(path, (err) => void): void path: 路径, 可以是绝对路径, 也可以是相对路径err: 错误信息
//当前文件的外部添加一个文件夹, 名为test1
fs.mkdir("../test1", (err) => {
if(err) throw err;
console.log("ok");
})
fs.rmdir("/test1", (err) => {
if(err) throw err;
console.log("ok");
})readdir
- 作用: 阅读一个文件夹的目录结构
- 声明:
readdir(path, (err, files) => void): void
[
'1.express-session中间件.js',
'cookie-parser.js',
'demo.ejs',
'ejs.js',
'joi.js',
'jwt.js',
'login.js',
'mysql2.js',
'nodemailer.js',
'proxy.js',
'static1.js'
]path路径模块
导入模块
const path = require("path");join
- 拼接路径, 返回值为
string - 声明:
join(...paths: string[]): string
fs.readFile(path.join(__dirname, "../", "/成绩.txt"), (err, data) => {/* ... */})
../会抵消前面的一层目录. 例如, 当前目录为:C:\Users\wang\Desktop\nodeJs\join.js, 使用../之后, 就是C:\Users\wang\Desktop\nodeJs然后在
/成绩.txt, 最终路径就是C:\Users\wang\Desktop\nodeJs\成绩.txt
basename
- 获得文件存放路径
- 声明:
basename(path, suffix): string suffix是后缀
path.basename("成绩.txt", ".txt");// 成绩extname
- 作用: 获取路径中的扩展名
- 声明:
extname(path): string
path.extname("成绩.txt")// .txthttp与https模块
创建服务器并开启监听
req包含许多客户端请求发来的信息res包含许多服务器响应发来的信息
const http = require('http');
// 创建服务器
const server = http.createServer((req, res) => {
// 处理请求
res.statusCode = 200;//设置状态码
//设置响应请求头
res.setHeader('Content-Type', 'text/plain');
// 原生nodejs中end方法只可以发送string类型, 如果是其他类型会报错
res.end(JSON.stringify({a: "我是傻逼"}));
});
// 监听端口
const port = 3000;
server.listen(port, () => {
console.log(`http://localhost:${port}/`);
});访问
http://localhost:3000会放回字符串{a: "我是傻逼"}, 一般来说前端会对JSON字符串进行转换
get和post发送网络请求
const http = require('http');
const https = require("https");
// 创建服务器
const server = http.createServer((req, res) => {
let str = "";
//一个https的网站, 对应的就要使用https模块发请求, chunk其实就相当于req的功能
https.get("https://developer.mozilla.org/api/v1/whoami",(chunk) => {
//data流, 对方服务器向我们传递的数据, 而这个数据会像流一样流到我们这, 所以on方法可能会触发好几次
chunk.on("data", (data) => {
str += data;
});
//当data数据流结束时, 这回调用这个函数
chunk.on("end", () => {
console.log(JSON.parse(str));
res.end(str);
})
})
})http中的
get与post函数参数一致
{
geo: { country: 'China', country_iso: 'CN' },
username: null,
is_authenticated: null,
email: null,
avatar_url: null,
is_subscriber: null,
subscription_type: null,
settings: null
}request发送请求
http中的request方法可以发送任何类型的请求, 例如: get, post, delete, put, putch, 等等.
- 声明:
request(options, (res) => void): void
options的参数有:
hostname-- 请求的主机名port-- 请求的端口path-- 请求的路径method-- 请求的方法headers-- 请求的头部信息authuser-- 用户名password-- 密码
let str = "";
https.request({
hostname: "localhost",
port: 3000,
path: "/test",
method: "get",
headers: { "Content-type": "application/json" },
auth: {
user: 'username',
pass: 'password',
}
} , (chunk) => {
chunk.on("data", () => {
str += chunk;
})
chunk.on("end", () => {
console.log(str);
})
})各类请求头以及参数
Content-Type
指定信息体的类型, 例如: query, params, body
消息体包含HTML内容、JSON数据、图像、文件等各种类型的数据
- 指示接收者如何处理消息体:
Content-Type告诉接收者如何解析、处理消息体的数据格式。通过指定适当的Content-Type,接收者可以根据该类型来决定如何正确解析和处理传输的数据. - 控制浏览器行为:在Web开发中,通过设置适当的
Content-Type,可以控制浏览器的行为。例如,Content-Type: image/jpeg会告诉浏览器显示接收到的数据作为JPEG图像。不同的Content-Type类型会触发浏览器采取不同的处理方式,如显示图像、下载文件等。 - 内容协商:当客户端向服务器发送请求时,可以使用
Accept头部指定可接受的Content-Type类型,服务器可以根据这些信息来选择合适的响应类型。通过内容协商,客户端和服务器可以就请求和响应的内容类型达成一致,提供更适合的数据格式。 - 防止安全漏洞:在文件上传和处理表单数据时,正确设置
Content-Type可以帮助防止潜在的安全问题。例如,在接收文件上传时,要确保把正确的Content-Type与文件的实际类型匹配,以防止恶意上载的文件被错误地解释和执行。
参数如下:
application/x-www-form-urlencoded-- 用于在HTTP请求中传输表单数据, 数据形式为键值对key1=value1&key2=value2&..., 并在请求的正文中作为纯文本传输。application/json-- 发送JSON字符串, 对应的后端或者前端都会做对应的处理text/plain-- 纯文本文件text/html-- HTML文档text/css-- CSS样式表application/xml-- XML数据image/jpeg: JPEG图像文件,image/png: PNG图像文件,image/gif: GIF图像文件,audio/mpeg: MPEG音频文件audio/ogg: Ogg音频文件video/mp4: MP4视频文件video/ogg: Ogg视频文件
Content-Length
Content-Length是HTTP消息头的一个字段,用于指示请求或响应中的消息体的长度,以字节为单位。它告诉接收方要接收的实体主体的长度,以便正确解析和处理消息。
对于请求,Content-Length字段通常出现在具有消息体(如POST请求)的请求中,它告诉服务器要读取的数据的长度。
对于响应,Content-Length字段通常出现在具有消息体(如响应主体)的响应中,它告诉客户端接收的数据的长度。
模块作用域以及module
模块作用域保证模块内定义的成员不在外界被访问(防止变量冲突,解决全局变量的污染)
而module.export方法可以将变量导出, 供其他模块使用. 而module.export本身就是一个对象
导出
module.export.a = 1;使用接收
const { a } = require('./module.js');dotenv
npm i dotenv -- savedotenv通常配合.env文件一起使用, 作用是配置环境变量, 例如: .env文件中的NODE_ENV=development
const dotenv = require('dotenv');
//配置完之后就可以访问process.env了
dotenv.config();
console.log(process.env.APP_PORT);// 1APP_PORT = 1注: 在
.env文件中只有string类型
morgan搭配chalk
morgan是一个日志工具, 可以记录请求信息, 而chalk是一个美化日志的工具, 可以让日志显示不同的颜色
- 安装
npm i morgan chalk@4 --save注意:
chalk5版本是ESM, 如果你想要在node环境下使用, 或者typescript中搭建项目, 你需要使用chalk4
import express from 'express';
import morgan from 'morgan';
import chalk from 'chalk';
app.use(morgan(`${chalk.yellowBright(":method")} - ${chalk.greenBright("{:url}")} - ${chalk.green(":status")} - ${chalk.red(":response-time ms")} - :res[content-length] - ${chalk.yellow(":remote-addr")}`));morgan的功能
Morgan中间件有着几种模式, 同时你也可以自定义模式(以上chalk和morgan搭配就是自定义模式)
固定模式
combinedcommondevtinyshort
// :method :url :status :res[content-length] - :response-time ms // :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" // :status :res[content-length] ":referrer" ":user-agent"
chalk
chalk可以改变控制台中字体的颜色
express
安装模块
npm i express --save基本使用
const express = require("express");
const app = express();
app.get("/test", (req, res) => {
res.send("Hello World!");
}
app.listen(8080, () =>{
console.log("127.0.0.1:8080");
})使用
get请求访问http://localhost:8080/test, 返回Hello World!
express-session
session在网络应用中称为“会话控制”,是服务器为了保存用户状态而创建的一个特殊的对象。简而言之,session就是一个对象,用于存储信息。 服务器会为每一个游览器(客户端)创建一个唯一的session。这个session是服务器端共享,每个游览器(客户端)独享的。我们可以在session存储数据,实现数据共享。
安装模块
npm i express-session --save//设置session中间件
app.use(session({
//服务器生成的session签名
secret: "handsome",
//向前端发送cookie的name
name: "wangjia",
resave: true,
//强制将初始化的cookie存储, 即一开始就把cookie发送过去
saveUninitialized: false,
/*
在每次请求时强行设置 cookie,这将重置 cookie 过期时间
为true时, 超时前刷新, cookie会重新计时, 为false表示在超时前刷新几次, 都是按照第一次刷新开始计时
*/
rolling: true,
cookie: {
//是否仅通过HTTP传输cookie
httpOnly: true,
// cookie的过期时间, 按照毫秒计算
maxAge: 9999,
//为true时, 表示只有https协议才可以访问cookie. 是否只通过HTTPS传输cookie
secure: false,
}
}))mysql的连接以及使用
- 安装
npm i mysql2 --save
mysql2有着更多的功能
- 使用
//导入mysql2, 这里的promise指的是方法返回值为promise对象
import mysql from "mysql2/promise";
//创建连接池
const db = mysql.createPool({
//主机ip地址
host: "localhost",
//mysql账号
user: "root",
//mysql密码
password: "root",
//需要进行操作的数据库名称
database: "manage_system",
//端口
port: 3306
})
//测试连接是否成功
async function test(sql: string) {
try {
const [result, field] = await db.query(sql);
console.log("连接成功");
} catch (error) {
throw error;
}
}
test("select 1");
//导出
export default db;jsonwebtoken
JWT机制
token实际上就是一个字符串, 它有着三个部分: header, payload, signature. 而它的作用是防止数据被伪造和篡改
那么首先就需要说没有jwt的时代下, 前端发送给服务器的信息, 我们是不知道这数据是正常的, 被伪造的, 还是被修改过的.
而jwt的生成需要数据(data)和密钥(secret), 生成过后发送给前端, 前端在发送数据给给服务器时, 会携带着token, 服务器会根据密钥(secret)和发送过来的数据(data)重新生成一个token, 如果生成的token和发送过来的token一致, 那么说明数据没有被篡改, 如果不一致, 那么说明数据被篡改了.
最终token的形式为:
header.payload.signatureheader:
header中存储的是token的类型和加密方式, 一般为JWT和HS256, 经过base64格式转换(不是加密, 经过btoa方法转换,atob方法解码)payload:
payload中存储的是数据, 一般存储用户的id, 用户名等, 经过base64格式转换(不是加密)signature:
signature是header和payload通过密钥(secret)加密生成的, 用于验证数据的完整性和真实性
//header经过base64转换后的数据
{ "alg": "HS256", "typ": "JWT" } ===> headers
{ "name": "12222" } ===> payload
header.payload 通过秘密加载生成了签名 ===> signature- 安装
npm i jsonwebtoken --save
npm i @types/jsonwebtoken -D- 使用
生成签名: jwt.sign(payload, secret, options)
options配置:
algorithm-- 算法, 默认为HS256expiresIn-- 过期时间, 默认为14dnotBefore-- 在什么时间之前不可用, 默认为0audience-- 接收人issuer-- 发送人jwtid--JWT的ID
import jwt from "jsonwebtoken";
//通过sign方法生成tokenredis使用方式
- 安装
npm i ioredis --save
npm i @types/ioredis -D- 使用
import Redis from "ioredis";
/* 使用redis代替session的使用, 因为session是存储在服务器当中, 当访问量足够大时, 服务器负载就很吃力.
而redis是在内存中运行的, 同时数据也是可以共享的
1. 首先需确保key的唯一性
2. 方便携带
如果我们采用phone:手机号这个的数据来存储当然是可以的,但是如果把这样的敏感数据存储到redis中并且从页面中带过来毕竟不太合适,
所以我们在后台生成一个随机串token,然后让前端带来这个token就能完成我们的整体逻辑了
*/
const redis = new Redis({
host: '192.168.159.134',
port: 6379,
password: 123456
})
//导出redis
export default redis;使用redis代替session的使用, 因为session是存储在服务器当中, 当访问量足够大时, 服务器负载就很吃力. 而redis是在内存中运行的, 同时数据也是可以共享的
数据库的数据会发生变化, 这时需要确保redis中的数据是最新的
对此应该先操作数据库, 再删除缓存.