每周热议功能
大概思路
思路分析
做每周热议,应该用缓存来做,如果直接查库的话,会对数据库造成压力。用缓存做的话,用Redis 来做缓存的话比较合适一点。
# 利用Redsi 添加 数据命令
# day:1 指的是在1号的时候 post:1 第一篇文章添加了 10 条评论。
#后面 6 post:2 指的是 在1号第二篇添加了6条评论
zadd day:1 10 post:1 6 post:2
zadd day:2 10 post:1 6 post:2
zadd day:3 10 post:1 6 post:2
....
zadd day:8 10 post:1 6 post:2
#这样就完成了7天的记录
上面的命令可以帮我们记录一下7天的所有的评论数。但是还没有帮我们计算出来谁是评论最高的。看Redis 的sorted set有序集合有个命令就可以帮我们实现这个功能。
这个命令可以帮助我们实现并集,我们只需要把7天的评论给做个并集就可以求出来,、。
# Redis 命令
#意思是并集把这7天的 放到一个新的集合里面 新的集合是 week:rank 这样这个新的集合里面就有了我们的
#7天的记录了
union week:rank 7 day:1...day:8
Redis 命令实践一下看看
本地命令行测试
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> zadd day:1 10 post:1
(integer) 1
127.0.0.1:6379> zadd day:2 10 post:1
(integer) 1
127.0.0.1:6379> zadd day:3 10 post:1
(integer) 1
127.0.0.1:6379> zadd day:1 5 post:2
(integer) 1
127.0.0.1:6379> zadd day:2 5 post:2
(integer) 1
127.0.0.1:6379> zadd day:3 5 post:2
(integer) 1
127.0.0.1:6379> keys *
1) "day:1"
2) "day:2"
3) "day:3"
查看当天的排行榜命令 ZRevrange
127.0.0.1:6379> zrevrange day:1 0 -1 withscores
1) "post:1"
2) "10"
3) "post:2"
4) "5"
127.0.0.1:6379>
每周的评论排行榜记录。因为我只有三天的,所以只写了3天的
127.0.0.1:6379> zrevrange week:rank 0 -1 withscores
1) "post:1"
2) "30"
3) "post:2"
4) "15"
127.0.0.1:6379>
上面的记录是没有错误的。上述的命令可以帮我们简单的实现了我们的想法。下面用代码来实现。上面还有一个小的 bug 就是当day:1这一天可能会出现就是不可能直接就过完了。可能会一条一条的增加,这个时候应该使用的是自增这个命令来解决这个问题。
#什么时候+1 什么时候-1 就是当你 添加一条评论的时候就添加1 删除的的时候就减1
ZINCRBY day:1 10 post:1
代码来进行实现
目前前端的样式,这样的话我们就需要在项目一开始的时候就启动这个功能
@Component
// 实现 启动类 ,还有 上下文的servlect
public class ContextStartup implements ApplicationRunner, ServletContextAware {
// 注入 categoryService
@Autowired
IMCategoryService categoryService;
ServletContext servletContext;
// 注入post 的服务类
@Autowired
IMPostService postService;
@Override
public void run(ApplicationArguments args) throws Exception {
// 调用全查的方法
List<MCategory> list = categoryService.list(new QueryWrapper<MCategory>().eq("status", 0));
servletContext.setAttribute("List", list);
// 调用每周热评的方法
postService.initweek();
}
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
}
服务类serviceimpl类
大概的思路
1,// 获取7天内发表的文章
2,// 初始化文章的总阅读量
// 缓存文章的基本信息(id,标题,评论数,作者 ID )
// 这样就可以避免的查库。可以直接用我们的缓存。
3,// 做并集
这里需要一个Redis 的工具类,我在网上找到的,不是我写的。网上一大堆。直接拿来用就可以了
package com.example.springbootblog.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtil {
@Autowired
private RedisTemplate redisTemplate;
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
//============================String=============================
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public Object get(String key) {