Redis实现文章投票功能
Redis的具体操作这里就不说了,说一下需求和设计思路。
需求:自己实现一个文章投票的功能
1.能够按照时间分页倒叙查看文章信息
2.能够给文章投票,一个用户给一篇文章只能投票一次
3.需要记录分值。每次投票后就+10分
思路:
1.设计一个Hash,用于存储文章的基本信息(标题、内容、创建人)。键:article:1
2.设计一个Set,用于记录一篇文章被哪些用户投过票。键:vole:1
3.设计一个ZSet,用于记录每一篇文章的分值。键:score
RedisUtil.java
package cn.duanjt; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * Redis公共操作类 * @author 段江涛 * @date 2018-12-29 */ public class RedisUtil { JedisPool pool = null; public RedisUtil(String host, int port) { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(20); config.setMaxIdle(5); config.setMaxWaitMillis(100); config.setTestOnBorrow(true); pool = new JedisPool(config, host, port); } public Jedis getJedis(){ return pool.getResource(); } public void dispose(Jedis jedis){ pool.returnResourceObject(jedis); } }
AppTest.java (测试代码)
package cn.duanjt; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Set; import org.junit.Before; import org.junit.Test; import redis.clients.jedis.Jedis; public class AppTest { RedisUtil redis = null; int userId = 200;//用户编号,可修改后执行下面的相关方法 int artId = 3;//文章编号,可修改后执行下面的相关方法 /** * 初始化 */ @Before public void load() { String host = "172.23.88.107"; int port = 6379; redis = new RedisUtil(host, port); } /** * 发表文章 * 逻辑: * 1.文章编号采用incr方法自增长 * 2.定义Redis的Hash类型存放文章信息,键采用 "article:"+文章编号的方式 * 3.定义Set用于记录哪些用户给这篇文章投过票,键采用 "vole:"+文章编号的方式 * 4.定义ZSet用于记录每篇文章的分值,方便排序,键使用"score" */ @Test public void addArticle() { Jedis jedis = redis.getJedis(); // 定义发布文章:编号、标题、内容、创建人 Hash HashMap<String, String> map = new HashMap<String, String>(); long id = jedis.incr("article:");// 文章id,自增长 map.put("title", "文章标题->" + id); map.put("content", "文章内容->" + id); map.put("user_id", String.valueOf(userId)); map.put("create_time", getDate()); jedis.hmset("article:" + id, map); // 自己给自己投上一票 Set jedis.sadd("vole:" + id, userId + ""); // 给自己+10分 ZSet jedis.zadd("score", 10, id + ""); printArticle(jedis, id); redis.dispose(jedis); } /** * 给文章投票 * 逻辑: * 1.记录文章投票用户集合的Set新增一条数据sadd,如果返回1表示新增成功,返回0表示已存在 * 2.记录分值的ZSet调用zincrby方法加10分 */ @Test public void voteArticle() { Jedis jedis = redis.getJedis(); try { // 查找文章 if (!jedis.exists("article:" + artId)) { System.out.println("文章:" + artId + " 不存在."); return; } // 用户投票 if (jedis.sadd("vole:" + artId, userId + "") == 0) { System.out.println("用户:" + userId + " 已对文章:" + artId + " 进行过投票,不可重复投票"); return; } // +10分 jedis.zincrby("score", 10, artId + ""); printArticle(jedis, artId); } finally { redis.dispose(jedis); } } /** * 查看文章信息 * 逻辑:就是简单的Hash的数据获取hmget */ @Test public void detailArticle() { Jedis jedis = redis.getJedis(); try { printArticle(jedis, artId); } finally { redis.dispose(jedis); } } /** * 按分值从高到低排序 * 1.调用ZSet的zrevrange方法根据分值倒序,获得一个集合 * 2.循环集合去Hash中查询文章信息 */ @Test public void allArticle() { Jedis jedis = redis.getJedis(); try { Set<String> set = jedis.zrevrange("score", 0, 1000);// 返回的是文章编号 for (String aId : set) { System.out.println("<<=================================================>>"); printArticle(jedis, Integer.parseInt(aId)); } } finally { redis.dispose(jedis); } } /** * 打印文章信息,参数是文章的id * @param jedis * @param id */ private void printArticle(Jedis jedis, long id) { /* 打印日志 */ System.out.println("***********************"); List<String> list = jedis.hmget("article:" + id, "title", "content", "user_id", "create_time"); System.out.println("文章编号:" + id); System.out.println("文章标题:" + list.get(0)); System.out.println("文章内容:" + list.get(1)); System.out.println("发布用户:" + list.get(2)); System.out.println("发布时间:" + list.get(3)); System.out.println("***********************"); double card = jedis.zscore("score", id + ""); System.out.println("文章分值:" + card); Set<String> set = jedis.smembers("vole:" + id); System.out.println("给文章投票的用户有:" + String.join(",", set)); } /** * 获取当前时间 * @return */ private String getDate() { java.text.DateFormat format1 = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String s = format1.format(new Date()); return s; } }
总结:
1.使用Redis之前一定要先设计好,写代码才能保证思路清晰。
2.设计和思路文档一定要保存好,不然其它同事接手会很懵逼。
3.上面的两个类,拷过去就可以执行,看效果。