【Redis】03--Java中操作redis

一,准备工作

1.创建工程

创建maven父工程,例如03-sca-redis,并在此工程下创建两个子工程,一个为sca-jedis,一个为sca-tempate,例如:
在这里插入图片描述

2.添加项目依赖

sca-jedis 工程依赖

<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>

在这里插入图片描述

添加sca-template工程依赖

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.3.2.RELEASE</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

在这里插入图片描述

二,Jedis的应用

1.简介

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

2.准备工作

第一步:从redis.io官方下载对应版本的redis.conf文件,地址如下
官方下载
第二步:停止redis并删除或者覆盖挂载目录下(/usr/local/docker/redis01/conf)的redis.conf配置文件.
停止redis服务
请添加图片描述

执行命令 docker inspect redis01 (我这里redis容器的名称设置为redis01),查看其挂载位置
请添加图片描述
第三步:将下载的redis.conf文件拷贝到redis挂载目录(/usr/local/docker/redis01/conf)
转到指定目录,因为现在存在的redis.conf是我们一开始创建的空的文件,所以,直接拖拽,覆盖该文件就好
在这里插入图片描述
第四步:基于vim打开redis.conf文件,然后注释 bind 127.0.0.1(不只限于本机使用)这一行,并修改protected-mode的值修改为no(将保护认证关闭,否则不经过认证,无法访问).,或者将该行注释一样的效果。
进入对应目录,打开redis.conf文件
请添加图片描述
进入文件后,按i进入编辑模式
请添加图片描述
请添加图片描述
按esc,:wq保存退出请添加图片描述
第五步:重启redis服务,并检查启动日志(docker logs 容器id)
请添加图片描述

3.快速入门实现

在Jedis工程中定义单元测试类,在类中定义单元测试方法:

连接测试

@Test
    public void testGetConnection() {
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //jedis.auth("123456");//假如设置了密码还要执行这个语句
        String ping = jedis.ping();
        System.out.println(ping); //PONG
    }

请添加图片描述
注意:这里的ip地址对应你redis所在容器的地址,我这里是192.168.126.128
请添加图片描述

字符串类型测试

@Test
    public void testStringOper() throws InterruptedException {
        //1.建立连接
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //2.向redis存储string类型数据
        jedis.set("id","1");
        jedis.set("name","Tony");
        jedis.set("token", UUID.randomUUID().toString());
        jedis.expire("token",2); //设置存在时长
        //3.更新redis中指定数据
        jedis.set("id","100");
        jedis.incr("id"); //自增 101
        jedis.incrBy("id",2); //自增 + 2 103
        jedis.decr("id"); //自减 102
        //4.删除redis中指定数据
        jedis.del("name");
        //5.查看redis中的数据
        String id = jedis.get("id");
        //Thread.sleep(2000);
        TimeUnit.SECONDS.sleep(1); //同上,休眠1s
        String token = jedis.get("token");
        Long strLen = jedis.strlen("token");
        String name = jedis.get("name");
        System.out.println("id = " + id);
        System.out.println("token = " + token);
        System.out.println("token.length = " + strLen);
        System.out.println("name = " + name);
        //6.释放资源
        jedis.close();
    }

在这里插入图片描述
当休眠时间设置的是 >= 2s 时,则token就不存在
在这里插入图片描述
在这里插入图片描述

Hash类型的测试

//对Hash类型的测试
    @Test
    public void testHashOper() {
        //1.建立连接
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //2.向redis存储数据
        jedis.hset("user","id","100");
        jedis.hset("user","name","drh");
        jedis.hset("user","age","man");
        jedis.hset("user","mobile","11111111111");
        //3.更新redis中指定数据
        jedis.hset("user","id","101");
        //4.删除redis中指定数据
        jedis.hdel("user","age","mobile");
        //5.查看redis中的数据
        String id = jedis.hget("user", "id");
        System.out.println("user.id = " + id);
        Map<String,String> user = jedis.hgetAll("user");
        System.out.println("user = " + user);
        //6.释放资源
        jedis.close();
    }

