Node.js笔记

Nvm版本控制

由于node版本与node项目存在兼容性问题,所以我们可以通过nvm管理node的版本

nvm的下载地址:https://github.com/coreybutler/nvm-windows/releases

关于nvm配置镜像

在D:\Java\Nvm\settings.txt里配置:

node_mirror: https://npmmirror.com/mirrors/node/
npm_mirror: https://npmmirror.com/mirrors/npm/
nvm list available查询镜像仓库node版本列表
nvm on启用版本管理
nvm install 12.22.0下载指定版本
nvm use 12.22.0

查看node版本:

node -v

运行js文件:

node 1.js

按住shift+鼠标右键:打开Power Shell,PS是新的cmd

npm类似maven包管理工具

npm设置阿里镜像:

npm config set registry http://registry.npm.taobao.org

fs模块

文件模块

文件的读取:

const fs = require('fs')
fs.readFile('./1.txt', 'utf8', function (err, dataStr) {
    // 读取失败后的值,如果成功就是null,如果失败就是异常原因
    if (err) {
        return console.log('文件读取失败:' + err.message)
    }
    console.log(dataStr) // 读取成功后的值
})

文件的写入:

// 如果文件不存在会自动创建
fs.writeFile('./1.txt', 'BCD', 'utf8', function (err) {
    if (err) {
        console.log('文件写入失败:' + err.message)
    }
})
// 简写
fs.writeFile('./1.txt', 'AAA', function (err) {
    if (err) {
        console.log('文件写入失败:' + err.message)
    }
})

__dirname:当前文件所在目录

__filename:__dirname本文件全名

path模块

路径拼接

const path = require('path')
let s=path.basename(__filename)
console.log(s) // 拿到当前文件名和路径名
s=path.basename(__filename,'.js') // 去掉扩展名
path.join('1','2','3') // 会自动加斜杆 1\2\3
s = path.extname(__filename) // 获取文件后缀名

path里面可以用../回退

@/        src目录

// 正则表达式匹配出符合条件的字符串
const regStyle = /<style>[\s\S]*<\/style>/
dataStr = regStyle.exec(dataStr)

http模块

http模块是创建web服务器的模块

const http = require('http')
// 创建实例
const server = http.createServer()
// 事件绑定
server.on('request', (req, res) => {
    res.setHeader('Content-Type', 'text/html;charset=utf-8')
    const url = req.url
    if ('/' === url) {
        const fpath = path.join(__dirname, 'index.html')
        fs.readFile(fpath, 'utf8', function (err, dataStr) {
            if (err) {
                return console.log('文件读取失败:' + err.message)
                res.end("404")
            } else {
                res.end(dataStr)
            }
        })
    } else {
        res.end("404")
    }
})
// 启动服务
server.listen(80, () => {
    console.log('服务器启动了')
})

模块化开发

// 内置模块:fs、path、http
const fs = require('fs')

// 自定义模块:用户自定义js文件,可以省略后缀名
// 变量不会引入
const custom=require('./custom')

// 第三方模块:例如:vue
const moment=require('moment')

module对象

每个自定义js模块都有一个module对象,它存储了和当前模块有关的信息

模块向外共享对象:

let username = 'tom'
module.exports.username = username
module.exports.sayHello = function () {
    console.log("hello")
}
// 另一种写法
module.exports = {
    username: 'tom',
    sayHello() {
        console.log('hello')
    }
}

外界引入模块共享的对象:

const index = require('./module/index')
// { username: 'tom', sayHello: [Function: sayHello] }
console.log(index)

npm包

npm包由第三方个人或团队提供的,免费开源

查看npm的版本:

npm -v

安装第三方包:

例如:安装moment日期格式化工具

npm install moment
// 简写
npm i moment

node_moudules:

下载好了的包放在这里,存放已安装到项目中的包,require()就是从这个目录加载

package-lock.json:配置文件,记录node_moudules目录下的包的下载信息(版本等)

package.json:记录与项目有关的一些信息

安装并指定版本:

// 2 大版本 大版本升级了,后面的小版本都重置为0
// 29 功能版本
// 4 bug修复版本
npm i moment@2.29.4

多人协作:

// 打包删除node_moudules,不然太浪费了,留package.json就行了

拿到别人项目后导包到node_moudules:

npm i

-f 强制安装

运行

npm run dev

 dependencies节点:

执行完导包命令后会package.json里会出现这个节点,记录用npm i命令安装了哪些包

卸载包:

npm uninstall moment

devDependencies节点:

一些包只在开发的时候用到,生产的时候不用到就放到devDependencies中,而dependencies节点是开发和生产过程都会用到

 如何安装到devDependencies节点:

npm install moment --save-dev
// 简写
npm i moment -D

解决下包速度慢的问题:

换成阿里的镜像:

npm config set registry=https://registry.npmmirror.com/

Express

基于node.js的web的http模块封装的更强大的框架,功能比node.js的http模块更强大

案例:

