Spring整合Redis

在这里插入图片描述

1.pom.xml

	<!--redis-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>

2.application.properties

#RedisProperties
##{选库,redis自带16个库,选择第12个,也就是11}
spring.redis.database=11
##{配置ip地址}
spring.redis.host=localhost
##{配置端口号}
spring.redis.port=6379

3.RedisConfig

写一个配置类,构造redisTemplate组件,这是由spring提供给我们的.
springboot也对redis做了一个自动的配置,自己配好了RedisTemplate的配置。因为redis是<key,value>的结构的,它把key做成了Object类型,更通用。
但是用的时候我们几乎都是<Spring,value>,使用Object调用起来不方便。所以使用配置类对RedisTemplate做一个重新的配置。
在这里插入图片描述

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        //1.redisTemplate要想具备访问数据库的能力,就得创建连接;连接是由连接工厂创建的,所以把连接工厂注入进来
        RedisTemplate<String, Object> template = new RedisTemplate<>();   //1.1 在参数上声明一个连接工厂,上面括号;然后实例化这个bean
        template.setConnectionFactory(factory); //1.2 把工厂设置给template,现在就有了访问数据库的能力

        //2.我们配这个template主要配的是序列化方式
        //因为写的程序是java程序,得到的数据是java类型的数据,最终要把数据存到redis数据库里,所以要指定一种序列化的方式,或者说数据转换的方式
        //2.1 设置key的序列化方式
        template.setKeySerializer(RedisSerializer.string());
        //2.2 设置value的序列化方式
        template.setValueSerializer(RedisSerializer.json());
        /*有一个value比较特殊,就是 hash。这个value本身就是一个hash,hash又说明key、value*/
        //2.3 设置 hash的key的序列化方式
        template.setHashKeySerializer(RedisSerializer.string());
        //2.4 设置 hash的value的序列化方式
        template.setHashKeySerializer(RedisSerializer.json());

        template.afterPropertiesSet();
        return template;
    }
}

4. RedisTests测试

查看第12个库,里面任何数据都没有。
在这里插入图片描述
RedisTests

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class RedisTests {

    @Autowired
    private RedisTemplate redisTemplate;


    /*访问以字符串为值(value)的数据*/
    @Test
    public void testStrings(){
        String redisKey = "test:count";

        redisTemplate.opsForValue().set(redisKey,2);  //设置value为2
        System.out.println(redisTemplate.opsForValue().get(redisKey)); //取数据
        System.out.println(redisTemplate.opsForValue().increment(redisKey)); //数据+1
        System.out.println(redisTemplate.opsForValue().decrement(redisKey)); //数据-1
    }

    /*访问以 hash为 value的数据*/
    @Test
    public void testHashes(){
        String redisKey = "test:user";

        redisTemplate.opsForHash().put(redisKey,"id",17);
        redisTemplate.opsForHash().put(redisKey,"name","YTY");
        System.out.println(redisTemplate.opsForHash().get(redisKey, "id"));
        System.out.println(redisTemplate.opsForHash().get(redisKey, "name"));

    }

	/*访问以 list列表为 value的数据*/
    @Test
    public void testLists(){
        String redisKey = "test:ids";

        redisTemplate.opsForList().leftPush(redisKey, 101); //从左边进
        redisTemplate.opsForList().leftPush(redisKey, 201);
        redisTemplate.opsForList().leftPush(redisKey, 401);
        redisTemplate.opsForList().rightPush(redisKey, 301); //从右边进
        //顺序应为 401 201 101 301

        System.out.println(redisTemplate.opsForList().size(redisKey));           //获取当前列表中一共有多少个数据 —— 4
        System.out.println(redisTemplate.opsForList().index(redisKey,2));  //获取当前列表中下标为2的数据 —— 101
        System.out.println(redisTemplate.opsForList().range(redisKey, 0, 2)); //获取范围 0到2的数据,所以301不会在里面 —— 【401,201,101】
        System.out.println(redisTemplate.opsForList().leftPop(redisKey));    //从左边弹出一条数据 —— 弹奏401
        System.out.println(redisTemplate.opsForList().rightPop(redisKey));   //从右边弹出一条数据 —— 弹走301
        System.out.println(redisTemplate.opsForList().size(redisKey));       //获取当前列表中一共有多少个数据 —— 2

    }
    
    /*访问以 set集合为 value的数据*/
    @Test
    public void testSets(){
        String redisKey = "test:teacher";

        redisTemplate.opsForSet().add(redisKey,"张飞","刘备","关羽","貂蝉","西施");

        System.out.println(redisTemplate.opsForSet().size(redisKey));  //查看集合中数据个数
        System.out.println(redisTemplate.opsForSet().pop(redisKey));   //随机弹出一个数:可用于抽奖啥的
        System.out.println(redisTemplate.opsForSet().members(redisKey)); //查看集合中具体数据是什么
    }
    
    /*访问以 zset有序集合为 value的数据*/
    @Test
    public void testSortedSets(){
        String redisKey = "test:students";

        redisTemplate.opsForZSet().add(redisKey,"孙悟空",10);
        redisTemplate.opsForZSet().add(redisKey,"唐僧",2);
        redisTemplate.opsForZSet().add(redisKey,"猪八戒",7);
        redisTemplate.opsForZSet().add(redisKey,"沙悟净",5);
        redisTemplate.opsForZSet().add(redisKey,"白龙马",4);

        System.out.println(redisTemplate.opsForZSet().zCard(redisKey));                       //统计集合一个多少个数据 —— 5
        System.out.println(redisTemplate.opsForZSet().score(redisKey, "白龙马"));           //查看某一个value值的分数 —— 4
        System.out.println(redisTemplate.opsForZSet().rank(redisKey, "唐僧"));              //查看某一个value的排名(从小到大)——0
        System.out.println(redisTemplate.opsForZSet().reverseRank(redisKey, "孙悟空"));     //查看某一个value的排名(从大到小)——0
        System.out.println(redisTemplate.opsForZSet().range(redisKey, 0, 3));       //取0-3范围内的数据(从小到大)
        System.out.println(redisTemplate.opsForZSet().reverseRange(redisKey, 0, 3));//取0-3范围内的数据(从大到小)
    }
}