在这里插入图片描述

Hash直接存取map对象

/**直接存取map对象*/
    @Test
    public void testHashOper02() {
        //1.建立连接
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //2.存储一个map对象
        Map<String,String> map = new HashMap<>();
        map.put("x","100");
        map.put("y","200");
        jedis.hset("point",map);
        //3.读取一个map对象
        Map<String,String> point = jedis.hgetAll("point");
        System.out.println(point);
    }

在这里插入图片描述

对json类型数据的测试

//对json类型数据的测试
    /**
     * 将对象转换为json字符串,再存储到redis中
     * 这种方式的最大弊端就是修改数据不方便,需要先修改map,然后再转换为json字符串,再存储
     */
    @Test
    public void testStringJsonOer() {
        //1.建立连接
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //2.将对象转换为json字符窜
        Map<String,Object> map = new HashMap<>();
        map.put("id","101");
        map.put("name","drh");
        Gson gson = new Gson(); //Google公司提供
        String jsonStr = gson.toJson(map); //将map转换为json串
        System.out.println("jsonStr = " + jsonStr);
        //3.将json字符窜存储到redis
        jedis.set("member",jsonStr);
        //4.取出member对象的值
        String member = jedis.get("member");
        System.out.println("member = " + member);
        //5.将json字符窜转换为Map对象
        map = gson.fromJson(member,Map.class);
        System.out.println(map);
        //6.释放资源
        jedis.close();
    }

在这里插入图片描述

list类型测试

 //list类型测试
    @Test
    public void testListOper01() {
        //1.建立连接
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //2.存储数据(list集合有顺序,允许重复)
        jedis.lpush("lst1","A","B","C","C");
        //3.修改数据
        //3.1首先获取要修改的元素的下表
        Long index = jedis.lpos("lst1","A");
        //3.2基于下表,修改元素内容
        jedis.lset("lst1",index,"D");
        //4.删除数据
        //5.查询数据
        List<String> lst1 = jedis.lrange("lst1",0,-1);
        System.out.println(lst1);
        //6.释放资源
        jedis.close();
    }

在这里插入图片描述

list阻塞队列

	/**
     * 阻塞式队列
     */
    @Test
    public void testListOper02() {
        //1.建立连接
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //2.存储数据
        jedis.lpush("lst2","A","B","C");
        //3.按先进先出的顺序从队列取数据
        List<String> list = jedis.brpop(40,"lst2");
        System.out.println(list);
        jedis.brpop(40,"lst2");
        jedis.brpop(40,"lst2");
        jedis.brpop(40,"lst2");
        //4.释放资源
        jedis.close();
    }

请添加图片描述
当lst2中数据全部删除后,阻塞了40s

set类型测试

//set类型测试
    @Test
    public void testSetOper() {
        //1.建立连接
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //2.存储数据(Set集合没有顺序,不允许重复)
        jedis.sadd("set1","A","A","B","C","D ");
        //3.修改数据
        //4.删除数据
        jedis.spop("set1"); //随机删除一个元素
        jedis.srem("set1","B");
        //5.查询数据
        Set<String> set1 = jedis.smembers("set1");
        System.out.println(set1);
        Long cards = jedis.scard("set1");
        System.out.println(cards); //查看元素个数
        //6.释放数据
        jedis.close();
    }

在这里插入图片描述

4.简易功能实现

单点登录

业务描述
在分布式系统中,通过会有多个服务,我们登录了一个服务以后,再访问其它服务时,不想再登录,就需要有一套单独的认证系统,我们通常会称之为单点登录系统,在这套系统中提供一个认证服务器,服务完成用户身份认证,在一些中小型分布式系统中中,我们通常会借助redis存储用户的认证信息,例如:
在这里插入图片描述
关键代码

package com.jt.redis;

import redis.clients.jedis.Jedis;

import java.util.UUID;

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

