Redis学习(三)一springboot整合Lettuce

Redis客户端

  • Jedis
  • Lettuce

为什么用Lettuce

1.Jedis在实现上是直连redis server,连接实例可以在多个线程间共享,多线程环境下非线程安全,除非使用连接池,为每个Jedis实例增加物理连接。当连接数量增多时,物理连接成本就较高了。

2.Lettuce基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,且线程安全,满足多线程环境下的并发访问,同时它是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。netty 是一个多线程、事件驱动的 I/O 框架,可以让我们更好的利用系统资源,而不用浪费线程等待网络或磁盘I/O。

整合Lettuce

1.导入依赖

       <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
        <!-- lettuce pool 缓存连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.5.0</version>
        </dependency>
        <!-- jackson json 优化缓存对象序列化 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.6</version>
        </dependency>

2.修改配置application.yml

spring:
  redis:
    host: 192.168.11.125  # IP
    port: 6379  # 端口号
    password: wangcheng123  # 密码
    timeout: 10000
    lettuce:
      pool:
        max-active: 8 # 连接池最大连接数
        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
        min-idle: 0 # 连接池中的最小空闲连接
        max-idle: 8 # 连接池中的最大空闲连接

3.编写缓存配置类CacheConfig

/**
 * @author wang
 */
/**
 * 缓存配置-使用Lettuce客户端,自动注入配置的方式
 */
@Configuration
@EnableCaching //启用缓存
public class CacheConfig extends CachingConfigurerSupport {
    /**
     * 自定义缓存key的生成策略。默认的生成策略是看不懂的(乱码内容)
     * 通过Spring 的依赖注入特性进行自定义的配置注入并且此类是一个配置类可以更多程度的自定义配置
     * @return
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for(Object object : params){
                    sb.append(object.toString());
                }
                return sb.toString();
            }
        };
    }
    /**
     * 缓存配置管理器
     */
    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory factory) {
        //以锁写入的方式创建RedisCacheWriter对象
        RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(factory);
        /*
        设置CacheManager的Value序列化方式为JdkSerializationRedisSerializer,
        但其实RedisCacheConfiguration默认就是使用
        StringRedisSerializer序列化key,
        JdkSerializationRedisSerializer序列化value,
        所以以下注释代码就是默认实现,没必要写,直接注释掉
         */
        // RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(new JdkSerializationRedisSerializer(this.getClass().getClassLoader()));
        // RedisCacheConfiguration redis = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
        //创建默认缓存配置对象
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        RedisCacheManager cacheManager = new RedisCacheManager(writer, config);
        return cacheManager;

    }
    /**
     * 获取缓存操作助手对象
     *
     * @return
     */
    @Bean
    public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory factory){
        //创建Redis缓存操作助手RedisTemplate对象
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        //以下代码为将RedisTemplate的Value序列化方式由JdkSerializationRedisSerializer更换为Jackson2JsonRedisSerializer
        //此种序列化方式结果清晰、容易阅读、存储字节少、速度快,所以推荐更换
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //在使用注解@Bean返回RedisTemplate的时候,同时配置hashKey与hashValue的序列化方式
        //key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        //value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        //hash的value也采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

}

4.编写缓存操作提供类RedisService(用于给开发提供缓存操作)

/**
 * @author wang
 */
@Service
public class RedisService {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 写入缓存
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(final String key, Object value) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 写入缓存设置时效时间
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(final String key, Object value, Long expireTime) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 批量删除对应的value
     *
     * @param keys
     */
    public void remove(final String... keys) {
        for (String key : keys) {
            remove(key);
        }
    }

    /**
     * 批量删除key
     * @param pattern
     */
    public void removePattern(final String pattern) {
        Set<Serializable> keys = redisTemplate.keys(pattern);
        if (keys.size() > 0) {
            redisTemplate.delete(keys);
        }
    }

    /**
     * 删除对应的value
     *
     * @param key
     */
    public void remove(final String key) {
        if (exists(key)) {
            redisTemplate.delete(key);
        }
    }

    /**
     * 判断缓存中是否有对应的value
     *
     * @param key
     * @return
     */
    public boolean exists(final String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 读取缓存
     *
     * @param key
     * @return
     */
    public Object get(final String key) {
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        return operations.get(key);
    }

    /**
     * 哈希 添加
     *
     * @param key
     * @param hashKey
     * @param value
     */
    public void hmSet(String key, Object hashKey, Object value) {
        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
        hash.put(key, hashKey, value);
    }

    /**
     * 哈希获取数据
     *
     * @param key
     * @param hashKey
     * @return
     */
    public Object hmGet(String key, Object hashKey) {
        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
        return hash.get(key, hashKey);
    }

    /**
     * 列表添加
     *
     * @param k
     * @param v
     */
    public void lPush(String k, Object v) {
        ListOperations<String, Object> list = redisTemplate.opsForList();
        list.rightPush(k, v);
    }

    /**
     * 列表获取
     *
     * @param k
     * @param l
     * @param l1
     * @return
     */
    public List<Object> lRange(String k, long l, long l1) {
        ListOperations<String, Object> list = redisTemplate.opsForList();
        return list.range(k, l, l1);
    }

    /**
     * 集合添加
     *
     * @param key
     * @param value
     */
    public void add(String key, Object value) {
        SetOperations<String, Object> set = redisTemplate.opsForSet();
        set.add(key, value);
    }

    /**
     * 集合获取
     *
     * @param key
     * @return
     */
    public Set<Object> setMembers(String key) {
        SetOperations<String, Object> set = redisTemplate.opsForSet();
        return set.members(key);
    }

    /**
     * 有序集合添加
     *
     * @param key
     * @param value
     * @param scoure
     */
    public void zAdd(String key, Object value, double scoure) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        zset.add(key, value, scoure);
    }