4.1 ❤事务

事务:redis也是一个数据库,它也支持事务的。但是它满足事务的机制不满足ACID,因为毕竟是NoSql数据库。
redis的事务管理是比较简单的,机制是:启用事务以后,当我再去执行一个redis命令的时候,它并不会立刻执行这个命令,而是把这个命令放到队列里先存着。
然后你再执行一个命令,它再放到队列里,直到你操作完了,你提交事务的时候,它会把队列中的命令一并发给redis服务器一起执行,是这样一个机制。
所以,这里就隐含了一个问题,使用的时候一定要注意,因为事务之内的命令不会立刻执行,提交时统一批量的执行。
所以说,如果在事务过程中做了一个查询,这个查询不会立刻返回结果;也就是不要在事务中间去做查询,要么提前查,要么事务提交以后再查。这一点和关系型数据库不一样。

在开发的时候,声明式事务更简单,只做一些配置+@Transaction即可,但是它只能精确到一个方法,整个方法范围内逻辑都是事务范围,这个方法之内就没法去查询了。
所以一般用编程式事务,把事务范围缩小。比如中间只有两步需要管理事务,我就把这两步写到相关的代码里,其他地方该咋就咋。

/*演示编程式事务*/
    @Test
    public void testTransactional(){
        Object obj = redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String redisKey = "test:tx";
                operations.multi();//启用事务  下面可做一些相关操作
                operations.opsForSet().add(redisKey,"zhangsan"); //添加数据
                operations.opsForSet().add(redisKey,"lisi");
                operations.opsForSet().add(redisKey,"wangwu");
                //查询 - 事务内是没效果的,这里测试看一下
                System.out.println(operations.opsForSet().members(redisKey));
                return operations.exec();  //提交事务
            }
        });
        System.out.println(obj);
    }
}

在这里插入图片描述

5.结果:

1
在这里插入图片描述
在这里插入图片描述

2
在这里插入图片描述
在这里插入图片描述
3
在这里插入图片描述
在这里插入图片描述
4
在这里插入图片描述
弹出了西施,查看具体数据就没了西施。
在这里插入图片描述
5
在这里插入图片描述
在这里插入图片描述
6
在这里插入图片描述
确实被删了
在这里插入图片描述
十秒后,再次查看 test:users 还在不在:
在这里插入图片描述
不在了。

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