运行结果
当我们模仿第一次访问资源时
在这里插入图片描述
在这里插入图片描述
当我们模拟登录后访问资源
在这里插入图片描述
在这里插入图片描述
当我们模拟登录时长超过10s时
在这里插入图片描述

在这里插入图片描述

简易分布式id生成策略

业务描述
在分布式系统中,数据量将越来越大时,就需要对数据进行分表操作,但是,分表后,每个表中的数据都会按自己的节奏进行自增,很有可能出现ID冲突。这时就需要一个单独的机制来负责生成唯一ID,生成出来的ID也可以叫做 分布式ID,这里我们借助redis实现一个简易的分布式id进行实现,当然还有一些第三方的系统,可以帮你生成这样的id,可以自己进行拓展学习
关键代码

package com.jt.redis;

import redis.clients.jedis.Jedis;

public class IdGenerator {
    /**
     * 编写一个方法,每次调用此方法
     * 外界都能够获取一个唯一的一个递增
     * 整数值
     */
    public static Long getId() {
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //incr方法用于对指定key的值进行递增,假如key不存在,则自动创建
        long id = jedis.incr("incrementId");
        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();
        }
    }
}

在这里插入图片描述
再执行一次
在这里插入图片描述

简易秒杀队列

业务描述

在设计一个秒杀或抢购系统时,为了提高系统的响应速度,通常会将用户的秒杀或抢购请求先存储到一个redis队列,这里我们就基于redis实现一个先进先出队列,例如:
在这里插入图片描述
关键代码

import java.util.List;

/**
 * 演示抢购活动中的秒杀队列
 * 数据逻辑结构:list
 * 算法:FIFO(公平性)
 * 在抢购活动中会执行这样的操作
 * 1)生产者(购买商品的用户):创建请求并将请求存储到队列
 * 2)消费者(处理购买请求的底层对象):从队列取请求,然后处理请求
 */
public class SecondsKillDemo01 {
    public static void main(String[] args) {
        //1.构建生产者(购买商品的用户)
        Thread t1 = new Thread() {
            @Override
            public void run() {
                int i = 1;
                for (;;) {
                    enqueue("request-" + i++);
                    try {
                        Thread.sleep(1000); //1s一个线程
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        //2.构建消费者(处理请求的对象)
        Thread t2 = new Thread() {
            @Override
            public void run() {
                for (;;) {
                    String request = dequeue();
                    if (request == null) continue;
                    System.out.println("process " + request);
                }
            }
        };
        //3.开启抢购活动
        t1.start();
        t2.start();
    }

    /**
     * 入队操作
     */
    public static void enqueue(String request) {
        Jedis jedis = new Jedis("192.168.126.128",6379);
        jedis.lpush("queue-1",request);
        jedis.close();
    }

    /**
     * 出队操作
     */
    public static String dequeue() {
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //非阻塞式取数据
        //return jedis.rpop("queue-1");
        //阻塞式取数据
        List<String> request = jedis.brpop(60,"queue-1"); //返回{"queue-1","request-x"}
        jedis.close();
        return request != null ? request.get(1) : null; //下表为0的时key 即queue-1
    }
}

运行结果
在这里插入图片描述

简易投票系统

业务描述
在很多系统中设计中,都会有一个活动设计,开启一个活动之前,可以对这个活动的支持力度先进行一个调查,例如基于这个活动设计一个投票系统,例如:
在这里插入图片描述
关键代码

package com.jt.redis;

import redis.clients.jedis.Jedis;

import java.util.Set;

/**
 * 投票系统演示:模拟基于某个活动的投票程序
 * 业务说明:一个用户只能投票一次(不允许重复)
 * 数据结构设计:基于redis的set类型进行数据存储
 */
public class VoteDemo01 {
    //进行投票(key为活动id,value为userId)
    public static void vote(String activityId,String userId) {
        Jedis jedis = new Jedis("192.168.126.128",6379);
        jedis.sadd(activityId,userId);
        jedis.close();
    }
    //查看投票次数
    public static Long getVoteCount(String activityId) {
        Jedis jedis = new Jedis("192.168.126.128",6379);
        Long count = jedis.scard(activityId);
        jedis.close();
        return count;
    }
    //查看这个活动被哪些用户投过票
    public static Set<String> getVoteUsers(String activityId) {
        Jedis jedis = new Jedis("192.168.126.128",6379);
        Set<String> smembers = jedis.smembers(activityId);
        jedis.close();
        return smembers;
    }
    //检查这个用户是否已对这个活动投过票
    public static Boolean checkVote(String activityId,String userId) {
        Jedis jedis = new Jedis("192.168.126.128",6379);
        Boolean flag = jedis.sismember(activityId,userId);
        jedis.close();
        return flag;
    }
    //模拟投票客户端
    public static void main(String[] args) {
        //1.初始化
        String activityId = "10001";
        String user1 = "201";
        String user2 = "202";
        String user3 = "203";
        //2.投票
        vote(activityId,user1);
        vote(activityId,user2);
        vote(activityId,user3);
        vote(activityId,user3);
        //3.获取投票次数
        Long voteCount = getVoteCount(activityId);
        System.out.println("投票次数:" + voteCount);
        //4.输出哪些人投过票
        Set<String> users = getVoteUsers(activityId);
        System.out.println(users);
        //5.检查用户是否投过票
        boolean flag = checkVote(activityId,user1);
        System.out.println(user1 + ":" + (flag ? "已投过票" : "还没投票"));
    }
}

运行结果
在这里插入图片描述

简易购物车实现

业务描述
简易购物车业务设计如图所示:
在这里插入图片描述
基础指令操作,例如:

1)向购物车添加商品
hset  cart:101  2001  1
hset  cart:101  2002  1
hset  cart:101  2003  2
2)查看购物车商品
hgetall cart:101
3)删除购物车商品
hdel cart:101 2003
4)改变购物车某个商品的购买数量
hincrby cart:101 2002 2

