03.Redis---Java操作Redis---Jedis

Jedis是Java中操作redis的一个客户端,类似通过jdbc访问mysql数据库。

一、基本操作

1.添加pom依赖


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

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

2.测试连接

 @Test
    public void testGetConnection(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        //jedis.auth("密码") 数据库有密码的话执行它
        String ping = jedis.ping();
        System.out.println(ping);
    }
}

3.String类型练习

 @Test
    public void testStringOper() throws InterruptedException {
        //建立链接(与redis建立链接)
        Jedis jedis=new Jedis("192.168.126.130",6379);
        //存储数据(key/value)
        jedis.set("count","1");
        jedis.set("id","10001");
        jedis.set("content","aaaaaaaadfas");
        //更新数据
        jedis.expire("id",1);//设置key的有效时长
        jedis.incr("count");//对key的值进行自增操作
        //获取数据
        String count = jedis.get("count");
        //TimeUnit是Java中枚举类型,SECONDS为枚举类型的实例,sleep底层会调用Thread.sleep()方法
        //TimeUnit.SECONDS.sleep(1);//休眠一秒
        Thread.sleep(1000);
        String id=jedis.get("id");
        Long num=jedis.strlen("content");
        System.out.println("cart.count="+count);
        System.out.println("id="+id);
        System.out.println("num="+num);
        //释放资源
        jedis.close();
    }
//json数据练习
@Test
 public void testJsonOper(){
     //构建对象
      Map<String,Object> map=new HashMap<>();
      map.put("id",100);
      map.put("title","spring 认证");
      map.put("content","very good");
     //将对象转换为json格式字符串
      Gson gson=new Gson();
      String jsonStr=gson.toJson(map);
      //将json字符串写入到redis
      Jedis jedis=new Jedis("192.168.126.128",6379);
      jedis.set("user",jsonStr);
      //读取redis中数据
      jsonStr=jedis.get("user");
      System.out.println(jsonStr);
      Map<String,Object> obj=gson.fromJson(jsonStr,Map.class);
      System.out.println(obj);
      jedis.close();
 }

这样情况下的修改太麻烦了,还需要把把json串再次转化为map对象再修改再改回去,所以一般不用这个,我们用Hash

4.Hash类型练习

  @Test
  public void testHashOper01(){
        //1.建立连接
        Jedis jedis=new Jedis("192.168.126.130",6379);
        //2.基于hash类型存储对象信息
        jedis.hset("member","id","101");
        jedis.hset("member","username","jack");
        jedis.hset("member","mobile","3333333");
        //3.更新hash类型存储的数据
        jedis.hset("member","username","tony");
        //4.获取hash类型数据信息
        String username=jedis.hget("member","username");
        String mobile = jedis.hget("member", "mobile");
        System.out.println(username);
        System.out.println(mobile);
        //5.释放资源
        jedis.close();
    }
//hash类型练习(直接存储map对象)
@Test
public void testHashOper02(){
    //1.建立连接
    Jedis jedis=new Jedis("192.168.126.130",6379);
    //2.存储一篇博客信息
    Map<String,String> map=new HashMap<>();
    map.put("x","100");
    map.put("y","200");
    jedis.hset("point",map);
    //3.获取博客内容并输出
    map=jedis.hgetAll("point");
    System.out.println(map);
    //4.释放资源
    jedis.close();
}

5.List类型练习

模拟先进先出队列

@Test
    public void testListOper01(){
        //1.连接
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.flushAll();
        //2.存储
        jedis.lpush("list1", "A","B","C","C");
        //3.修改
        Long index = jedis.lpos("list1", "A");
        jedis.lset("list1", index, "D");
//        Long Cindex = jedis.lpos("list1", "C");
        //4.删除
        jedis.rpop("list1",1);
        //5.查询
        System.out.println(jedis.lrange("list1", 0, -1));
        //6.释放
        jedis.close();
    }

模拟阻塞式队列

