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);
    }
}
View Code
复制代码

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

posted @   段江涛IT  阅读(2227)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
历史上的今天:
2017-12-29 Java将byte[]和int的互相转换
2017-12-29 java调用dll/so文件
页脚HTML代码
点击右上角即可分享
微信分享提示