• Java 实现Redis客户端,服务端


    1.Java实现Redis发布订阅

    爆米花9958:Java实现Redis发布订阅

    1.1实例

    首先封装JedisUtils中加入发布和订阅操作的方法:

    /**
     * 发布一个消息
     *
     * @param channel
     * @param message
     */
    public void publishMsg(String channel, String message) {
        try {
            jedis.publish(channel, message);
        } catch (Exception e) {
        }
    }
    

    参数channel是消息的频道,message是消息的内容。在Junit测试或者其他的地方,使用工具类的此方法即可发布一个消息。

    接收消息。定义一个类继承JedisPubSub,然后实现其中未实现的方法,最后在工具类JedisUtils中定义一个操作的方法。

    public class RedisMsgSubListener extends JedisPubSub {
        // 取得订阅的消息后的处理
        public void onMessage(String channel, String message) {
            System.out.println(channel + "=" + message);
        }
     
        // 初始化订阅时候的处理
        public void onSubscribe(String channel, int subscribedChannels) {
            // System.out.println(channel + "=" + subscribedChannels);
        }
     
        // 取消订阅时候的处理
        public void onUnsubscribe(String channel, int subscribedChannels) {
            // System.out.println(channel + "=" + subscribedChannels);
        }
     
        // 初始化按表达式的方式订阅时候的处理
        public void onPSubscribe(String pattern, int subscribedChannels) {
            // System.out.println(pattern + "=" + subscribedChannels);
        }
     
        // 取消按表达式的方式订阅时候的处理
        public void onPUnsubscribe(String pattern, int subscribedChannels) {
            // System.out.println(pattern + "=" + subscribedChannels);
        }
     
        // 取得按表达式的方式订阅的消息后的处理
        public void onPMessage(String pattern, String channel, String message) {
            System.out.println(pattern + "=" + channel + "=" + message);
        }
     
    }
    

    在工具类JedisUtils中定义一个操作的方法:

    /**
     * 接收消息。在main方法调用后,会一直执行下去。当有发布对应消息时,就会在jedisPubSub中接收到!
     *
     * @param jedisPubSub
     * @param channels
     */
    public void subscribeMsg(JedisPubSub jedisPubSub, String channels) {
        try {
            jedis.subscribe(jedisPubSub, channels);
        } catch (Exception e) {
        }
    }
    

    测试方法:

    public class PubTest {
        JedisUtil4 jedisUtil;
        public void  publishMsg(){
            jedisUtil= JedisUtil4.getInstance();
            jedisUtil.publishMsg("test","hello world!");
        }
     
        public static void main(String[] args) {
            PubTest pubTest=new PubTest();
            pubTest.publishMsg();
        }
    }
    public class SubTest {
        JedisUtil4 jedisUtil;
        public void subscribeMsg(){
            jedisUtil=JedisUtil4.getInstance();
            RedisMsgSubListener pubsub = new RedisMsgSubListener();
            jedisUtil.subscribeMsg(pubsub, "test");
     
        }
     
        public static void main(String[] args) {
            new SubTest().subscribeMsg();
        }
    }
    

    publishMsg()方法是用来测试发布消息的,subscribeMsg()是用来测试接收订阅消息的。

    执行subscribeMsg()方法后,客户端会一直开启着,不会关闭。另外,在其他的redis客户端中发布一条消息,控制台就会立刻输出该消息。

    2.【Redis】Java实现redis消息订阅/发布(PubSub)

    Mr_EvanChen

    ①建立发布者,通过频道(mychannel)发布消息。

    package com.cqh.PubSub;
     
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
     
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
     
    /**
     * Created by yl1794 on 2018/3/28.
     */
    //建立发布者,通过频道(mychannel)发布消息
    public class Publisher extends Thread{
        private final JedisPool jedisPool;
     
        public Publisher(JedisPool jedisPool) {
            this.jedisPool = jedisPool;
        }
     
        @Override
        public void run(){
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            Jedis jedis = jedisPool.getResource();   //连接池中取出一个连接
            while (true) {
                String line;
                try {
                    line = reader.readLine();
                    if (!"quit".equals(line)) {
                        jedis.publish("mychannel", line);   //从通过mychannel 频道发布消息
                        System.out.println(String.format("发布消息成功!channel: %s, message: %s", "mychannel", line));
                    } else {
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    ②建立消息监听类,并重写了JedisPubSub的一些相关方法

    package com.cqh.PubSub;
     
    import redis.clients.jedis.JedisPubSub;
     
    /**
     * Created by yl1794 on 2018/3/28.
     */
    //建立消息监听类,并重写了JedisPubSub的一些相关方法
    public class MsgListener extends JedisPubSub{
     
        public MsgListener(){}
     
        @Override
        public void onMessage(String channel, String message) {       //收到消息会调用
            System.out.println(String.format("收到消息成功! channel: %s, message: %s", channel, message));
            this.unsubscribe();
        }
     
        @Override
        public void onSubscribe(String channel, int subscribedChannels) {    //订阅频道会调用
            System.out.println(String.format("订阅频道成功! channel: %s, subscribedChannels %d",
            channel, subscribedChannels));
        }
     
        @Override
        public void onUnsubscribe(String channel, int subscribedChannels) {   //取消订阅会调用
            System.out.println(String.format("取消订阅频道! channel: %s, subscribedChannels: %d",
                    channel, subscribedChannels));
     
        }
    }
    

    ③建立订阅者,订阅者去订阅频道(mychannel)

    package com.cqh.PubSub;
     
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
     
    /**
     * Created by yl1794 on 2018/3/28.
     */
    //建立订阅者,订阅者去订阅频道(mychannel)
    public class Subscriber extends Thread {
        private final JedisPool jedisPool;
        private final MsgListener msgListener = new MsgListener();
     
        private final String channel = "mychannel";
     
        public Subscriber(JedisPool jedisPool) {
            super("Subscriber");
            this.jedisPool = jedisPool;
        }
     
        @Override
        public void run() {
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();   //取出一个连接
                jedis.subscribe(msgListener, channel);    //通过subscribe的api去订阅,参数是订阅者和频道名
     
                //注意:subscribe是一个阻塞的方法,在取消订阅该频道前,会一直阻塞在这,无法执行后续的代码
                //这里在msgListener的onMessage方法里面收到消息后,调用了this.unsubscribe();来取消订阅,才会继续执行
                System.out.println("继续执行后续代码。。。");
     
            } catch (Exception e) {
                System.out.println(String.format("subsrcibe channel error, %s", e));
            } finally {
                if (jedis != null) {
                    jedis.close();
                }
            }
        }
    }
    

    ④测试类

    package com.cqh.PubSub;
     
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
     
    /**
     * Created by yl1794 on 2018/3/28.
     */
    //测试类,键盘输入消息
    public class TestPubSub {
        public static void main( String[] args )
        {
            // 连接redis服务端
            JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379);
     
            Publisher publisher = new Publisher(jedisPool);    //发布者
            publisher.start();
     
            Subscriber subscriber = new Subscriber(jedisPool);    //订阅者
            subscriber.start();
     
     
        }
    }
    

    ⑤结果
    在这里插入图片描述

    3.java实现 redis的发布订阅

    半城枫叶半城雨丶

    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.9.0</version>
    </dependency>
    

    建立一个Publisher (发布者)

    public class Publisher extends Thread{
    
        private final JedisPool jedisPool;
    
        public Publisher(JedisPool jedisPool) {
            this.jedisPool = jedisPool;
        }
        
        @Override
        public void run() {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            Jedis jedis = jedisPool.getResource();   //连接池中取出一个连接
            while (true) {
                String line = null;
                try {
                    line = reader.readLine();
                    if (!"quit".equals(line)) {
                        jedis.publish("mychannel", line);   //从 mychannel 的频道上推送消息
                    } else {
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    再建立一个订阅者

    public class Subscriber extends JedisPubSub {
    
        public Subscriber(){}
        @Override
        public void onMessage(String channel, String message) {       //收到消息会调用
            System.out.println(String.format("receive redis published message, channel %s, message %s", channel, message));
        }
        @Override
        public void onSubscribe(String channel, int subscribedChannels) {    //订阅了频道会调用
            System.out.println(String.format("subscribe redis channel success, channel %s, subscribedChannels %d",
                    channel, subscribedChannels));
        }
        @Override
        public void onUnsubscribe(String channel, int subscribedChannels) {   //取消订阅 会调用
            System.out.println(String.format("unsubscribe redis channel, channel %s, subscribedChannels %d",
                    channel, subscribedChannels));
    
        }
    }
    

    这里订阅者需要继承JedisPubSub,来重写它的三个方法。用途 注释上已经写了,很简单。

    我们这里只是定义了一个订阅者,下面去订阅频道。

    public class SubThread extends Thread {
    
        private final JedisPool jedisPool;
        private final Subscriber subscriber = new Subscriber();
    
        private final String channel = "mychannel";
    
        public SubThread(JedisPool jedisPool) {
            super("SubThread");
            this.jedisPool = jedisPool;
        }
    
        @Override
        public void run() {
            System.out.println(String.format("subscribe redis, channel %s, thread will be blocked", channel));
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();   //取出一个连接
                jedis.subscribe(subscriber, channel);    //通过subscribe 的api去订阅,入参是订阅者和频道名
            } catch (Exception e) {
                System.out.println(String.format("subsrcibe channel error, %s", e));
            } finally {
                if (jedis != null) {
                    jedis.close();
                }
            }
        }
    }
    

    最后,再写一个测试类去跑一下。键盘输入消息,订阅者就会触发onMessage方法

    public class PubSubDemo {
    
        public static void main( String[] args )
        {
            // 连接redis服务端
            JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379);
            
            System.out.println(String.format("redis pool is starting, redis ip %s, redis port %d", "127.0.0.1", 6379));
    
            SubThread subThread = new SubThread(jedisPool);  //订阅者
            subThread.start();
    
            Publisher publisher = new Publisher(jedisPool);    //发布者
            publisher.start();
        }
    }
    

    打印结果:
    在这里插入图片描述

    4.在Java中使用Redis

    在Java中使用Redis

    4.1String

    import redis.clients.jedis.Jedis;
    
    public class Test {
        private Jedis jedis; 
        public static void main(String[] args) {
            //连接本地的 Redis 服务
            Jedis jedis = new Jedis("192.168.1.90",6379);
            jedis.auth("1");  
    
            //查看服务是否运行
            System.out.println("服务正在运行: "+jedis.ping());
            System.out.println("连接成功");
            
            //向key-->name中放入了value-->gp6  
            jedis.set("name","gp6");
            //执行结果:gp6  
            System.out.println(jedis.get("name"));
            
            //拼接
            jedis.append("name", " is my lover");
            //执行结果:gp6  is my lover
            System.out.println(jedis.get("name")); 
            
            jedis.del("name");  //删除某个键
            //执行结果:null
            System.out.println(jedis.get("name"));
            
            //设置多个键值对
            jedis.mset("name","gp6","age","24","qq","6266XXX01");
            //进行加1操作
            jedis.incr("age"); 
            //执行结果:gp6-25-6266XXX01
            System.out.println(jedis.get("name") + "-" + jedis.get("age") + "-" + jedis.get("qq"));
        }
    }
    

    4.2Map(Hash)

    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import redis.clients.jedis.Jedis;
    
    public class Test {
        private Jedis jedis; 
        public static void main(String[] args) {
            //连接本地的 Redis 服务
            Jedis jedis = new Jedis("192.168.1.90",6379);
            jedis.auth("1");  
    
            //查看服务是否运行
            System.out.println("服务正在运行: "+jedis.ping());
            System.out.println("连接成功");
            
            //-----添加数据----------  
            Map<String, String> map = new HashMap<String, String>();
            map.put("name", "gp6");
            map.put("age", "24");
            map.put("qq", "6266156XX");
            jedis.hmset("user",map);
            
            //取出user中的name,执行结果:[minxr]-->注意结果是一个泛型的List  
            //第一个参数是存入redis中map对象的key,后面跟的是放入map中的对象的key,后面的key可以跟多个,是可变参数  
            List<String> rsmap = jedis.hmget("user", "name", "age", "qq");
            //执行结果:[gp6, 24, 6266156XX]
            System.out.println(rsmap);  
               
            //删除map中的某个键值  
            jedis.hdel("user","age");
            System.out.println(jedis.hmget("user", "age")); //因为删除了,所以返回的是null  
            System.out.println(jedis.hlen("user")); //返回key为user的键中存放的值的个数2 
            System.out.println(jedis.exists("user"));//是否存在key为user的记录 返回true  
            System.out.println(jedis.hkeys("user"));//返回map对象中的所有key  
            System.out.println(jedis.hvals("user"));//返回map对象中的所有value 
            
            
            Iterator<String> iter = jedis.hkeys("user").iterator();  
            while (iter.hasNext()){  
                String key = iter.next(); 
                //执行两次,第一次结果:qq:[6266156XX]
                //执行两次,第二次结果:name:[gp6]
                System.out.println(key+":"+jedis.hmget("user",key));  
            }  
        }
    }
    

    4.3List

    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import redis.clients.jedis.Jedis;
    
    public class Test {
        private Jedis jedis; 
        public static void main(String[] args) {
            //连接本地的 Redis 服务
            Jedis jedis = new Jedis("192.168.1.90",6379);
            jedis.auth("1");  
    
            //查看服务是否运行
            System.out.println("服务正在运行: "+jedis.ping());
            System.out.println("连接成功");
            
            //开始前,先移除所有的内容  
            jedis.del("java framework");  
            //执行结果:[]
            System.out.println(jedis.lrange("java framework",0,-1)); 
            
            //先向key java framework中存放三条数据  
            jedis.lpush("java framework","spring");  
            jedis.lpush("java framework","struts");  
            jedis.lpush("java framework","hibernate");  
            //再取出所有数据jedis.lrange是按范围取出,  
            // 第一个是key,第二个是起始位置,第三个是结束位置,jedis.llen获取长度 -1表示取得所有 
            
            //执行结果:[hibernate, struts, spring]
            System.out.println(jedis.lrange("java framework",0,-1));  
                   
            jedis.del("java framework");
            jedis.rpush("java framework","spring");  
            jedis.rpush("java framework","struts");  
            jedis.rpush("java framework","hibernate");
            //执行结果:[spring, struts, hibernate]
            System.out.println(jedis.lrange("java framework",0,-1));
        }
    }
    
    

    4.4set

    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import redis.clients.jedis.Jedis;
    
    public class Test {
        private Jedis jedis; 
        public static void main(String[] args) {
            //连接本地的 Redis 服务
            Jedis jedis = new Jedis("192.168.1.90",6379);
            jedis.auth("1");  
    
            //查看服务是否运行
            System.out.println("服务正在运行: "+jedis.ping());
            System.out.println("连接成功");
            
            //添加  
            jedis.sadd("user1","gp6");  
            jedis.sadd("user1","carry");  
            jedis.sadd("user1","gao");  
            jedis.sadd("user1","liu");
            jedis.sadd("user1","who");  
            
            //移除noname  
            jedis.srem("user1","who");  
            //执行结果:[carry, gao, liu, gp6]
            System.out.println(jedis.smembers("user1"));//获取所有加入的value  
            //执行结果:false
            System.out.println(jedis.sismember("user1", "who"));//判断 who 是否是user1集合的元素 
            //执行结果:carry
            System.out.println(jedis.srandmember("user1"));  
            //执行结果:4
            System.out.println(jedis.scard("user1"));//返回集合的元素个数  
        }
    }
    

    4.5模拟Redis事务

    import java.sql.*;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import org.json.JSONObject;
    import org.json.JSONString;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.Transaction;
    
    public class Test {
        private Jedis jedis; 
        public static void main(String[] args) {
            //连接本地的 Redis 服务
            Jedis jedis = new Jedis("192.168.1.90",6379);
            System.out.println("Redis连接成功");
            
            //开启事务
            Transaction transaction = jedis.multi();
            
            transaction.set("k6", "v6");
            transaction.set("k7", "v7");
            
            //执行事务
            transaction.exec();
            
            //放弃事务
            //transaction.discard();
        }
    }
    

    4.6Watch监控

    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.Transaction;
    
    public class TestTransaction {
        public boolean transMethod() {
            Jedis jedis = new Jedis("192.168.1.90",6379);
            int balance;// 可用余额
            int debt;// 欠额
            int amtToSubtract = 10;// 实刷额度
            System.out.println(jedis.get("k4"));
    
            jedis.watch("balance");
            // jedis.set("balance","5");//此句不该出现,模拟其他程序已经修改了该条目,也可以在redis里面直接修改
            balance = Integer.parseInt(jedis.get("balance"));
    
            if (balance < amtToSubtract) {
                jedis.unwatch();
                System.out.println("modify");
                return false;
            } else {
                System.out.println("***********transaction");
                Transaction transaction = jedis.multi();
                transaction.decrBy("balance", amtToSubtract);
                transaction.incrBy("debt", amtToSubtract);
                transaction.exec();
                balance = Integer.parseInt(jedis.get("balance"));
                debt = Integer.parseInt(jedis.get("debt"));
    
                System.out.println("*******" + balance);
                System.out.println("*******" + debt);
                return true;
            }
        }
        
        /**
           * 通俗点讲,watch命令就是标记一个键,如果标记了一个键, 在提交事务前如果该键被别人修改过,那事务就会失败,这种情况通常可以在程序中
           * 重新再尝试一次。
           * 首先标记了键balance,然后检查余额是否足够,不足就取消标记,并不做扣减; 足够的话,就启动事务进行更新操作,
           * 如果在此期间键balance被其它人修改, 那在提交事务(执行exec)时就会报错, 程序中通常可以捕获这类错误再重新执行一次,直到成功。
           */
        public static void main(String[] args) {
            TestTransaction testTransaction = new TestTransaction();
            boolean retValue = testTransaction.transMethod();
            System.err.println("=======" + retValue);
        }
    }
    
  • 相关阅读:
    生产者消费者模型
    查看网络通不通的几种方法
    tomcat在45秒内没有启动,启动超时
    request获取各种路径
    修改web项目发布路径
    web.xml不同版本的头
    Web.xml 错误或异常页面配置
    ModelAndView command
    java初始化顺序
    初始化时的过程
  • 原文地址:https://www.cnblogs.com/aixing/p/13327336.html
Copyright © 2020-2023  润新知