做每周热议,应该用缓存来做,如果直接查库的话,会对数据库造成压力。用缓存做的话,用Redis 来做缓存的话比较合适一点。d8c1da9c34db0fd9058016a3a350830f.png

  1. # 利用Redsi 添加 数据命令
  2. # day:1 指的是在1号的时候 post:1 第一篇文章添加了 10 条评论。
  3. #后面 6 post:2 指的是 1号第二篇添加了6条评论
  4. zadd day:1 10 post:1 6 post:2
  5. zadd day:2 10 post:1 6 post:2
  6. zadd day:3 10 post:1 6 post:2
  7. ....
  8. zadd day:8 10 post:1 6 post:2
  9. #这样就完成了7天的记录

上面的命令可以帮我们记录一下7天的所有的评论数。但是还没有帮我们计算出来谁是评论最高的。看Redis 的sorted set有序集合有个命令就可以帮我们实现这个功能。
这个命令可以帮助我们实现并集,我们只需要把7天的评论给做个并集就可以求出来,
e0ce7f157be1291d7c8cd87d101bab41.png

  1. # Redis 命令
  2. #意思是并集把这7天的 放到一个新的集合里面 新的集合是 week:rank 这样这个新的集合里面就有了我们的
  3. #7天的记录了
  4. union week:rank 7 day:1...day:8

Redis 命令实践一下看看

本地命令行测试
228f658c607db31d39b6e161507579ae.png

  1. 127.0.0.1:6379> ping
  2. PONG
  3. 127.0.0.1:6379> zadd day:1 10 post:1
  4. (integer) 1
  5. 127.0.0.1:6379> zadd day:2 10 post:1
  6. (integer) 1
  7. 127.0.0.1:6379> zadd day:3 10 post:1
  8. (integer) 1
  9. 127.0.0.1:6379> zadd day:1 5 post:2
  10. (integer) 1
  11. 127.0.0.1:6379> zadd day:2 5 post:2
  12. (integer) 1
  13. 127.0.0.1:6379> zadd day:3 5 post:2
  14. (integer) 1
  15. 127.0.0.1:6379> keys *
  16. 1) "day:1"
  17. 2) "day:2"
  18. 3) "day:3"

查看当天的排行榜命令 ZRevrange

  1. 127.0.0.1:6379> zrevrange day:1 0 -1 withscores
  2. 1) "post:1"
  3. 2) "10"
  4. 3) "post:2"
  5. 4) "5"
  6. 127.0.0.1:6379>

每周的评论排行榜记录。因为我只有三天的,所以只写了3天的

  1. 127.0.0.1:6379> zrevrange week:rank 0 -1 withscores
  2. 1) "post:1"
  3. 2) "30"
  4. 3) "post:2"
  5. 4) "15"
  6. 127.0.0.1:6379>


上面的记录是没有错误的。上述的命令可以帮我们简单的实现了我们的想法。下面用代码来实现。上面还有一个小的 bug 就是当day:1这一天可能会出现就是不可能直接就过完了。可能会一条一条的增加,这个时候应该使用的是自增这个命令来解决这个问题。

  1. #什么时候+1 什么时候-1 就是当你 添加一条评论的时候就添加1 删除的的时候就减1
  2. ZINCRBY day:1 10 post:1

代码来进行实现

目前前端的样式,这样的话我们就需要在项目一开始的时候就启动这个功能
7730770295bba0b3c9280ffd2a8c594f.png
cec558d4cd6bb8a8148b2f588065f8fa.png

  1. @Component
  2. // 实现 启动类 ,还有 上下文的servlect
  3. public class ContextStartup implements ApplicationRunner, ServletContextAware {
  4. // 注入 categoryService
  5. @Autowired
  6. IMCategoryService categoryService;
  7. ServletContext servletContext;
  8. // 注入post 的服务类
  9. @Autowired
  10. IMPostService postService;
  11. @Override
  12. public void run(ApplicationArguments args) throws Exception {
  13. // 调用全查的方法
  14. List<MCategory> list = categoryService.list(new QueryWrapper<MCategory>().eq("status", 0));
  15. servletContext.setAttribute("List", list);
  16. // 调用每周热评的方法
  17. postService.initweek();
  18. }
  19. @Override
  20. public void setServletContext(ServletContext servletContext) {
  21. this.servletContext = servletContext;
  22. }
  23. }