@Test
    public void testListOper02(){
        //1.连接
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.flushAll();
        //2.存储
        jedis.lpush("list2", "A","B","C");
        //3.基于阻塞方式取数据
        System.out.println(jedis.brpop(20, "list2"));
        System.out.println(jedis.brpop(20, "list2"));
        System.out.println(jedis.brpop(20, "list2"));
        System.out.println(jedis.brpop(20, "list2"));

        //4.释放
        jedis.close();
    }

        list取完为空时,运行不会停止,进入等待状态,cpu使用权转移,当集合里出现了新的内容或者等待超时时会自动停止运行

6.Set类型练习

@Test
public void testSetOper01() {
    //1.连接redis
    Jedis jedis = new Jedis("192.168.126.128", 6379);
    //2.朋友圈点赞
    jedis.sadd("count", "1", "1", "2");
    //3.取出点赞数
    Set<String> set = jedis.smembers("count");
    System.out.println(set);
    //4.释放资源
    jedis.close();
}

        这样的操作的问题在于频繁的连接和释放资源会对性能有所下降,我们可以利用池的概念创建一个Redis连接池

二、连接池

 public void testJedisPool(){
        //0.构建连接池配置
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(16);//最大连接数默认为8
        config.setMaxIdle(60);//最大空闲时间,超时后会释放连接
        final  String IP="192.168.126.129";
        final  int PORT=6379;
        //1.构建jedis连接池
        JedisPool jedisPool = new JedisPool(config, IP, PORT);
        //2.从池中获取连接
        Jedis resource = jedisPool.getResource();
        //3.执行redis操作
        resource.set("pool", "JedisPool");
        String pool = resource.get("pool");
        System.out.println(pool);
        //4.释放(不是关闭,而是将连接还回池中)
        resource.close();
        //5.关闭连接池(一般不关,服务停止时才关)
        //jedisPool.close();

    }

我们可以创建一个数据源,将来直接调用获取连接就好了

public class JedisDataSource {
    final static String IP="192.168.126.129";
    final static int PORT=6379;
    private static final JedisPool jedisPool;
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxIdle(60);
        config.setMaxTotal(16);
        jedisPool = new JedisPool(config, IP, PORT);
    }

    public static Jedis getConnection(){
        return jedisPool.getResource();
    }
    public static JedisPool getJedisPool() {
        return jedisPool;
    }
}

三、实战练习Demo

1.投票系统简易设计

public class VoteDemo01 {
    final static String IP="192.168.126.129";
    final static int PORT=6379;
    /*投票*/
    static void doVote(String activityId,String userId){
        //1.创建jedis对象
        Jedis jedis = new Jedis(IP, PORT);
        //2.投票
        jedis.sadd(activityId, userId);
        //3.释放
        jedis.close();
    }
    /*查看活动投票数量*/
    static Long doGetVotes(String activityId){
        //1.创建jedis对象
        Jedis jedis = new Jedis(IP, PORT);
        //2.查看活动的投票数
        Long count = jedis.scard(activityId);
        //3.释放
        jedis.close();
        return count;

    }
    /*获取参与投票的用户*/
    static Set<String> doGetUsers(String activityId){
        //1.创建jedis对象
        Jedis jedis = new Jedis(IP, PORT);
        //2.查看参与投票的用户
        Set<String> smembers = jedis.smembers(activityId);
        //3.释放
        jedis.close();
        return smembers;

    }
    /*检查是否参与过投票*/
    static Boolean isVote(String activityId,String userId){
        //1.创建jedis对象
        Jedis jedis = new Jedis(IP, PORT);
        //2.检查是否参与投票
        Boolean flag = jedis.sismember(activityId, userId);
        //3.释放
        jedis.close();
        return flag;


    }
    public static void main(String[] args) {
        //1.定义活动ID,用户ID
        String user1="yjh";
        String user2="zzf";
        String activityId="1001";
        //2.投票检查
        Boolean flag = isVote(activityId, user1);
        //3.投票
        if (flag==true){
            System.out.println("已经投过了,换个人再来把");
            return;
        }
        doVote(activityId, user1);
        doVote(activityId, user2);
        //4.查看投票总数
        Long aLong = doGetVotes(activityId);
        System.out.println(activityId+"号的投票总数为:"+aLong);
        //5.获取参与投票用户
        Set<String> users = doGetUsers(activityId);
        System.out.println("参与"+activityId+"活动的投票用户为"+users);

    }
}