关键代码

package com.jt.redis;

import redis.clients.jedis.Jedis;

import java.util.Map;

/**
 * 基于redis存储商品购物车信息
 */
public class CartDemo01 {
    //添加商品
    public static void addCart(Long userId,Long productId,int num) {
        //1.建立连接
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //2.向购物车添加商品
        //hincrBy这个函数在key不存在时会自动创建key
        jedis.hincrBy("cart:" + userId,String.valueOf(productId),num);
        //3.释放redis链接
        jedis.close();
    }
    //查看我的购物车
    public static Map<String,String> listCart(Long userId) {
        //1.建立连接
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //2.查看购物车商品
        Map<String,String> map = jedis.hgetAll("cart:" + userId);
        //3.释放redis链接
        jedis.close();
        return map;
    }
    //删除某些商品
    public static void doDelCart(Long userId,String ...productId) {
        //1.建立连接
        Jedis jedis = new Jedis("192.168.126.128",6379);
        //2.清除指定商品
        jedis.hdel("cart:" + userId, productId);
        //3.释放资源
        jedis.close();
    }
    //模拟购物车
    public static void main(String[] args) {
        //1.向购物车添加商品
        addCart(1L,201L,1);
        addCart(1L,202L,1);
        addCart(1L,203L,2);
        //2.查看购物车商品
        Map<String,String> map = listCart(1L);
        System.out.println("刚开始购物车:");
        System.out.println(map);
        //3.清除购物车
        doDelCart(1L,"201","203");
        map = listCart(1L);
        System.out.println("删除商品后购物车");
        System.out.println(map);
    }
}

运行结果
第一次执行
在这里插入图片描述
第二次执行
在这里插入图片描述
已发生递增
当添加删除操作后
在这里插入图片描述

5.连接池JedisPool应用

我们直接基于Jedis访问redis时,每次获取连接,释放连接会带来很大的性能开销,可以借助Jedis连接池,重用创建好的连接,来提高其性能,简易应用方式如下:
先做测试

package com.jt;