服务类serviceimpl类
大概的思路

  1. 1// 获取7天内发表的文章
  2. 2// 初始化文章的总阅读量
  3. // 缓存文章的基本信息(id,标题,评论数,作者 ID )
  4. // 这样就可以避免的查库。可以直接用我们的缓存。
  5. 3// 做并集

这里需要一个Redis 的工具类,我在网上找到的,不是我写的。网上一大堆。直接拿来用就可以了

  1. package com.example.springbootblog.util;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.data.redis.core.RedisTemplate;
  4. import org.springframework.data.redis.core.ZSetOperations;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.util.CollectionUtils;
  7. import java.util.Collection;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Set;
  11. import java.util.concurrent.TimeUnit;
  12. @Component
  13. public class RedisUtil {
  14. @Autowired
  15. private RedisTemplate redisTemplate;
  16. /**
  17. * 指定缓存失效时间
  18. *
  19. * @param key 键
  20. * @param time 时间(秒)
  21. * @return
  22. */
  23. public boolean expire(String key, long time) {
  24. try {
  25. if (time > 0) {
  26. redisTemplate.expire(key, time, TimeUnit.SECONDS);
  27. }
  28. return true;
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. return false;
  32. }
  33. }
  34. /**
  35. * 根据key 获取过期时间
  36. *
  37. * @param key 键 不能为null
  38. * @return 时间(秒) 返回0代表为永久有效
  39. */
  40. public long getExpire(String key) {
  41. return redisTemplate.getExpire(key, TimeUnit.SECONDS);
  42. }
  43. /**
  44. * 判断key是否存在
  45. *
  46. * @param key 键
  47. * @return true 存在 false不存在
  48. */
  49. public boolean hasKey(String key) {
  50. try {
  51. return redisTemplate.hasKey(key);
  52. } catch (Exception e) {
  53. e.printStackTrace();
  54. return false;
  55. }
  56. }
  57. /**
  58. * 删除缓存
  59. *
  60. * @param key 可以传一个值 或多个
  61. */
  62. @SuppressWarnings("unchecked")
  63. public void del(String... key) {
  64. if (key != null && key.length > 0) {
  65. if (key.length == 1) {
  66. redisTemplate.delete(key[0]);
  67. } else {
  68. redisTemplate.delete(CollectionUtils.arrayToList(key));
  69. }
  70. }
  71. }
  72. //============================String=============================
  73. /**
  74. * 普通缓存获取
  75. *
  76. * @param key 键
  77. * @return 值
  78. */
  79. public Object get(String key) {
  80. return key == null ? null : redisTemplate.opsForValue().get(key);
  81. }
  82. /**
  83. * 普通缓存放入
  84. *
  85. * @param key 键
  86. * @param value 值
  87. * @return true成功 false失败
  88. */
  89. public boolean set(String key, Object value) {
  90. try {
  91. redisTemplate.opsForValue().set(key, value);
  92. return true;
  93. } catch (Exception e) {
  94. e.printStackTrace();
  95. return false;
  96. }
  97. }
  98. /**
  99. * 普通缓存放入并设置时间
  100. *
  101. * @param key 键
  102. * @param value 值
  103. * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
  104. * @return true成功 false 失败
  105. */
  106. public boolean set(String key, Object value, long time) {
  107. try {
  108. if (time > 0) {
  109. redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
  110. } else {
  111. set(key, value);
  112. }
  113. return true;
  114. } catch (Exception e) {
  115. e.printStackTrace();
  116. return false;
  117. }
  118. }
  119. /**
  120. * 递增
  121. *
  122. * @param key 键
  123. * @param delta 要增加几(大于0)
  124. * @return
  125. */
  126. public long incr(String key, long delta) {
  127. if (delta < 0) {
  128. throw new RuntimeException("递增因子必须大于0");
  129. }
  130. return redisTemplate.opsForValue().increment(key, delta);
  131. }
  132. /**
  133. * 递减
  134. *
  135. * @param key 键
  136. * @param delta 要减少几(小于0)
  137. * @return
  138. */
  139. public long decr(String key, long delta) {
  140. if (delta < 0) {
  141. throw new RuntimeException("递减因子必须大于0");
  142. }
  143. return redisTemplate.opsForValue().increment(key, -delta);
  144. }
  145. //================================Map=================================
  146. /**
  147. * HashGet
  148. *
  149. * @param key 键 不能为null
  150. * @param item 项 不能为null
  151. * @return 值
  152. */
  153. public Object hget(String key, String item) {
  154. return redisTemplate.opsForHash().get(key, item);
  155. }
  156. /**
  157. * 获取hashKey对应的所有键值
  158. *
  159. * @param key 键
  160. * @return 对应的多个键值
  161. */
  162. public Map<Object, Object> hmget(String key) {
  163. return redisTemplate.opsForHash().entries(key);
  164. }
  165. /**
  166. * HashSet
  167. *
  168. * @param key 键
  169. * @param map 对应多个键值
  170. * @return true 成功 false 失败
  171. */
  172. public boolean hmset(String key, Map<String, Object> map) {
  173. try {
  174. redisTemplate.opsForHash().putAll(key, map);
  175. return true;
  176. } catch (Exception e) {
  177. e.printStackTrace();
  178. return false;
  179. }
  180. }
  181. /**
  182. * HashSet 并设置时间
  183. *
  184. * @param key 键
  185. * @param map 对应多个键值
  186. * @param time 时间(秒)
  187. * @return true成功 false失败
  188. */
  189. public boolean hmset(String key, Map<String, Object> map, long time) {
  190. try {
  191. redisTemplate.opsForHash().putAll(key, map);
  192. if (time > 0) {
  193. expire(key, time);
  194. }
  195. return true;
  196. } catch (Exception e) {
  197. e.printStackTrace();
  198. return false;
  199. }
  200. }
  201. /**
  202. * 向一张hash表中放入数据,如果不存在将创建
  203. *
  204. * @param key 键
  205. * @param item 项
  206. * @param value 值
  207. * @return true 成功 false失败
  208. */
  209. public boolean hset(String key, String item, Object value) {
  210. try {
  211. redisTemplate.opsForHash().put(key, item, value);
  212. return true;
  213. } catch (Exception e) {
  214. e.printStackTrace();
  215. return false;
  216. }
  217. }
  218. /**
  219. * 向一张hash表中放入数据,如果不存在将创建
  220. *
  221. * @param key 键
  222. * @param item 项
  223. * @param value 值
  224. * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
  225. * @return true 成功 false失败
  226. */
  227. public boolean hset(String key, String item, Object value, long time) {
  228. try {
  229. redisTemplate.opsForHash().put(key, item, value);
  230. if (time > 0) {
  231. expire(key, time);
  232. }
  233. return true;
  234. } catch (Exception e) {
  235. e.printStackTrace();
  236. return false;
  237. }
  238. }
  239. /**
  240. * 删除hash表中的值
  241. *
  242. * @param key 键 不能为null
  243. * @param item 项 可以使多个 不能为null
  244. */
  245. public void hdel(String key, Object... item) {
  246. redisTemplate.opsForHash().delete(key, item);
  247. }
  248. /**
  249. * 判断hash表中是否有该项的值
  250. *
  251. * @param key 键 不能为null
  252. * @param item 项 不能为null
  253. * @return true 存在 false不存在
  254. */
  255. public boolean hHasKey(String key, String item) {
  256. return redisTemplate.opsForHash().hasKey(key, item);
  257. }
  258. /**
  259. * hash递增 如果不存在,就会创建一个 并把新增后的值返回
  260. *
  261. * @param key 键
  262. * @param item 项
  263. * @param by 要增加几(大于0)
  264. * @return
  265. */
  266. public double hincr(String key, String item, double by) {
  267. return redisTemplate.opsForHash().increment(key, item, by);
  268. }
  269. /**
  270. * hash递减
  271. *
  272. * @param key 键
  273. * @param item 项
  274. * @param by 要减少记(小于0)
  275. * @return
  276. */
  277. public double hdecr(String key, String item, double by) {
  278. return redisTemplate.opsForHash().increment(key, item, -by);
  279. }
  280. //============================set=============================
  281. /**
  282. * 根据key获取Set中的所有值
  283. *
  284. * @param key 键
  285. * @return
  286. */
  287. public Set<Object> sGet(String key) {
  288. try {
  289. return redisTemplate.opsForSet().members(key);
  290. } catch (Exception e) {
  291. e.printStackTrace();
  292. return null;
  293. }
  294. }
  295. /**
  296. * 根据value从一个set中查询,是否存在
  297. *
  298. * @param key 键
  299. * @param value 值
  300. * @return true 存在 false不存在
  301. */
  302. public boolean sHasKey(String key, Object value) {
  303. try {
  304. return redisTemplate.opsForSet().isMember(key, value);
  305. } catch (Exception e) {
  306. e.printStackTrace();
  307. return false;
  308. }
  309. }
  310. /**
  311. * 将数据放入set缓存
  312. *
  313. * @param key 键
  314. * @param values 值 可以是多个
  315. * @return 成功个数
  316. */
  317. public long sSet(String key, Object... values) {
  318. try {
  319. return redisTemplate.opsForSet().add(key, values);
  320. } catch (Exception e) {
  321. e.printStackTrace();
  322. return 0;
  323. }
  324. }
  325. /**
  326. * 将set数据放入缓存
  327. *
  328. * @param key 键
  329. * @param time 时间(秒)
  330. * @param values 值 可以是多个
  331. * @return 成功个数
  332. */
  333. public long sSetAndTime(String key, long time, Object... values) {
  334. try {
  335. Long count = redisTemplate.opsForSet().add(key, values);
  336. if (time > 0) expire(key, time);
  337. return count;
  338. } catch (Exception e) {
  339. e.printStackTrace();
  340. return 0;
  341. }
  342. }
  343. /**
  344. * 获取set缓存的长度
  345. *
  346. * @param key 键
  347. * @return
  348. */
  349. public long sGetSetSize(String key) {
  350. try {
  351. return redisTemplate.opsForSet().size(key);
  352. } catch (Exception e) {
  353. e.printStackTrace();
  354. return 0;
  355. }
  356. }
  357. /**
  358. * 移除值为value的
  359. *
  360. * @param key 键
  361. * @param values 值 可以是多个
  362. * @return 移除的个数
  363. */
  364. public long setRemove(String key, Object... values) {
  365. try {
  366. Long count = redisTemplate.opsForSet().remove(key, values);
  367. return count;
  368. } catch (Exception e) {
  369. e.printStackTrace();
  370. return 0;
  371. }
  372. }
  373. //===============================list=================================
  374. /**
  375. * 获取list缓存的内容
  376. *
  377. * @param key 键
  378. * @param start 开始
  379. * @param end 结束 0 到 -1代表所有值
  380. * @return
  381. */
  382. public List<Object> lGet(String key, long start, long end) {
  383. try {
  384. return redisTemplate.opsForList().range(key, start, end);
  385. } catch (Exception e) {
  386. e.printStackTrace();
  387. return null;
  388. }
  389. }
  390. /**
  391. * 获取list缓存的长度
  392. *
  393. * @param key 键
  394. * @return
  395. */
  396. public long lGetListSize(String key) {
  397. try {
  398. return redisTemplate.opsForList().size(key);
  399. } catch (Exception e) {
  400. e.printStackTrace();
  401. return 0;
  402. }
  403. }
  404. /**
  405. * 通过索引 获取list中的值
  406. *
  407. * @param key 键
  408. * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
  409. * @return
  410. */
  411. public Object lGetIndex(String key, long index) {
  412. try {
  413. return redisTemplate.opsForList().index(key, index);
  414. } catch (Exception e) {
  415. e.printStackTrace();
  416. return null;
  417. }
  418. }
  419. /**
  420. * 将list放入缓存
  421. *
  422. * @param key 键
  423. * @param value 值
  424. * @return
  425. */
  426. public boolean lSet(String key, Object value) {
  427. try {
  428. redisTemplate.opsForList().rightPush(key, value);
  429. return true;
  430. } catch (Exception e) {
  431. e.printStackTrace();
  432. return false;
  433. }
  434. }
  435. /**
  436. * 将list放入缓存
  437. *
  438. * @param key 键
  439. * @param value 值
  440. * @param time 时间(秒)
  441. * @return
  442. */
  443. public boolean lSet(String key, Object value, long time) {
  444. try {
  445. redisTemplate.opsForList().rightPush(key, value);
  446. if (time > 0) expire(key, time);
  447. return true;
  448. } catch (Exception e) {
  449. e.printStackTrace();
  450. return false;
  451. }
  452. }
  453. /**
  454. * 将list放入缓存
  455. *
  456. * @param key 键
  457. * @param value 值
  458. * @return
  459. */
  460. public boolean lSet(String key, List<Object> value) {
  461. try {
  462. redisTemplate.opsForList().rightPushAll(key, value);
  463. return true;
  464. } catch (Exception e) {
  465. e.printStackTrace();
  466. return false;
  467. }
  468. }
  469. /**
  470. * 将list放入缓存
  471. *
  472. * @param key 键
  473. * @param value 值
  474. * @param time 时间(秒)
  475. * @return
  476. */
  477. public boolean lSet(String key, List<Object> value, long time) {
  478. try {
  479. redisTemplate.opsForList().rightPushAll(key, value);
  480. if (time > 0) expire(key, time);
  481. return true;
  482. } catch (Exception e) {
  483. e.printStackTrace();
  484. return false;
  485. }
  486. }
  487. /**
  488. * 根据索引修改list中的某条数据
  489. *
  490. * @param key 键
  491. * @param index 索引
  492. * @param value 值
  493. * @return
  494. */
  495. public boolean lUpdateIndex(String key, long index, Object value) {
  496. try {
  497. redisTemplate.opsForList().set(key, index, value);
  498. return true;
  499. } catch (Exception e) {
  500. e.printStackTrace();
  501. return false;
  502. }
  503. }
  504. /**
  505. * 移除N个值为value
  506. *
  507. * @param key 键
  508. * @param count 移除多少个
  509. * @param value 值
  510. * @return 移除的个数
  511. */
  512. public long lRemove(String key, long count, Object value) {
  513. try {
  514. Long remove = redisTemplate.opsForList().remove(key, count, value);
  515. return remove;
  516. } catch (Exception e) {
  517. e.printStackTrace();
  518. return 0;
  519. }
  520. }
  521. //================有序集合 sort set===================
  522. /**
  523. * 有序set添加元素
  524. *
  525. * @param key
  526. * @param value
  527. * @param score
  528. * @return
  529. */
  530. public boolean zSet(String key, Object value, double score) {
  531. return redisTemplate.opsForZSet().add(key, value, score);
  532. }
  533. public long batchZSet(String key, Set<ZSetOperations.TypedTuple> typles) {
  534. return redisTemplate.opsForZSet().add(key, typles);
  535. }
  536. public void zIncrementScore(String key, Object value, long delta) {
  537. redisTemplate.opsForZSet().incrementScore(key, value, delta);
  538. }
  539. public void zUnionAndStore(String key, Collection otherKeys, String destKey) {
  540. redisTemplate.opsForZSet().unionAndStore(key, otherKeys, destKey);
  541. }
  542. /**
  543. * 获取zset数量
  544. * @param key
  545. * @param value
  546. * @return
  547. */
  548. public long getZsetScore(String key, Object value) {
  549. Double score = redisTemplate.opsForZSet().score(key, value);
  550. if(score==null){
  551. return 0;
  552. }else{
  553. return score.longValue();
  554. }
  555. }
  556. /**
  557. * 获取有序集 key 中成员 member 的排名 。
  558. * 其中有序集成员按 score 值递减 (从大到小) 排序。
  559. * @param key
  560. * @param start
  561. * @param end
  562. * @return
  563. */
  564. public Set<ZSetOperations.TypedTuple> getZSetRank(String key, long start, long end) {
  565. return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
  566. }
  567. }