2.分布式ID生成策略

//分布式ID生成策略
public class IdGenerator {
    /*每次调用此方法都可以得到一个唯一的递增的整数值*/
    public static Long getId(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        Long id = jedis.incr("id");
        jedis.close();
        return id;
    }

    public static void main(String[] args) {
        for (int i=0;i<10;i++){
            new Thread(){
                @Override
                public void run(){
                    System.out.println(IdGenerator.getId());
                }
            }.start();
        }
    }
}

3.购物车简易实现

/*性能高于数据安全可以存储到redis*/
public class CartDemo01 {
    final static String IP="192.168.126.129";
    final static int PORT=6379;
    //添加商品
    //修改商品数量
    static void doAddCart(String userId,String productId,int num){
        //1.创建Jedis对象
        Jedis jedis = new Jedis(IP, PORT);
        //2.基于hash存储商品信息
        jedis.hincrBy("cart:"+userId, productId, num);
        //3.释放
        jedis.close();
    }
    //查看购物车商品
    static Map<String, String> doViewCart(String userId){
        //1.创建Jedis对象
        Jedis jedis = new Jedis(IP, PORT);
        //2.查看购物车信息
        Map<String, String> cart = jedis.hgetAll("cart:" + userId);
        //3.释放
        jedis.close();
        return cart;

    }
    //清空购物车
    static void delAll(String userId){
        //1.创建Jedis对象
        Jedis jedis = new Jedis(IP, PORT);
        //2.设置有效期为0
        jedis.expire("cart:"+userId, 0);
        //3.释放
        jedis.close();
    }


    //删除购物车商品
    /*
    *用连接池获取连接
    * */
    static void delCart(String userId,String... productId){
        //1.创建Jedis对象
        Jedis jedis = JedisDataSource.getConnection();
        //2.删除
        jedis.hdel("cart:" + userId, productId);
        //3.释放
        jedis.close();
    }
    public static void main(String[] args) {
        String userId="yjh";
        //1.购买商品时,将商品信息添加到购物车
        doAddCart(userId, "201",1);
        doAddCart(userId, "202",2);
        doAddCart(userId, "203",3);
        //2.修改购物车商品数量
        doAddCart(userId, "201",2);
        doAddCart(userId, "202",1);
        doAddCart(userId, "203",7);
        //3.查看购物车商品
        Map<String, String> cart = doViewCart(userId);
        System.out.println(cart);
        //4.删除购物车商品
        delCart(userId, "203");
        System.out.println(doViewCart(userId));
        //5.清空购物车
        delAll(userId);
        System.out.println(doViewCart(userId));

    }
}

4.抢购秒杀队列

算法:FIFO

逻辑:生产者(购买商品的用户):创建请求并将请求存储到队列 消费者(处理购买请求的底层对象):从队列取请求,然后处理请求

public class SecondsKillDemo01 {

    /**
     * 入队操作
     */
    public static void enque(String request){
        Jedis jedis=new Jedis("192.168.126.129", 6379);
        jedis.lpush("queue-1",request);
        jedis.close();
    }
    /**
     * 出队操作
     */
    public static String deque(){
        Jedis jedis=new Jedis("192.168.126.129", 6379);
        //非阻塞式取数据
        //return jedis.rpop("queue-1");
        //阻塞式取数据
        List<String> list = jedis.brpop(3, "queue-1");
        jedis.close();
        return list!=null?list.get(1):null;//0为key
    }

    public static void main(String[] args) {
        //1.构建生产对象(购买商品的用户)
        Thread t1=new Thread(){
            @Override
            public void run() {
                for(int i=1;i<=10;i++){
                    enque("request-"+i);
                }
            }
        };
        //2.构建消费者对象(处理请求的对象)
        Thread t2=new Thread(){
            @Override
            public void run() {
                for(;;){
                    String request=deque();
                    if(request==null)continue;
                    System.out.println("process "+request);
                }
            }
        };
        //3.开启抢购活动
        t1.start();
        t2.start();
    }
}

