SpringBoot中的Redis

在 SpringBoot2.x 之后,本来运用的jedis被替换为了lettuce?

jedis : 选用的直连,多个线程操作的话,是不安全的,假如想要避免不安全的,运用 jedis pool 连接 池! 更像 BIO 形式

lettuce : 选用netty,实例能够再多个线程中进行共享,不存在线程不安全的状况!能够削减线程数据 了,更像 NIO 形式

环境建立与测验

1.创立一个SpringBoot项目。选择要导入的依赖。最重要的是导入Redis依赖。

SpringBoot整合Redis

2.编写配置文件。运用WIndows本地的Redis(保证Redis运行)

SpringBoot整合Redis

3.在测验类中进行测验

五大数据类型

  • opsForValue() 操作字符串 相似String
  • opsForList() 操作List 相似List
  • opsForSet() 操作Set 相似Set
  • opsForZSet() 操作ZSet 相似ZSet
  • opsForHash() 操作Hash 相似Hash

特别数据类型

  • opsForGeo()
  • opsForHyperLogLog()
@Test
void contextLoads() {
    //五大数据类型
    //opsForValue() 操作字符串 相似String
    //opsForList() 操作List 相似List
    //opsForSet() 操作Set 相似Set
    //opsForZSet() 操作ZSet 相似ZSet
    //opsForHash() 操作Hash 相似Hash
    //特别数据类型
    //opsForGeo()
    //opsForHyperLogLog()
    //除了根本的操作,咱们常用的办法都能够经过redisTemplate操作。比如事务,和根本的CRUD
    redisTemplate.opsForValue().set("mykey", "kylin");
    System.out.println(redisTemplate.opsForValue().get("mykey"));
}

SpringBoot整合Redis

SpringBoot整合Redis

自定义RedisTemplate

SpringBoot整合Redis

	@Bean
	@ConditionalOnMissingBean(name = "redisTemplate")
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
			throws UnknownHostException {
         // 默许的 RedisTemplate 没有过多的设置,redis 目标都是需要序列化!
		// 两个泛型都是 Object, Object 的类型,咱们后运用需要强制转化 <String, Object>
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}
	@Bean
	@ConditionalOnMissingBean
	// 由于 String 是redis中最常运用的类型,所以说独自提出来了一个bean!
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
			throws UnknownHostException {
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

首要咱们编写一个实体类User

@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
//一切的pojo都要序列化
public class User implements Serializable {
    private String name;
    private int age;
}

SpringBoot整合Redis

在测验类中测验像Redis存储一个User目标

SpringBoot整合Redis

@Test
void test2() {
    //真实的开发一般都是用Json来传递目标
    User user = new User("kylin", 18);
    //String jsonUser = new ObjectMapper().writeValueAsString(user)
    redisTemplate.opsForValue().set("user", user);
    System.out.println(redisTemplate.opsForValue().get("user"));
}

成功存储并获取到~

SpringBoot整合Redis

但是咱们在运用redis-cli连接redis。发现在redis中存储的数据变成了像乱码一样的字符串。

SpringBoot整合Redis

仅仅由于redis默许序列化时会运用jdk序列化器。要想处理这样的问题题咱们就要自定义配置RedisTemplate

1.首要咱们创立一个config包在包下编写一个RedisConfig配置类。以后运用直接仿制就行。

SpringBoot整合Redis

@Configuration
public class RedisConfig {
    // 这是我给咱们写好的一个固定模板,咱们在企业中,拿去就能够直接运用!
    // 自己定义了一个 RedisTemplate
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 咱们为了自己开发便利,一般直接运用 <String, Object>
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        // Json序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // String 的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key选用String的序列化办法
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也选用String的序列化办法
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化办法选用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化办法选用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

2.此外由于RedisTemplate的供给的办法也和操作原生redis又较大的差异。所以编写一个工具类RedisUtil将其供给的API进行进一步的封装更像操作原生redis一样。同理以后运用仿制即可

SpringBoot整合Redis

// 在咱们真实的分发中,或者你们在公司,一般都能够看到一个公司自己封装RedisUtil
@Component
public final class RedisUtil {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    // =============================common============================
    /**
     * 指定缓存失效时刻
     * @param key  键
     * @param time 时刻(秒)
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 依据key 获取过期时刻
     * @param key 键 不能为null
     * @return 时刻(秒) 回来0代表为永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }
    /**
     * 判别key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 删去缓存
     * @param key 能够传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }
    // ============================String=============================
    /**
     * 一般缓存获取
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }
    /**
     * 一般缓存放入
     * @param key   键
     * @param value 值
     * @return true成功 false失利
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 一般缓存放入并设置时刻
     * @param key   键
     * @param value 值
     * @param time  时刻(秒) time要大于0 假如time小于等于0 将设置无限期
     * @return true成功 false 失利
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 递加
     * @param key   键
     * @param delta 要增加几(大于0)
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递加因子有必要大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }
    /**
     * 递减
     * @param key   键
     * @param delta 要削减几(小于0)
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子有必要大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }
    // ================================Map=================================
    /**
     * HashGet
     * @param key  键 不能为null
     * @param item 项 不能为null
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }
    /**
     * 获取hashKey对应的一切键值
     * @param key 键
     * @return 对应的多个键值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }
    /**
     * HashSet
     * @param key 键
     * @param map 对应多个键值
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * HashSet 并设置时刻
     * @param key  键
     * @param map  对应多个键值
     * @param time 时刻(秒)
     * @return true成功 false失利
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 向一张hash表中放入数据,假如不存在将创立
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失利
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 向一张hash表中放入数据,假如不存在将创立
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时刻(秒) 注意:假如已存在的hash表有时刻,这里将会替换原有的时刻
     * @return true 成功 false失利
     */
    public 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) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 删去hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 能够使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }
    /**
     * 判别hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }
    /**
     * hash递加 假如不存在,就会创立一个 并把新增后的值回来
     *
     * @param key  键
     * @param item 项
     * @param by   要增加几(大于0)
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }
    /**
     * hash递减
     *
     * @param key  键
     * @param item 项
     * @param by   要削减记(小于0)
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }
    // ============================set=============================
    /**
     * 依据key获取Set中的一切值
     * @param key 键
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 依据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 能够是多个
     * @return 成功个数
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    /**
     * 将set数据放入缓存
     *
     * @param key    键
     * @param time   时刻(秒)
     * @param values 值 能够是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    /**
     * 获取set缓存的长度
     *
     * @param key 键
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 能够是多个
     * @return 移除的个数
     */
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    // ===============================list=================================
    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开端
     * @param end   结束 0 到 -1代表一切值
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 获取list缓存的长度
     *
     * @param key 键
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    /**
     * 经过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 将list放入缓存
     * @param key   键
     * @param value 值
     * @param time  时刻(秒)
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时刻(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 依据索引修正list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 移除N个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}

3.在测验类中进行测验。运用自定义的RedisTemplate和RedisUtil

SpringBoot整合Redis

SpringBoot整合Redis

在经过redis-cli查看。成功!

SpringBoot整合Redis

源码地址

gitee.com/kylincw/Red…