import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * 测试jedis连接池的一个基本应用
 */
public class JedisPoolTests {
    @Test
    public void testJedisPool() {
        //1.构建jedis连接池
        //1.1定义连接池配置
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(16);//最大连接数默认为8
        config.setMaxIdle(60);//最大空闲时间(连接后续不用了,超出一定空闲时间要释放)
        //1.2定义连接的url和端口
        String host = "192.168.126.128";
        int port = 6379;
        //1.3创建连接池
        JedisPool jedisPool = new JedisPool(config,host,port);
        //2.从池中获取连接(jedis对象)
        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();
    }
}

测试结果
在这里插入图片描述
我们可以基于池对象,设计一个数据源,将来在业务中通过一个数据源对象,从池中获取连接,不用每次获取连接都要创建池对象,例如:

package com.jt.redis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisDataSource {
    private static final JedisPool jedisPool;
    private static final String HOST = "192.168.126.128";
    private static final int PORT = 6379;
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(16);//最大连接数,默认为8
        config.setMaxIdle(60);
        jedisPool = new JedisPool(config,HOST,PORT);
    }

    /**
     * 获取一个连接对象
     * @return
     */
    public static Jedis getConnection() {
        return jedisPool.getResource();
    }
    public static JedisPool getJedisPool() {
        return jedisPool;
    }
}

这样我们在连接时,只需要调用这个方法即可
在这里插入图片描述

5.StringRedisTemplate 应用

配置application.yml文件
在这里插入图片描述
并且打开对应ip和端口的redis服务。
StringRedisTemplate 是一个专门用于操作redis字符串类型数据的一个对象,其应用方式如下:

package com.cy.redis;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.RedisConnection;

import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SpringBootTest
public class StringRedisTemplateTests {
    /**
     * 此对象 操作redis的一个客户端对象,这个对象
     * 对key/value采用了字符串的序列化方式进行
     * redis数据的读写操作
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Test
    public void testGetConnection() {
        RedisConnection connection = stringRedisTemplate.getConnectionFactory().getConnection();
        String ping = connection.ping();
        System.out.println(ping);
    }
    @Test
    public void testStringOper01() {
        //1.获取字符串操作对象
        ValueOperations<String,String> vo = stringRedisTemplate.opsForValue();
        //读写redis中的数据
        vo.set("x","100");
        String x = vo.get("x");
        System.out.println("String类型测试1");
        System.out.println(x);
    }
    @Test
    public void testStringOper02() throws JsonProcessingException {
        //获取字符串操作对象
        ValueOperations<String,String> vo = stringRedisTemplate.opsForValue();
        //2.读写redis中的数据
        Map<String,String> map = new HashMap<>();
        map.put("id","01");
        map.put("name","drh");
        //将map对象转换为json字符串写到redis数据库
        String jsonStr = new ObjectMapper().writeValueAsString(map);
        vo.set("blog",jsonStr);
        jsonStr = vo.get("blog");
        System.out.println("String类型测试2");
        System.out.println(jsonStr);
        map = new ObjectMapper().readValue(jsonStr,Map.class);
        System.out.println(map);
    }
    @Test
    public void testHashOper01() {
        //1.获取hash操作
        HashOperations<String,Object,Object> vo = stringRedisTemplate.opsForHash();
        //2.读取redis数据
        //2.1 存储一个对象
        vo.put("user","id","100");
        vo.put("user","username","drh");
        vo.put("user","status","1"); //注意这里1必须是字符串形式
        //2.2获取一个对象
        //2.2.1获取对象某个属性的值
        Object username = vo.get("user","username");
        System.out.println("Hash类型测试");
        System.out.println(username);
        //2.2.2获取对象所有的值
        List<Object> user = vo.values("user");
        System.out.println(user);
    }
}

注意导包别导错了
运行结果:
在这里插入图片描述

6.RedisTemplate 应用

RedisTemplate是一个专门用于实现对远端redis中复杂数据的操作的对应,应用案例如下:

package com.cy.redis;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.xml.transform.Source;
import java.util.*;

@SpringBootTest
public class RedisTemplateTests {
    //这个对象在spring boot工程的RedisAutoConfiguration类中已经做了配置
    //此对象在基于redis存储数据时默认采用序列化的方式
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void testGetConnection() {
        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
        String ping = connection.ping();
        System.out.println("连接测试");
        System.out.println(ping);
    }

    /**
     * 测试String类型的数据
     */
    @Test
    public void testStringOper01() {
        //自己指定key/value序列化方式
        //redisTemplate.setKeySerializer(new StringRedisSerializer());
        //redisTemplate.setValueSerializer(new StringRedisSerializer());
        ValueOperations vo = redisTemplate.opsForValue();
        //key和value默认会采用JDK的序列化的方式进行存储
        vo.set("token", UUID.randomUUID().toString());
        Object token = vo.get("token");
        System.out.println("String类型测试");
        System.out.println(token);
    }