const express = require('express')
const app = express()
app.listen(80, () => {
    console.log('服务器启动了')
})
app.get('/', function (req, res) {

    // 第一种接收方式
    // http://localhost?name=tom
    let query = req.query
    console.log(query) // { name: 'tom' }

    // 第二种接收方式,适合RestFul风格
    // app.get('/:id'
    // http://localhost/123
    let params = req.params
    console.log(params) //{ id: '123' }

    res.send('0')
})

托管静态资源目录:

// static目录作为静态资源文件夹托管出去
// localhost/index.html 不包含static本身
// 如果要托管多个目录,就多次编写
app.use(express.static('./static'))

// localhost/public/index.html 要加public目录才能访问到
app.use('/public',express.static('./static'))

nodemon热部署模块:

-g        是全局安装

安装:

npm i nodemon -g nodemon

启动:

nodemon index.js

模块化路由

将路由写在模块中,然后再引入模块

模块:

const express = require('express')
const router = express.Router()
// 创建路由对象
router.get('/:uid', function (req, res) {
    res.send('查询对象成功' + req.params.uid)
})
router.post('/', function (req, res) {
    res.send('新建用户成功')
})
module.exports = router

主模块:

const express = require('express')
const app = express()
const user = require('./router/user')
// 统一访问前缀
app.use('/user', user)
app.listen(80, () => {
    console.log('服务器启动了')
})

 中间件:

app.use():注册中间件

中间件函数:类似是Spring的AOP,特点是可以在方法之前运行

全局中间件:

// 在方法前执行
const mw = function (req, res, next) {
    console.log('ABC')
    // 调用下一个方法
    next()
}
app.use(mw)
// 简便写法
app.use((req, res, next) => {
    console.log('ABC')
    // 调用下一个方法
    next()
})

局部中间件:

const mw1 = function (req, res, next) {
    console.log('我是局部中间件函数1')
}
const mw2 = function (req, res, next) {
    console.log('我是局部中间件函数2')
}
// 局部中间件生效
app.get('/', mw1,mw2, (req, res) => {
    res.send('0')
})
// 局部中间件不生效
app.get('/user', (req, res) => {
    res.send('0')
})

以上的是应用级别的中间件,下面是路由级别的中间件:

const express = require('express')
const app = express()
const router = express.Router()
router.use((req, res, next) => {
    next()
})
app.use('/', router)

错误级别的中间件:

作用:专门用来捕获项目中的异常,防止项目崩溃,必须注册在路由之后,这样才能捕获住

例如:

app.get('/', (req, res) => {
    throw new Error('服务器发生了错误')
    res.send('hello')
})
app.use((err, req, res, next) => {
    console.log('发生了错误:' + err.message)
    res.send('err:' + err.message)
})

3个内置中间件:

express.static:静态托管中间件

app.use(express.static('./cors'))
 

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

app.use(express.json())

express.urlencoded 解析encoded格式的数据

app.use(express.urlencoded({extended:false}))

服务器通过 req.body 来获取数据

如果没有配置任何解析表单数据的中间件,则req.body的值为undefined

第三方中间件:

比如body-parser

// 安装
npm i body-parser
// 导入
const parser = require('body-parser')
// 使用
app.use(parser.urlencoded({extended: false}))

app.post('/user', (req, res) => {
    let body = req.body
    console.log(body)
    res.send(body)
})
// express内置的express.urlencoded中间件,就是基于body-parser这个第三方中间件封装出来的

自定义中间件:

const express = require('express')
const app = express()
const qs = require('querystring')
// 自定义中间件
app.use((req, res, next) => {
    let str = ''
    req.on('data', (chunk) => {
        str += chunk
    })
    // 数据接收完毕 xwfu格式
    req.on('end', () => {
        console.log(str)
        // 用querystring模块解析数据
        // [Object: null prototype] { name: 'tom', age: '18', sex: '1' }
        req.body = qs.parse(str)
        console.log(req.body)
    })
    console.log('我是自定义中间件')
    next()
})
app.get('/', (req, res) => {
    res.send(req.body)
})
app.listen(80, () => {
    console.log('服务器启动了')
})

将自定义中间件模块化:

const qs = require('querystring')
// 自定义中间件
const bodyParser = (req, res, next) => {
    let str = ''
    req.on('data', (chunk) => {
        str += chunk
    })
    // 数据接收完毕 xwfu格式
    req.on('end', () => {
        // console.log(str)
        // 用querystring模块解析数据
        // { name: 'tom', age: ' 18', sex: '1' }
        req.body = qs.parse(str)
        console.log(req.body)
    })
    console.log('我是自定义中间件')
    next()
}
module.exports = bodyParser
const express = require('express')
const app = express()
const cbp = require('./module/custom-body-parser')
app.use(cbp)
app.get('/', (req, res) => {
    res.send(req.body)
})
app.listen(80, () => {
    console.log('服务器启动了')
})

创建本地基本服务器案例:

