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.上面的两个类,拷过去就可以执行,看效果。