实现类的代码

  1. // 每周热评的方法
  2. @Override
  3. public void initweek() {
  4. //获取 7天的文章
  5. List<MPost> posts = this.list(new QueryWrapper<MPost>().ge("created", DateUtil.lastWeek())
  6. .select("id", "title", "user_id", "comment_count", "view_count", "created")
  7. );// 获取到7天前的以及按照这几个查询,不需要全部查询
  8. // 初始化文章的总评论
  9. for (MPost post : posts) {
  10. // 设置 key
  11. String key = "day:rank:" + DateUtil.format(post.getCreated(), DatePattern.PURE_DATE_FORMAT);
  12. // 缓存进去的评论数量
  13. redisUtil.zSet(key, post.getId(), post.getCommentCount());
  14. //设置自动过期 7天过期
  15. long between = DateUtil.between(new Date(), post.getCreated(), DateUnit.DAY);
  16. long expireTime = (7 - between) * 24 * 60 * 60; // 有效 时间
  17. redisUtil.expire(key, expireTime);
  18. // 缓存文章的一些基本信息
  19. this.hashCachePost(post, expireTime);
  20. }
  21. // 做并集
  22. this.zunionAndStore();
  23. }
  24. /**
  25. * 文章每周评论数量并集操作
  26. **/
  27. private void zunionAndStore() {
  28. String destkey = "day:rank:" + DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
  29. // 设置并集后的新的 key
  30. String newkey = "week:rank";
  31. ArrayList<String> otherKeys = new ArrayList<>();
  32. // 计算7天的
  33. for (int i = -6; i < 0; i++) {
  34. String temp = "day:rank:" + DateUtil.format(DateUtil.offsetDay(new Date(), i), DatePattern.PURE_DATE_FORMAT);
  35. otherKeys.add(temp);
  36. }
  37. redisUtil.zUnionAndStore(destkey, otherKeys, newkey);
  38. }
  39. /**
  40. * 文章作者缓存
  41. **/
  42. private void hashCachePost(MPost post, long expireTime) {
  43. // 设置 key
  44. String key = "rank:post:" + post.getId();
  45. // 判断存在不存在
  46. boolean hasKey = redisUtil.hasKey(key);
  47. if (!hasKey) {
  48. // 就存到缓存里面
  49. redisUtil.hset(key, "post:id", post.getId(), expireTime);
  50. redisUtil.hset(key, "post:title", post.getTitle(), expireTime);
  51. redisUtil.hset(key, "post:commentCount", post.getCommentCount(), expireTime);
  52. }
  53. }
  54. }

