nodejs官网支持的各种库api
https://nodejs.org/docs/latest-v21.x/api/http.html
nodejs包括vp8引擎和内置的基本库如fs,path,http,querystring等,也可以用npm按转第三方库
npm是nodejs环境的包管理工具,可以为这个环境安装卸载各种包。
npm install pkg
npm uninstall pkg
安装包时会报缺少一个package.json,此时执行npm init就会自动创建,它用来记录这个环境里安装了什么包,这样移植环境时只需要执行npm install或者npm i就可以按着这个文件下载需要的包了。
编写.js文件,用node file.js即可运行
fs文件系统的使用
const fs = require('fs')
//读文件
fs.readFile('./file.txt', 'utf8', function(err, dataStr)){
console.log(err)
console.log('-----')
console.log(dataStr)
console.log('hello world!')
//写文件
fs.writeFile('./file.txt', 'abcd', function(err){if(err){return console.log('文件写入失败' + err.message)}console.log(err)
})
path路径的处理
const path = require('path')
const pathStr = path.join('/a', 'b/c', '../', './d', 'e');
console.log(pathStr)// /a/b/d/e
在浏览器访问80端口的服务器时可以省略端口号,因为80是默认的。浏览器只能发起Get请求
IIS和Apache(php开发人员使用)都是web服务器,而nodejs通过其提供的http模块,几行代码就能实现一个服务器。
nodejs创建web服务器步骤
1.导入http模块
2.创建web服务器实例
3.为服务器实例绑定request事件,监听客户端请求
4.启动服务器
const http = require('http')
const server = http.createServer();
//只要被访问就会触发request监听req对象包括了来访问的客户端的信息,如url代表起访问的目录,method代表了访问的方法如Post或Get。
比如访问127.0.0.1:8080/index.html,那么url就是/index.html,如果访问127.0.0.1:8080,那么默认访问的/目录
server.on('request', function(req, res)
{
console.log('Someone vi@feature:terminalsit our web server.')
})
server,listen(8080, function(){
console.log('server running at http://127.0.0.1:8080')
}
res对象表示返回给客户端的信息
server.on('request', (req, res) => {const url = req.urlconst method = req.method// const str = 'Your request url is ${url}, and request method is ${method}'console.log('Your request url is ' + url + ' method is ' + method)const ch_str = '您请求的是进击的巨人!'//如果不添加的话,浏览器访问中文会乱码,这两个参数是固定的res.setHeader('Content-Type', 'text/html; charset=utf-8')res.end(ch_str)//返回给客户端,并结束响应
})
node.js模块分类
内置模块(如http),自定义模块(用户创建的每个.js文件都是自定义的)
第三方模块,第三方开发,需要先下载才能使用
用require(),加载以上模块
require(‘http’)//
require(‘./test.js’)//自定义模块需要加路径
require(‘moment’)//第三方
require()加载其他模块时,会执行这个模块的代码
模块作用域:只能在当前模块访问的变量和方法,叫做模块作用域,模块默认都是有模块作用域的。
在每个.js自定模块中都有一个module对象,它里面存储了当前模块的有关信息。
在定义模块中,可以用module.exports来把模块贡献出去,默认module.exports的名字为空
const age = 20
module.exports.username = ‘zs’
module.exports.sayHello = function(){}
module.exports.age = age //向外暴露
module.exports比较复杂,exports代表他的简写版本。
require()获取到的地向永远都是module.exports指向的对象,如果没有它的话,那么就导入exports指向的对象。如果两个都设置了,有冲突以moduel.exports为主,没有则合并。
node.js遵循CommonJS模块化规范:
1.每个模块内部,module变量代表当前模块。
2.module变量是一个对象,他的exports属性时对外的接口
3.加载莫个模块,其实就是加载module.exports属性。用require()属性。
npm公司提供了公共的包开发和下载网站,在这个网站可以搜到包,且查看包的api用法,下载命令
https://www.npmjs.com/,并且提供了一个服务器专门去下载包,https://registry.npmjs.org/在这个服务器下载包
npm用@安装指定版本的包
npm i moment@2.22.2
如果已经安装了其他版本不用卸载,会覆盖之前的版本。
npm规定,在项目根目录,必须提供一个package.json的包管理配置文件,用来记录跟项目有关的信息,如:
1.项目的名称,版本号
2.项目用了哪些包
3.哪些包只会开发期间用到
4.哪些包在开发和部署时都需要用到
初次安装包后,会自动创建一个node_modules文件夹,在这个文件夹里还有package-lock.json配置文件。
node_modules是用来存放下载的包的,每个包单独一个文件夹。
package-lock.json用来记录每个包的下载信息,名字,版本号,和下载地址。
快速创建package.json,用下命令
npm init -y
上述命令只能在英文目录下运行,不能在中文下,且英文间不能有空格。
npm install命令安装包时,mpm会自动把包的名称和版本号记录到package.json中的"dependencies"节点,如果没有这个节点会自动创建。
运行npm install会读取package.json中的"dependencies"节点,然后一次性全部下载。
运行以下命令,来卸载指定的包
npm uninstall moment
它会自动去"dependencies"节点去把这个包删除。
devDependencies节点用来记录只在开发阶段使用的包,在项目上线后不会使用的包。"dependencies"节点记录上线会使用的包。
npm i 包名 -D
以上命令指定下载的包记录在devDependencies节点,它等价于以下写法
npm install 包名 --save-dev
如何判断这个包放在哪个节点,可以去官网搜这个包,会有它的安装命令来判断。
使用npm下包时,其实是从官方服务器下载数据,每个数据都要经过海底光缆,因此可以切换为淘宝源。
npm config get registry //查看当前源 默认官方源
npm config set registry=https://registry.npm.taobao.org
nrm切换和查看镜像源的工具
npm i nrm -g //-g 安装全局
nrm ls //列出了当前可用源
nrm use tabao //切换
卸载全局包
npm uninstall 包名 -g
哪些包需要全局安装呢,可以去官方搜一下。只有工具性质的包,才有全局的必要性,它会提供终端命令供使用。
i5ting_toc这个包可以把.md转换为.html
npm i -g i5ting_toc
i5ting_toc -f .md -o .html
package.json必须包含,包名,版本和main,其中main代表着包的入口文件
发布包,需要在官网申请账号https://www.npmjs.com/,然后终端执行
npm login
但需要先把npm源切换到官方源
npm publish
删除已经发布的包
npm unpublish //只能删除72小时以内发布的包
模块的加载机制
加载后的模块会缓存,多次require()并不会重复加载。
内置模块的加载优先级最高
加载自定义模块时必须指定./或者…/开头,不然nodejs会把它当内置模块或者第三方模块加载。
如果没有写扩展名,node做法:
1.按照确切的文件名进行加载
2.补全.js再加载
3.补全.json再加载
Express是对http进行封装的第三方包,用它来作web服务器和api接口服务器比http更加简洁好用。
安装
npm i express@4.17.1
创建web服务器
const express = require('express')
const app = express()
app.get('/user', (req, res)=>{res.send({name:'25', age:20, gender:'男'})
})
app.post('/user', (req, res)=>{res.send('请求成功')
})
//通过req.params对象获取动态参数
// postman的url为http://127.0.0.1:8089/user/2
//其实就是url不用写key值了,key值在服务器里固定了
app.get('/user/:id', (req, res)=>{console.log(req.params) //req.query()默认是空res.send(req.params)
})
//打印和postman得到的值
// {
// "id": "2"
// }
app.listen(8088, ()=>{console.log('express server running at http://127.0.0.1')
})
//将当前clock文件夹下的目录暴露给客户端
//当暴露多个文件时,会按暴露的顺序依次去目录里查找
//https://127.0.0.1:8089/index.html index.html为html目录下的文件,以本文件为相对目录
// app.use(express.static('./html'))//此时访问url必须是https://127.0.0.1:8089/abc/index.html 这是伪装,防止别人知道自己的真实路径
app.use('/abc',express.static('./html'))
//每次修改.js文件,都需要关闭,然后重启,nodemon可以检测.js文件的修改,自动重启
npm install -g nodemon
使用,当修改的文件保存后就会自动重启
nodemon index.js
路由匹配,先匹配方法,再匹配路径,成功就会调用函数。按注册顺序,首先匹配成功就调用,然后不会再匹配了。
app.post('/user', (req, res)=>{res.send('请求成功')})app.post('/user', (req, res)=>{res.send('请求成功')})
路由的模块化
const express = require('express')
const router = express.Router()
router.get('/user/list', (req, res) => {
res.send('Get user list.')
})
router.get('/user/menu', (req, res) => {
res.send('Get user list.')
})
module.exports = router然后在其他文件导入
const userRouter = require('./router/user.js')
//app.use(userRouter)
app.use('/api', userRouter) //那么访问这个userRouter所有的对象时,url都需要加上api前缀
//定义一个最简单的全局中间件函数
//中间件的一个作用,由于所有的中间件公用req和res,那么就可以在上游的中间件中添加自定义的属性或方法,供下游的中间件或路由使用
//什么是中间件,在app.use()函数里的都可以被成为中间件
const mw = function(req, res, next){
console.log('这是最简单的中间件函数')
//把流转关系,转交给下一个中间件或路由
next()
}
//全局生效的中间件,所有访问服务器的请求都会调用
app.use(mw)
const mw = function(req, res, next){console.log('这是最简单的中间件函数')const time = Data.now()req.startTime = timenext()
}
app.use(mw)
app.get('/', (req, res)=>{
res.send('Home page.' + req.startTime)
})
//局部生效的中间件
const mw = (req, res, next) => {
console.log('调用了局部生效的中间件')
next()
}
app.get('/', mw, (req, res) => {
//会先执行mw函数,再执行此函数
res.send({
state:0,
msg:'GET 请求成功!',
data:'dataMSG'
})
})
//定义多个局部中间件
//以下两种写法等价,会依次执行各个中间件
app.get('/', mw1, mw2, (req, res) => { res.send('Home page.')})
app.get('/user', [mw1, mw2], (req, res) => { res.send('Home page2.')})
p48中间件的分类
//什么是跨域(称为CORS),网页打开的地址和ajax访问的地址不同
比如用浏览器打开本地的.html文件,然后点击其页面中的按钮,用Get/Post访问远端的服务器,就叫跨域。
解决跨域的方法
1.CORS(主流的解决方案,推荐使用,它只支持GET,POST,HEAD,不支持PUT,DELETE)
2.JSONP(有缺陷,只支持GET请求)
解决
1.npm install cors
2.const cors = require(‘cors’)
3.在路由之前调用app.use(cors())
CORS请求分为
1.简单请求
2.预简请求,它在正式发送请求之前会发送预请求,来检查服务器是否访问的通。
JSONP:
浏览器通过
在Express中使用Session认证
安装express-session中间件
npm install express-session
var session = require('express-session')
app.use(session({
secret:'keyboard cat',//这个value值可以任意
resave:false//固定写法
saveUninitialized:true//固定写法
}))
向session中存数据
app.post('/api/login', (req, res) => {
if(req,body.username !== 'admin' || req.body.password != '00000'){
return res.send({status:1, msg:'登陆失败'})
}
req.session.user = req.body //用户信息
req,session.islogin = true //登陆状态
res.send({status:0, msg:'登陆成功'})
})
//从session中取数据
app.get('api/username', (req, res) => {
if(!req,session,islogin){
return res.send({status:1, msg:'fail'})
}
res.send({
status:0,
msg:'success',
username:req.session.user.username,
})
})
//清空session,比如用户推出时需要清空
app.post('/api/logout', (req, res) => {
req.session.destroy()
res.send({
status:0,
msg:'退出登陆成功',
})
})
JWT认证机制
Session认证机制需要配合Cookie才能实现,由于Cookie默认不支持跨域访问,所以当涉及到前端跨域请求后端接口的时候,需要很多额外的配置,才能实现Session认证。
当存在在跨域时,推荐使用Session身份认证。
当需要跨域时,不推荐使用Session,推荐使用JWT认证机制。
什么是JWT
JWT(JSON Web Token)是目前最流行的跨域认证解决方案。
JWT的工作原理:
客户端把用户名密码发送给服务器,服务器对用户名和密码加密成字符串,也就是Token,再把它发给客户端,客户端下次请求时通过请求头的Authorization字段,将Token发送给服务器,服务器受到后,把Token解密成用户名和密码,然后再验证,成功则返回给请求的内容。
请求头中Authorization字段:
Authorization:Bearer
JWT机制是把Token保存在客户端的,然后服务器去解密
Session机制是把Cookie保存在客户端和浏览器端的。
Token的组成:
Header.Payload.Signature
Payload是加密后的用户名和密码
Header和Signature是安全性相关的部分,只是为了保证Token的安全性。
sudo snap install postman
参考:B站