const express = require('express')
const apiRouter = express.Router()
apiRouter.get('/:id', (req, res) => {
    let result = {
        status: 0,
        msg: '',
        data: ''
    }
    result.msg = '查询用户成功:' + req.params.id
    res.send(result)
})
apiRouter.post('/', (req, res) => {
    const body = req.body
    let result = {
        status: 0,
        msg: '新增用户成功',
        data: ''
    }
    result.data = body
    console.log(body)
    res.send(result)
})
module.exports = apiRouter
const express = require('express')
const app = express()
const apiRouter = require('./module/apiRouter')
// 全局中间件
app.use(express.urlencoded({extended: false}))
app.use('/apiRouter', apiRouter)
app.listen(80, () => {
    console.log('服务器启动了')
})

解决cors跨域问题:

协议,域名,端口有一个不同都会出现跨域问题。cors主要在服务器端配置。

npm i cors
// 解决跨域问题
const cors = require('cors')
// 在路由之前
app.use(cors())

整合MySql:

npm i mysql
// 导入
const mysql = require('mysql')
// 配置连接
const db = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: 'root',
    database: 'my_db_01'
})
// 测试
db.query('select 1', (err, result) => {
    if (err) {
        console.log('连接数据库失败:' + err)
    } else {
        console.log('连接数据库成功')
    }
})

查询语句:

// 使用案例
let sqlStr = 'select * from user'
db.query(sqlStr, (err, result) => {
    if (err) {
        console.log('查询语句失败:' + err.message)
    } else {
        console.log(result)
    }
})

插入语句:

// 插入语句
let sqlStr = 'insert into user(username,password,created_time) values(?,?,?)'
const user = {username: 'rose', password: 'rose', created_time: new Date()}
db.query(sqlStr, [user.username, user.password, user.created_time], (err, result) => {
    if (result.affectedRows === 1) {
        console.log('插入数据成功')
    } else {
        console.log('插入语句失败:' + err.message)
    }
})

更新语句:

// 更新语句
let sqlStr = 'update user set username=?,password=? where uid=?'
const user = {uid: 9, username: '666', password: '666'}
db.query(sqlStr, [user.username, user.password, user.uid], (err, result) => {
    if (result.affectedRows === 1) {
        console.log('更新数据成功')
    } else {
        console.log('更新语句失败:' + err.message)
    }
})

身份认证:

http请求是无状态的,每次请求都是独立的

session:服务器保存用户状态,客户端自动存储,自动发送

session的使用:

npm i express-session
// 导入
const session = require('express-session')
// 配置
app.use(session({
    secret: 'itheima', // 任意字符
    resave: false, // 固定写法
    saveUninitialized: true // 固定写法
}))

案例:

// 解析解析xwfu的body
app.use(express.urlencoded({extended: false}))
app.post('/api/login', (req, res) => {
    if (req.session.isLogin === true) {
        return res.send({
            status: 0,
            msg: '登录成功'
        })
    } else if (req.body.username != 'root' || req.body.password != 'root') {
        return res.send({
            status: -1,
            msg: '登录失败'
        })
    } else {
        req.session.user = req.body
        req.session.isLogin = true
        return res.send({
            status: 0,
            msg: '登录成功'
        })
    }
})

清除session:

app.get('/api/logOut', (req, res) => {
    // 清空session
    req.session.destroy()
    res.send({
        status: 0,
        msg: '退出登录成功'
    })
})

jwt:用户保存用户状态,token里面会包含用户的信息,服务器不存数据,服务器拿到token后解密

安装:

npm i jsonwebtoken express-jwt

jsonwebtoken:生成jwt字符串

express-jwt:将jwt字符串还原成json对象

需要盐值

加密:

// 盐值
let secretKey = '123456'
// 导入加密
const jwt = require('jsonwebtoken')
// 加密部分
app.post('/api/login', (req, res) => {
    // expiresIn过期时间
    let tokenStr = jwt.sign({username: 'root'}, secretKey, {expiresIn: '30s'})
    res.send({
        status: 0,
        msg: '登录成功',
        token: tokenStr
    })
})

解密:

// 导入解密
const {expressjwt} = require('express-jwt')
// 启用解密 unless指定哪些接口不需要访问权限
app.use(expressjwt({secret: secretKey, algorithms: ['HS256']}).unless({path: /^\/api\//}))
// 解密部分 express-jwt配置后会把用户信息挂载到req.auth
app.get('/isLogin', (req, res) => {
    // 响应头:Authorization和Bearer 你的token
    console.log(req.auth)
    res.send({
        status: 0,
        msg: '登录成功',
        data: {
            username: req.auth.username
        }
    })
})

 在最后放一个异常捕获,防止程序崩溃:

app.use((err, req, res, next) => {
    if (err.name === 'UnauthorizedError') {
        return res.send({
            status: 401,
            msg: '无效的token'
        })
    } else {
        return res.send({
            status: 500,
            msg: '未知错误'
        })
    }
    next()
})

ita:jwt的签发时间

exp:过期时间

token需要前端手动去保存

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蒋劲豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值