    /**
     * 有序集合获取
     *
     * @param key
     * @param scoure
     * @param scoure1
     * @return
     */
    public Set<Object> rangeByScore(String key, double scoure, double scoure1) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        return zset.rangeByScore(key, scoure, scoure1);
    }
}

5.编写测试控制类 RedisTestController

/**
 * @author wang
 */
@RestController
public class RedisTestController {

    @Autowired
    private RedisService redisService;

    /**
     * 设置Redis数据
     *
     * @param key
     * @param value
     * @return
     */
    @PostMapping("/set")
    public Object setRedis(String key, String value) {
        redisService.set(key, value);
        return "设置成功";
    }

    /**
     * 根据key删除Redis数据
     *
     * @param key
     * @return
     */
    @GetMapping("/del")
    public Object delRedis(String key) {
        redisService.remove(key);
        return "删除成功";
    }

    /**
     * 根据key获取Redis数据
     *
     * @param key
     * @return
     */
    @GetMapping("/get")
    public Object getRedis(String key) {
        Object value = redisService.get(key);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("value", value);
        return map;
    }


}

测试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

操作其他类型

下列的就是Redis其它类型所对应的操作方式

  • opsForValue: 对应 String(字符串)
  • opsForZSet: 对应 ZSet(有序集合)
  • opsForHash: 对应 Hash(哈希)
  • opsForList: 对应 List(列表)
  • opsForSet: 对应 Set(集合)
  • opsForGeo: 对应 GEO(地理位置)

事务(Transaction)

使用

RedisTemplate通过execute方法提供事务功能,但不保证所有的事务操作在同一个连接中进行。

//执行一次事务操作
//调用RedisTemplte的execute(SessionBack<T> session)方法
//需要实现SessionBack中的execute(RedisOperations<K,V> operations)方法
//使用lamda表达式
List<Object> txResults = redisTemplate.execute((RedisOperations<K, V> operations)->{
    //开启事务
    operations.multi();
    //添加操作
    operations.opsForSet().add("key", "value1");
    //这个将会返回事务操作的所有结果
    return operations.exec();
  }
});
//打印结果
System.out.println("Number of items added to set: " + txResults.get(0));

结束!!!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Spring Boot整合Lettuce,你可以按照以下步骤进行操作: 1. 首先,在你的Spring Boot项目的pom.xml文件中添加Lettuce的依赖项。例如,你可以添加以下代码到<dependencies>标签中: ```xml <dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> <version>VERSION</version> </dependency> ``` 确保将`VERSION`替换为你希望使用的Lettuce版本。 2. 接下来,你需要配置Lettuce连接到Redis服务器。在Spring Boot中,你可以在`application.properties`或`application.yml`文件中进行配置。例如,如果你使用`application.properties`文件,可以添加以下配置: ```properties spring.redis.host=your_redis_host spring.redis.port=your_redis_port spring.redis.password=your_redis_password (如果有密码的话) ``` 确保将`your_redis_host`、`your_redis_port`和`your_redis_password`替换为你的Redis服务器的实际信息。 3. 在你的Spring Boot应用程序中,你可以使用`LettuceConnectionFactory`来创建Redis连接工厂,并将其注入到需要使用Redis的组件中。例如,你可以创建一个配置类来完成这个任务,如下所示: ```java @Configuration public class RedisConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.password}") private String password; @Bean public LettuceConnectionFactory lettuceConnectionFactory() { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(host, port); config.setPassword(RedisPassword.of(password)); return new LettuceConnectionFactory(config); } @Bean public RedisTemplate<String, Object> redisTemplate() { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(lettuceConnectionFactory()); return template; } } ``` 在上面的配置中,我们使用`RedisStandaloneConfiguration`来配置Redis连接,并使用`LettuceConnectionFactory`来创建连接工厂。然后,我们使用`RedisTemplate`来操作Redis。 4. 现在,你可以在你的应用程序中注入`RedisTemplate`,并使用它来进行Redis操作。例如,你可以在一个服务类中注入`RedisTemplate`,并使用它来执行一些基本的Redis操作,如下所示: ```java @Service public class RedisService { private final RedisTemplate<String, Object> redisTemplate; public RedisService(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } public void setValue(String key, String value) { redisTemplate.opsForValue().set(key, value); } public String getValue(String key) { return (String) redisTemplate.opsForValue().get(key); } } ``` 在上面的示例中,我们使用`opsForValue()`方法来获取一个用于操作字符串的操作对象,并使用它来设置和获取值。 这就是整合Spring Boot和Lettuce的基本步骤。你可以根据自己的需求进一步扩展和使用Lettuce的其他功能。希望对你有所帮助!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值