1.nodejs 连接 redis 的 Demo
2.nodejs 连接 redis–封装成工具
3.redis 使用
4.server端登陆
1.nodejs 连接 redis 的 Demo
目录:
node-redis
way liu@DESKTOP-NG9KB5L MINGW64 /e/work-vscode/node-redis
$ npm i redis --save
index.js
const redis = require('redis')
// 创建客户端
const redisClient = redis.createClient(6379, '127.0.0.1',{auth_pass:123456})
redisClient.on('error', err => {
console.log(err)
})
// 测试
redisClient.set('myname','zhangsan2',redis.print)
redisClient.get('myname', (err, val) => {
if (err) {
console.log(err)
return
}
console.log('val',val)
// 退出
redisClient.quit()
})
- const redisClient = redis.createClient(6379, ‘127.0.0.1’,{auth_pass:123456}),注意创建客户端参数
- get 和 set 方法的使用
控制台输出:
Reply: OK
val zhangsan2
2.nodejs 连接 redis--封装成工具
conf/db.js
const env = process.env.NODE_ENV //环境变量(package.json中已定义)
// 配置
let MYSQL_CONF
let REDIS_CONF
if (env === 'dev') {
// mysql
MYSQL_CONF = {
host: 'localhost',
user: 'root',
password: '123456',
port: '3306',
database: 'myblog'
}
// redis
REDIS_CONF = [
6379,
'127,0.0.1',
{
auth_pass: 123456
}
]
}
// 线上环境配置
if (env === 'production') {
MYSQL_CONF = {
host: 'localhost',
user: 'root',
password: '123456',
port: '3306',
database: 'myblog'
}
// redis
REDIS_CONF = [
6379,
'127,0.0.1',
{
auth_pass: 123456
}
]
}
module.exports = {
MYSQL_CONF,
REDIS_CONF
}
db/redis.js
const redis = require('redis')
const { REDIS_CONF } = require('../conf/db')
// 创建客户端
const redisClient = redis.createClient(REDIS_CONF[0],REDIS_CONF[1],REDIS_CONF[2])
redisClient.on('error', err => {
console.log(err)
})
function set(key,val) {
// 如果是对象类型转为字符串
if (typeof val === 'object') {
val = JSON.stringify(val)
}
redisClient.set(key,val,redis.print)
}
function get(key) {
// redisClient.get()有回调,是异步形式,用promise封装
const promise = new Promise((resolve, reject) => {
redisClient.get(key, (err,val) => {
if (err) {
reject(err)
return
}
// 如果不存在key
if (val == null) {
resolve(null)
return
}
// 通过 try cath 兼容json格式
try {
resolve(
JSON.parse(val)
)
} catch (ex) {
resolve(val)
}
resolve(val)
})
})
return promise
}
module.exports = {
set,
get
}
3.redis 使用
app.jsconst {get, set} = require('./src/db/redis')
...
// 解析cookie
req.cookie = {}
const cookieStr = req.headers.cookie || '' //k1=v1;k2=v2;
cookieStr.split(';').forEach(item => {
if(!item) {
return
}
const arr = item.split('=')
const key = arr[0].trim()
const val = arr[1].trim()
req.cookie[key] = val
})
console.log('req.cookie is',req.cookie)
// 解析session(使用redis)
let needSetCookie = false //有userId不需设置cookie
let userId = req.cookie.userid
if (!userId) {
needSetCookie = true
userId = `${Date.now()}_${Math.random()}`
console.log(userId)
set(userId,{})
}
// 获取session
req.sessionId = userId
get(req.sessionId).then((sessionData) => {
if (sessionData == null) {
// 初始化 redis 中的 session 值
set(req.sessionId,{})
} else {
// 设置session
console.log(sessionData)
req.session = sessionData
}
})
...
if (blogResult) {
blogResult.then(blogData => {
// 如果需要设置cookie
if (needSetCookie) {
res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
}
res.end(
JSON.stringify(blogData)
)
})
return
}
// 处理 user 路由
const userResult = handleUserRouter(req,res)
if (userResult) {
userResult.then(userData => {
// 如果需要设置cookie
if (needSetCookie) {
res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
}
res.end(
JSON.stringify(userData)
)
})
return
}
- 解析cookie,通过req.headers.cookie获取cookie字符串(k1=v1;k2=v2;),经过一些列操作得到req.cookie is { userid: ‘1602603841727_0.36866137268150534’ }
- userId =req.cookie.userid,如果userId不存在则进行随机生成的操作,通过needSetCookie标识并在后面的两个处理路由中通过res.setHeader(‘Set-Cookie’,
userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}
)返回客户端生成cookie。 - req.sessionId = userId,通过调用get方法获取一个promise包裹的对应value(userId作为key),如果为空即redis中没有的话就set(req.sessionId,{}),不为空的话req.session = sessionData(把value值给req.session,别的操作可以通过req.session获取对应的session的value)
登陆:把username和realname作为req.session对象的key和他们的value存储为redis的value
router/user.js
// 登陆
if (method === 'GET' && req.path === '/api/user/login') {
// const {username, password} = req.body
const {username, password} = req.query
const result = login(username, password)
return result.then(data => {
if (data.username) {
// 设置 session
req.session.username = data.username
req.session.realname = data.realname
console.log('req.session is',req.session)
// 同步到redis
set(req.sessionId, req.session)
return new SuccessModel()
}
return new ErrorModel('登陆失败')
})
}
4.server端登陆
router/blog.js// 统一的登陆验证函数
const loginCheck = (req) => {
if (!req.session.username) {
return Promise.resolve(new ErrorModel('尚未登陆'))
}
}
// 获取博客详情
if (method === 'GET' && req.path ==='/api/blog/detail') {
const result = getDetail(id)
return result.then(data => {
return new SuccessModel(data)
})
}
// 新建一篇博客
if (method === 'POST' && req.path ==='/api/blog/new') {
const loginCheckResult = loginCheck(req)
if (loginCheckResult) {
// 未登陆
return loginCheck
}
// 由于还没有登陆,需模拟登陆后
// const author = 'zhangsan'
const author = req.session.username
req.body.author = author
const result = newBlog(req.body)
return result.then(data => {
return new SuccessModel(data)
})
}
// 更新一篇博客
if (method === 'POST' && req.path ==='/api/blog/update') {
const loginCheckResult = loginCheck(req)
if (loginCheckResult) {
// 未登陆
return loginCheck
}
const result = updateBlog(id, req.body)
return result.then(val => {
if (val) {
return new SuccessModel()
} else {
return new ErrorModel('更新博客失败')
}
})
}
// 删除一篇博客
if (method === 'POST' && req.path ==='/api/blog/delete') {
const loginCheckResult = loginCheck(req)
if (loginCheckResult) {
// 未登陆
return loginCheck
}
// 由于还没有登陆,需模拟登陆后
const author = req.session.username
const result = delBlog(id,author)
return result.then(val => {
if (result) {
return new SuccessModel()
} else {
return new ErrorModel('删除博客失败')
}
})
}
定义一个统一的登陆验证函数,由于删除、更新、新建都需要登陆,所以在各字路由分别添加上
if (loginCheckResult) {
// 未登陆
return loginCheck
}
由于删除和更新需要author参数,之前用的是写死的,现在可以改为req.session.username获取。
router/user.js
// 登陆
if (method === 'POST' && req.path === '/api/user/login') {
const {username, password} = req.body
// const {username, password} = req.query
const result = login(username, password)
return result.then(data => {
if (data.username) {
// 设置 session
req.session.username = data.username
req.session.realname = data.realname
console.log('req.session is',req.session)
// 同步到redis
set(req.sessionId, req.session)
return new SuccessModel()
}
return new ErrorModel('登陆失败')
})
}
1.把GET改为POST
2.改为从req.body中获取数据。