5.简易单点登录

方案一

/**
 * SSO(单点登录系统) 案例演示:
 * 1)访问资源(假如没有登录,要提示先登录,如何判定是否登录了)
 * 2)执行登录(登录成功,存储用户登录信息)
 * 3)访问资源(已登录)
 * 解决方案
 * 1)方案1:SpringSecurity+jwt+oauth2 (并发比较大)
 * 2)方案2:SpringSecurity+redis+oauth2 (中小型并发)
 *
 */
public class SSODemo01 {
    /**认证中心的登录设计*/
    static String doLogin(String username,String password){
        //1.执行用户身份校验
        if(!"jack".equals(username))//将来这个jack来自数据库
            throw new IllegalArgumentException("这个用户不存在");
        //2.用户存在并且密码正确,表示用户是系统的合法用户
        if(!"123456".equals(password))
            throw new IllegalArgumentException("密码不正确");
        //3.将合法用户信息存储到redis
        Jedis jedis=new Jedis("192.168.126.129", 6379);
        String token=UUID.randomUUID().toString();
        jedis.set(token,username);
        jedis.expire(token, 2);
        jedis.close();
        return token;//token
    }
    /**获取资源服务中的资源*/
    static Object doGetResource(String token){
        //1.检查用户是否已经登录
        if(token==null||"".equals(token))
            throw new IllegalArgumentException("请先登录");
        Jedis jedis=new Jedis("192.168.126.129", 6379);
        String username=jedis.get(token);
        jedis.close();
        //2.假如没有登录,则提示先登录
        if(username==null)
            throw new RuntimeException("登录超时或token无效,请重新登录");
        //3.已登录则可以访问资源
        System.out.println("继续访问资源");
        //.....
        return "the resource of user";
    }
    //假设这里的main方法为客户端
    public static void main(String[] args) throws InterruptedException {
        String token=null;
        //第一次访问资源
        // doGetResource(token);
        //执行登录操作(将来认证要在认证中心实现)
        token=doLogin("jack", "123456");
        //第二次访问资源
        doGetResource(token);
    }
}

方案二

public class SSODemo02 {
    /**认证中心的登录设计*/
    static String doLogin(String username,String password){
        //1.执行用户身份校验
        if(!"jack".equals(username))//将来这个jack来自数据库
            throw new IllegalArgumentException("这个用户不存在");
        //2.用户存在并且密码正确,表示用户是系统的合法用户
        if(!"123456".equals(password))
            throw new IllegalArgumentException("密码不正确");
        //3.将合法用户信息存储到redis
        Jedis jedis=new Jedis("192.168.126.129", 6379);
        String token=UUID.randomUUID().toString();
        jedis.hset(token,"username",username);
        jedis.hset(token, "status", "1");
        //....
        jedis.expire(token, 2);
        jedis.close();
        return token;//token
    }
    /**获取资源服务中的资源*/
    static Object doGetResource(String token){
        //1.检查用户是否已经登录
        if(token==null||"".equals(token))
            throw new IllegalArgumentException("请先登录");
        Jedis jedis=new Jedis("192.168.126.129", 6379);
        Map<String,String> map=jedis.hgetAll(token);
        jedis.close();
        //2.假如没有登录,则提示先登录
        if(map==null||map.isEmpty())
            throw new RuntimeException("登录超时或token无效,请重新登录");
        //3.已登录则可以访问资源
        System.out.println("继续访问资源");
        //.....
        return "the resource of user";
    }
    //假设这里的main方法为客户端
    public static void main(String[] args) throws InterruptedException {
        String token=null;
        //第一次访问资源
        // doGetResource(token);
        //执行登录操作(将来认证要在认证中心实现)
        token=doLogin("jack", "123456");
        //第二次访问资源
        doGetResource(token);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值