03. SpringBoot 整合 Redis

Jedis

Jedis 是 Redis 官方推荐的 Java 连接工具。

导入依赖

  </dependencies>
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>3.2.0</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
    </dependency>
  </dependencies>

测试连接

package com.zk.jedis;

import redis.clients.jedis.Jedis;

public class TestJedis {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        System.out.println(jedis.ping());
    }
}

输出:

PONG

Jedis 实现事务

执行成功:

package com.zk.jedis;

import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class TestJedis {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "xiaoming");
        jsonObject.put("num", "24");
        String result = jsonObject.toJSONString();

        // 开启事务
        Transaction multi = jedis.multi();

        try{
            multi.set("user1", result);
            multi.set("user2", result);
            // 执行事务
            multi.exec();
        }catch (Exception e){
            // 失败就放弃事务
            multi.discard();
        }finally {
            // 关闭事务
            multi.close();
        }

        System.out.println(jedis.get("user1"));
        System.out.println(jedis.get("user2"));
    }
}

输出:

{"num":"24","name":"xiaoming"}
{"num":"24","name":"xiaoming"}

执行失败:

package com.zk.jedis;

import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class TestJedis {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);

        jedis.flushDB();

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "xiaoming");
        jsonObject.put("num", "24");
        String result = jsonObject.toJSONString();

        // 开启事务
        Transaction multi = jedis.multi();
//        jedis.watch(result);

        try{
            multi.set("user1", result);
            multi.set("user2", result);

            int i = 1 / 0; // 代码执行异常,事务会执行失败

            // 执行事务
            multi.exec();
        }catch (Exception e){
            // 失败就放弃事务
            multi.discard();
        }finally {
            // 关闭事务
            multi.close();
        }

        System.out.println(jedis.get("user1"));
        System.out.println(jedis.get("user2"));
    }
}

输出:

null
null

SpringBoot 整合 Redis

SpringBoot 操作数据:Spring Data jpa jdbc redis。
Spring Data 也是和 SpringBoot 齐名的项目。

在 SpringBoot 2.x 之后,Jedis 被换成了 Lettuce。

Jedis:底层采用直连的方式,如果多个线程操作,不安全。要避免不安全,就要使用 Jedis Pool 连接池!更像 BIO 模式!

Lettuce:采用 netty,实例可以在多个线程中共享,不存在不安全的情况!可以减少线程数,性能高,更像 NIO 模式!

SpringBoot 所有的配置类,都有一个自动配置类,RedisAutoConfiguration;
自动配置类都会绑定一个 properties 文件,RedisProperties。

RedisTemplate

  • 默认的 RedisTemplate 没有过多的设置,redis 保存的对象都是需要序列化的!
  • RedisTemplate<Object, Object> 的两个参数都是 Object 类型的,我们使用需要强制转换 RedisTemplate<String, Object>(我们期望使用 String 类型的 key);
  • @ConditionalOnMissingBean:判断当前需要注入 Spring 容器的 bean 的实现类是否已经含有,有的话不注入,没有就注入。(可以使用默认的 RedisTemplate,也可以自定义 RedisTemplate)

SpringBoot 整合 Redis 测试

  1. 导入依赖
	<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
  1. 配置连接
# SpringBoot 所有的配置类,都有一个自动配置类,RedisAutoConfiguration;
# 自动配置类都会绑定一个 properties 文件,RedisProperties。

# 配置redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
  1. 测试

RedisTemplate 序列化

默认的 RedisTemplate 没有过多的设置,redis 保存的对象都是需要序列化的!

	@Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        // 我们为了自己使用方便,一般直接使用<String, Object>
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 配置连接工厂
        redisTemplate.setConnectionFactory(connectionFactory);
        
        // Json 的序列化
        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        //指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        
        // String 的序列化
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        
        
        // key 采用 String 的序列化方式
        redisTemplate.setKeySerializer(stringSerializer);
        // Hash 的 key 也采用 String 的序列化方式
        redisTemplate.setHashKeySerializer(stringSerializer);
        // value 采用 jackson 的序列化方式
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // Hash 的 value 也采用 jackson 的序列化方式
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        
        RedisUtils.setRedisTemplate(redisTemplate);
        
        return redisTemplate;
    }

RedisUtils

package com.zte.rdcloud.wbs.util;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author 10307952
 * @date 2023/1/31 下午5:05
 */
@Slf4j
@Component
public class RedisUtils {

    @Setter
    private static RedisTemplate<String, Object> redisTemplate;

    /**
     * 为键值设置过期时间,单位秒
     *
     * @param key  键
     * @param time 时间(秒)
     * @return true:成功;false:失败
     */
    public static boolean expire(String key, long time) {
        try {
            if (time > 0){
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        }catch (Exception e){
            log.error(e.getMessage());
            return false;
        }
    }

    //------------------------------String-----------------------------

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public static boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 普通缓存放入并设置过期时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public static boolean set(String key, Object value, long time) {
        try {
            if(time > 0){
                redisTemplate.opsForValue().set(key, value, time);
            }else{
                set(key, value);
            }
            return true;
        }catch (Exception e){
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    public static void del(String... key) {
        try {
            if(null != key && key.length > 0){
                if(key.length == 1){
                    redisTemplate.delete(key[0]);
                }else{
                    redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
                }
            }
        }catch(Exception e){
            log.error(e.getMessage());
        }
    }

    /**
     * 普通缓存获取
     *
     * @param key
     * @return
     */
    public static Object get(String key){
        try {
            return null == key ? null : redisTemplate.opsForValue().get(key);
        }catch(Exception e){
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 获取旧值,缓存新值
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public static Object getAndSet(String key, Object value) {
        try {
            return redisTemplate.opsForValue().getAndSet(key, value);
        } catch (Exception e) {
            return null;
        }
    }

    //------------------------------Hash-----------------------------

    /**
     * 向一张hash表中放入数据,如果不存在将创建,存在则覆盖
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public static boolean hSet(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        }catch (Exception e){
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建,存在则覆盖,并设置过期时间
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
  /*  public static boolean hSet(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if(time > 0){
                expire(key, time);
            }
            return true;
        }catch (Exception e){
            log.error(e.getMessage());
            return false;
        }
    }*/

    /**
     * 向一张hash表中放入数据,如果不存在将创建,存在则只设置失效时间(不会设置新值)
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
   /* public static boolean hSetIfAbsent(String key, String item, Object value, long time) {
        try {
            Boolean result = redisTemplate.opsForHash().putIfAbsent(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return result;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }*/

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    /*public static boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }*/

    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以是多个 不能为null
     */
    public static void hDel(String key, Object... item) {
        try {
            redisTemplate.opsForHash().delete(key, item);
        }catch(Exception e){
            log.error("redis failed hdel", e);
        }
    }

    /**
     * 获取指定键对应的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return 值
     */
    public static Object hGet(String key, String item) {
        try {
            return redisTemplate.opsForHash().get(key, item);
        }catch (Exception e){
            log.error(e.getMessage());
            return null;
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值