1、NoSQL数据库。支持多种类型的数据结构,如字符串(String),哈希(Hashes),列表(Lists),集合(Sets),有序集合(Sorted sets)等。
2、数据存在内存里,所以读写性能很惊人。同时将内存中的数据以快照或日志的形式保存在硬盘上,以保证数据安全性。
3、典型应用场景:缓存、排行榜、计数器、社交网络、消息队列等。
引入依赖
配置redis
访问redis
点赞:支持对帖子、评论点赞;第一次点赞,第二次取消点赞
首页点赞数量:统计帖子的点赞数量
详情页点赞数量:统计点赞数量;显示点赞状态
1、数据层:在util里增加RedisKeyUtil类,里面设计点赞数据的存储方式。在redis里,点赞实体的存储格式是:
like:entity:entityType:entityId -> set(userId)
2、服务层:在service里增加LikeService类,里面定义:
点赞(like)的方法(将得到的userid插入value的set里)
查询点赞数量(findEntityLikeCount)的方法(value的set里有多少个userid)
查询某人有没有对某个帖子或详情点赞(findEntityLikeStatus)(查询某userid有没有在value的set里)
3、视图层:在controller里增加LikeController类,里面定义方法,来使用LikeService里的方法。
like:首先从hostholder里获取当前用户,然后调用LikeService里的like方法,调用LikeService里的findEntityLikeCount方法,调用LikeService里的findEntityLikeStatus方法,最后将获取的数量和状态使用map封装后传给页面
4、页面:帖子详情页面(discuss-detail)里修改点赞按钮(帖子、评论)
5、修改首页帖子点赞数量:在首页home controller里的现实帖子的方法里,增加查询帖子点赞数量(findEntityLikeCount)的代码。然后在index.html里修改对应代码。
6、修改首页帖子详情点赞数量:在帖子详情discussPostController里增加显示帖子点赞数量(findEntityLikeCount)和状态(findEntityLikeStatus)的逻辑(注意:这里没有登陆状态为0)。然后在discuss-detail.html里修改对应代码。
重构点赞功能:以用户为key,记录点赞数量;increment(key),decrement(key)
开发个人主页:以用户为key,查询点赞数量。
1、数据层:在util的RedisKeyUtil类里面增加点赞实体的存储方式(以用户为key存储)。在redis里,某个用户的赞的存储格式是:
like:user:userId -> int
2、服务层:在service的LikeService类里面
重构点赞(like)方法。使得点赞后,以用户为key的value要增或减。
增加查询某个用户获得的赞的数量的方法。
3、视图层:在controller的LikeController类里还是调用LikeService里的方法。
4、页面:帖子详情页面(discuss-detail)里修改点赞按钮(帖子、评论)
1、控制层:在usercontroller里增加查看个人主页的方法
2、页面:主页index和个人主页profile
需求:开发关注、取消关注功能;统计用户关注数、粉丝数。
关键:如果a关注了b,则a是b的粉丝(follower),b是a的目标(followee);关注的目标可以是用户、帖子、题目等,在实现时将这些目标抽象为实体。
1、数据层:在util的RedisKeyUtil类里设计关注数据的存储方式。在redis里有follower和followee两份数据。
follower:
// 某个实体拥有的粉丝 // follower:entityType:entityId -> zset(userId,now)
followee:
// 某个用户关注的实体 // followee:userId:entityType -> zset(entityId,now)以当前时间排序
2、服务层:在service里增加FollowService类,里面定义:
关注(follow)的方法:插入键值对
注意:在 Spring Data Redis 中,redisTemplate.execute(new SessionCallback())
允许你在一个 Redis 会话(session)中执行多个命令,而不是为每个命令创建一个新的会话。这在多个命令需要在同一个事务中执行时是很有用的。通常,执行单个 Redis 命令不需要使用 SessionCallback
。然而,当你有多个命令需要在同一个事务中执行时,使用 SessionCallback
可以提高效率和保证数据一致性。
取消关注的方法:删除键值对
查询关注的实体的数量:以user为key查询
查询实体的粉丝的数量:以实体为key查询
查询当前用户是否已关注该实体:以user为key,看看能不能查询到这个实体的某个属性
3、视图层:
在controller里增加FollowController类,里面定义如何使用FollowService里的方法。
follow:首先从hostholder里获取当前用户,然后调用FollowService里的follow方法,然后给页面返回消息
unfollow:同上
在usercontrolle里,查询关注数量、粉丝数量、是否已关注
4、页面:
修改个人主页(profile)
业务层:
查询某个用户关注的人和粉丝,并分页
表现层:
处理“查询关注的人”、“查询粉丝"请求
编写“查询关注的人”、“查询粉丝"模版
业务层:
FollowService类,里面定义:
查询某用户关注的人:
查询某用户的粉丝:
表现层:
FollowController类,里面定义:
查询某用户关注的人:
查询某用户的粉丝:
是否关注:
页面:profile、follower、followee
使用redis存储验证码:验证码需要频繁的访问与刷新,对性能要求很高;验证码不需要永久保存,通常在很短时间后失效;分布式部署时,存在session共享的问题
使用redis存储登陆凭证:处理每次请求时,都需要查询用户的登录凭证,访问的频率很高
使用redis缓存用户信息:处理每次请求时,都要根据凭证查询用户信息,访问的频率非常高。
数据层:RedisKeyUtil类里设计验证码数据的存储方式。
验证码只用redis存
// 获取验证码的时候,要将验证码和用户对应起来,但这时用户还没登陆 // 所以在用户访问登陆页面时给他发个凭证,将凭证存在cookie里,以凭证标识用户 // kaptcha:owner -> string
表现层:
logincontroller里重构getKaptcha方法:首先生成验证码的图片;然后生成cookie,在cookie里添加验证码的owner;然后将验证码的键值对(owner -> kaptchatext)插入数据库(设置过期时间为60秒)
logincontroller里重构login方法:首先从cookie里取出owner并且检查是不是空;然后从redis里以owner为key取出验证码;最后检查数据库和页面输入的验证码是否一致。
凭证:只用redis存
存凭证:重构userService的login方法:账号密码都验证通过后,生成登陆凭证后,将键值对插入数据库,并将ticket值用map封装(在表现层,会将封装好的ticket用cookie传给服务器,服务器的请求会带着cookie,需要验证登陆凭证的时候就将ticket值从cookie里取,然后服务器会查redis,看登陆凭证是什么状态)
改凭证:重构userService的logout方法:根据ticket值获取loginticket对象;然后将它的status改为1(删除状态);最后再将键值对存回去。(在页面点击了logout,表现层就会调用logout方法,里面调用业务层的logout方法)
取凭证:重构userService的findLoginTicket方法:根据ticket值获取loginticket对象(在表现层,需要验证登陆凭证时,将ticket值从cookie里取,然后服务器会调用findLoginTicket,查redis,看登陆凭证是什么状态)
数据层:RedisKeyUtil类里设计用户数据的存储方式。用redis和mysql存
先定义三种方法:
// 1.优先从缓存中取值
// 2.取不到时初始化缓存数据(从mysql数据库取,然后存入redis)
// 3.数据变更时清除缓存数据
重构findUserById方法:1、优先从缓存中取值,2、取不到时初始化缓存数据
重构activation方法:如果激活成功,就3、数据变更时清除缓存数据
重构updateHeader方法:3、数据变更时清除缓存数据