Springboot——整合Redis

一、核心流程

  1. 引入依赖
  2. 创建RedisConfig配置文件
  3. 使用Redis缓存数据

配置Redis的序列化是为了解决程序中的数据转化成Redis二进制数据后无法直观查看数据信息的问题。

二、代码实战

2.1 引入依赖

spring-boot-starter-data-redis默认会使用lettuce,本次使用的是Jedis,所以依赖中我们要屏蔽掉lettuce而改用jedis。

Springboot会帮我们自动装配Redis,自动生成RedisConnectionFactory、RedisTemplate、StringRedisTemplate等常用的Redis对象。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.7.5</version>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

在spring-data-redis中,RedisConnection通过RedisConnectionFactory创建,Spring为了简化以上操作,做出了简化,并诞生了RedisTemplate

2.2 创建RedisConfig配置文件

因为Redis的数据以二进制的方式存储,与Java数据不相同,所以直接存入Java数据到Redis中会导致你在使用RedisCli查看数据时,是我们无法看懂的二进制序列化数据,为了解决这个问题,我们需要对Redis配置序列化的方式。

package com.example.demo.config.redis;
/**
 * @Author : HuangJiajian
 * @create 2022/10/24 9:07
 */

@Configuration
public class RedisConfig {
    /**
     * @Author HJJ
     * @Date 2022-12-30 15:49
     * @Params
     * @Return
     * @Description 注入CacheManager
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        return RedisCacheManager.builder(factory)
                .cacheDefaults(defaultCacheConfig())
                .transactionAware()
                .build();
    }

    /**
     * @Author HJJ
     * @Date 2022-12-30 15:48
     * @Params
     * @Return
     * @Description 配置通过@Cacheable注解缓存的序列化方式以及过期时间
     */
    private RedisCacheConfiguration defaultCacheConfig() {
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
        serializer.setObjectMapper(mapper);
        return RedisCacheConfiguration.defaultCacheConfig()
                // 20秒过期
                .entryTtl(Duration.ofSeconds(20))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer))
                .disableCachingNullValues();
    }
}

2.3 使用Redis缓存数据

在Controller层中,使用@Cacheable注解来缓存return的数据。

@Cacheable(value, key)中,value是属性名称,key是标识,在RedisCli中应该通过get value::key的形式读取数据,如get User::Jackget User::John

package com.example.demo.controller;

/**
 * @Author : HuangJiajian
 * @create 2022/12/2 10:59
 */
@RestController
@RequestMapping("/cache")
public class TestRedis {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("/str")
    @Cacheable(key = "#str", value = "Str")
    public String cacheStr(String str) {
        System.out.println("缓存str(第二次同参数时,不应该出现这一打印信息):" + str);
        return cache;
    }
    
    @GetMapping("/user")
    @Cacheable(key = "#username", value = "User")
    public AjaxResult cacheUser(String username) {
        UserEntity userEntity = new UserEntity(u, "123456");
        System.out.println("缓存username(第二次同参数时,不应该出现这一打印信息):" + username);
        return new AjaxResult(AjaxResult.CODE.SUCCESS, "success", userEntity);
    }
}

验证缓存

发送发送2次GET请求/cache/str,参数都是?str=value1,结果如下:

第一次请求:

控制台打印出”缓存str(第二次同参数时,不应该出现这一打印信息):value1“

浏览器获取到数据“value1”

RedisCli运行get Str::value1打印出"value1"

第二次请求:

控制台不打印

浏览器获取到数据“value1”

RedisCli运行get Str::value1打印出"value1"

三、拓展知识

3.1 Redis事务

事务处理简单来讲就是“要么是0,要么是1”。常见于电商系统,如商品在用户提交的订单后库存便减少,但若用户取消支付或支付失败,就需要将库存数据回滚。Redis也具有部分事务处理的功能。

Redis的事务处理包含三个部分:watch(监控)…multi(开始)…exec(执行)

@GetMapping("/multi")
public String testMulti(){
    stringRedisTemplate.opsForValue().set("key1", "value1");
    List list = (List) stringRedisTemplate.execute(new SessionCallback<Object>() {
        @Override
        public Object execute(RedisOperations ops) throws DataAccessException {
            ops.watch("key1");
            ops.multi();
            ops.opsForValue().set("key2", "value2");
            // 还未执行事务,所以数据是空的
            System.out.println(ops.opsForValue().get("key2")); // null
            // 情况1:在multi和exec之间打断点,然后使用reids-cli修改key1的值,exec之后Redis会监听到key1已经发生改变,故会回滚事务。
            // 情况2:key1增操作错误,但Redis仅存在队列中,直到exec时才会报错,应避免
            // ops.opsForValue().increment("key1", 1);
            ops.exec();
            return null;
        }
    });
    System.out.println(list);
    return "end";
}

四、问题记录

4.1 @Cacheable注解失效

@Cacheable的原理是SpringAOP,很多@Cacheable失效的原因都是因为RedisConfig的初始化在其使用位置之后,所以无法执行AOP拦截,导致@Cacheable注解失效。这个可以通过使用@Autowired StringRedisTemplate stringRedisTemplate;实现Redis缓存,但这样并不会用上RedisConfig中的配置,所以需要在函数中自己配置序列化方式和过期时间等。

还有一种是@Cacheable方法A(),然后使用方法B()去调用方法A,我知道你想要让B调用A时,返回A在Redis中的缓存数据,但这样也是无法做到的。

参考文献

  1. 10分钟拿下 HashMap
  2. 深入浅出Spring Boot 2.x
  3. RedisTemplate配置的jackson.ObjectMapper里的一个enableDefaultTyping方法过期解决
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot 2.7中,可以通过以下步骤来整合Redis: 1. 添加Redis依赖:在项目的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置Redis连接信息:在application.properties或application.yml文件中配置Redis的连接信息,例如: ```yaml spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= ``` 3. 创建Redis配置类:创建一个Redis配置类,用于配置Redis连接工厂和Redis模板。可以使用以下示例代码: ```java @Configuration public class RedisConfig { @Bean public RedisConnectionFactory redisConnectionFactory() { LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(); connectionFactory.setHostName("127.0.0.1"); connectionFactory.setPort(6379); return connectionFactory; } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } } ``` 4. 使用Redis:在需要使用Redis的地方,可以通过注入RedisTemplate来操作Redis。例如,以下代码演示了如何向Redis中存储和获取数据: ```java @Autowired private RedisTemplate<String, Object> redisTemplate; public void setValue(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object getValue(String key) { return redisTemplate.opsForValue().get(key); } ``` 以上是SpringBoot 2.7整合Redis的基本步骤。你可以根据自己的需求进行进一步的配置和使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值