    /**
     * 测试hash类型的数据
     */
    @Test
    public void testHashOper01() {
        //1.获取操作hash类型数据的操作对象
        HashOperations ho = redisTemplate.opsForHash();
        //2.读写redis数据hash类型数据
        Map<String,Object> map = new HashMap<>();
        map.put("id",100);
        map.put("title","spring boot");
        //直接存储一个map
        ho.putAll("blog",map); //hash存储 序列化
        //存储单个字段,值
        ho.put("blog","content","spring boot redis");
        //取blog对象中id属性的值
        Object o = ho.get("blog", "id");
        System.out.println("Hash类型测试");
        System.out.println("id = " + o);
        //获取整个blog对象所有属性和值
        Map blog = ho.entries("blog"); //反序列化
        System.out.println(blog);
    }

    /**
     * 测试list类型的数据
     */
    @Test
    public void testListOper01() {
        //1.获取操作list类型数据的操作对象
        ListOperations lo = redisTemplate.opsForList();
        //2.读写redis数据list类型数据
        lo.leftPush("lst1","A");
        lo.leftPushAll("lst1","B","C","D","D");
        //取数据
        List lst1 = lo.range("lst1", 0, -1);
        System.out.println("List类型测试");
        System.out.println(lst1);
    }
    @Test
    public void testSetOper01() {
        //1.获取操作list类型数据的操作对象
        SetOperations so = redisTemplate.opsForSet();
        //2.读写redis数据set类型数据
        so.add("set1","A","B","C","C"); //不允许重复
        Set set = so.members("set1");
        System.out.println("set类型测试");
        System.out.println(set);
    }
}

注意导包
运行结果,首先观察一个现象。我们测试String类型时,查看redis数据库时,如下图
请添加图片描述
key和value默认会采用JDK的序列化方式进行存储
如果需要在数据库中也显示我们存入的数据,需要自己设置序列化的方式
在这里插入图片描述
请添加图片描述
在这里插入图片描述

7.定制RedisTemplate对象

对于系统默认的RedisTemplate默认采用的是JDK的序列化机制,假如我们不希望实用JDK的序列化,可以采用的定制RedisTemplate,并采用自己指定的的序列化方式,例如:

package com.jt.redis.config;
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        //1.构建RedisTemplate对象
        RedisTemplate<Object,Object> redisTemplate=new RedisTemplate<>();
        //2.设置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //3.定义序列化方式(在这里选择jackson)
        Jackson2JsonRedisSerializer redisSerializer= new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper=new ObjectMapper();
        //设置要序列化的域(属性)
        //any表示任意级别访问修饰符修饰的属性 private,public,protected
        objectMapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
        //启动输入域检查(类不能是final修饰的)
        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY);
        redisSerializer.setObjectMapper(objectMapper);
        //4.设置RedisTemplate的序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(redisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(redisSerializer);
        //spring规范中假如修改bean对象的默认特性,建议调用一下afterPropertiesSet()
        redisTemplate.afterPropertiesSet();
       return redisTemplate;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值