这样就可以把我们的命令行转换成代码的形式。就可以把我们的数据库的数据先存到缓存中去了。
效果

  1. 127.0.0.1:6379> keys *
  2. 1) "rank:post:4"
  3. 2) "week:rank"
  4. 3) "day:rank:20210724"
  5. 4) "rank:post:3"
  6. 5) "rank:post:2"
  7. 6) "day:rank:20210726"
  8. #查看我们并集完后的数据 id 为 3 的有 1条评论。
  9. 127.0.0.1:6379> zrevrange week:rank 0 -1 withscores
  10. 1) "3"
  11. 2) "1"
  12. 3) "2"
  13. 4) "1"
  14. 5) "4"
  15. 6) "0"
  16. 127.0.0.1:6379>

数据库中id 为 3 的有 1条评论
9ad5fac70c72d0319214f12345e152f4.png
1419489b792060f1539d246fe15f8f13.png
确实只有一条评论的

前端展示出来

这里的思路就比较简单了,把我们的数据从缓存中取出来就可以。用的freemarker可以自定义标签。我自定义了标签。
Hosttemplate

  1. /**
  2. * 本周热议
  3. */
  4. @Component
  5. public class HotsTemplate extends TemplateDirective {
  6. @Autowired
  7. RedisUtil redisUtil;
  8. @Override
  9. public String getName() {
  10. return "hots";
  11. }
  12. @Override
  13. public void execute(DirectiveHandler handler) throws Exception {
  14. // 设置 key
  15. String key ="week:rank";
  16. Set<ZSetOperations.TypedTuple> zSetRank = redisUtil.getZSetRank(key, 0, 6);
  17. ArrayList<Map> maps = new ArrayList<>();
  18. // 便利
  19. for (ZSetOperations.TypedTuple typedTuple : zSetRank) {
  20. // 创建 Map
  21. HashMap<String, Object> map = new HashMap<>();
  22. Object post_id = typedTuple.getValue();
  23. String PostHashKey = "rank:post:" +post_id;
  24. map.put("id",post_id);
  25. map.put("title",redisUtil.hget(PostHashKey,"post:title"));
  26. map.put("commentCount",typedTuple.getScore());
  27. maps.add(map);
  28. }
  29. handler.put(RESULTS,maps).render();
  30. }
  31. }

在FreemarkerConfig把我们写的便签注入就可以使用我们自定义的标签了

  1. @Configuration
  2. public class FreemarkerConfig {
  3. @Autowired
  4. private freemarker.template.Configuration configuration;
  5. @Autowired
  6. PostsTemplate postsTemplate;
  7. @Autowired
  8. HotsTemplate hotsTemplate;
  9. @PostConstruct
  10. public void setUp() {
  11. configuration.setSharedVariable("timeAgo", new TimeAgoMethod());
  12. configuration.setSharedVariable("posts", postsTemplate);
  13. configuration.setSharedVariable("hosts", hotsTemplate);
  14. }
  15. }

a47d829916147e73048ebd3b327bc5c0.png

总结

在做这个功能的时候。不够全面。虽然写完了,但是应该是获取7天内的评论。我获取了7天的文章。虽然是个 bug 但是我不想修复。就这样吧。现在能用就行。道理是一样的。到时候有时间出问题了在改吧。累了,无情的代码机器记录代码生活中。。。。。。