SpringBoot集成Redis使用Lettuce

- 日理万妓 2024-03-26 13:27 211阅读 0赞

Redis是最常用的KV数据库,Spring 通过模板方式(RedisTemplate)提供了对Redis的数据查询和操作功能。本文主要介绍基于RedisTemplate + lettuce方式对Redis进行查询和操作的案例。

一、Redis基础数据类型

首先对redis来说,所有的key(键)都是字符串。我们在谈基础数据结构时,讨论的是存储值的数据类型,主要包括常见的5种数据类型,分别是:String、List、Set、Zset、Hash。


































结构类型

结构存储的值

结构的读写能力

String字符串

可以是字符串、整数或浮点数

对整个字符串或字符串的一部分进行操作;对整数或浮点数进行自增或自减操作;

List列表

一个链表,链表上的每个节点都包含一个字符串

对链表的两端进行push和pop操作,读取单个或多个元素;根据值查找或删除元素;

Set集合

包含字符串的无序集合

字符串的集合,包含基础的方法有看是否存在添加、获取、删除;还包含计算交集、并集、差集等

Hash散列

包含键值对的无序散列表

包含方法有添加、获取、删除单个元素

Zset有序集合

和散列一样,用于存储键值对

字符串成员与浮点数分数之间的有序映射;元素的排列顺序由分数的大小决定;包含方法有添加、获取、删除单个元素以及根据分值范围或成员来获取元素

二、 Redis常用连接池

Jedis:是Redis的Java实现客户端,提供了比较全面的Redis命令的支持。

Redisson:实现了分布式和可扩展的Java数据结构。

Lettuce:高级Redis客户端,用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。

三、SpringBoot集成Redis案例

1、yml配置常量:

redis:
# 地址
host: 192.168.1.66
# 端口,默认为6379
port: 6379
# 数据库索引
database: 0
# 密码(如没有密码请注释掉)
password: 123456
# 连接超时时间
timeout: 3000
# 是否开启ssl
ssl: false
lettuce:
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接

2、pom.xml引入依赖:


org.springframework.boot
spring-boot-starter-data-redis
2.4.0



org.apache.commons
commons-pool2
2.8.0

3、RedisConfig配置类:

  1. package com.cn.common.conf;
  2. import com.alibaba.fastjson.parser.ParserConfig;
  3. import com.alibaba.fastjson.support.config.FastJsonConfig;
  4. import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
  5. import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
  6. import org.springframework.beans.factory.annotation.Value;
  7. import org.springframework.cache.annotation.EnableCaching;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.Configuration;
  10. import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
  11. import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
  12. import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
  13. import org.springframework.data.redis.core.RedisTemplate;
  14. import org.springframework.data.redis.serializer.RedisSerializer;
  15. import org.springframework.data.redis.serializer.StringRedisSerializer;
  16. import java.nio.charset.StandardCharsets;
  17. import java.time.Duration;
  18. /**
  19. * redis配置类
  20. *
  21. * @author zq
  22. */
  23. @Configuration
  24. @EnableCaching
  25. public class RedisConfig {
  26. // 倘若 spring.redis.host 不存在,则会默认为127.0.0.1.
  27. @Value("${spring.redis.host:#{'127.0.0.1'}}")
  28. private String hostName;
  29. @Value("${spring.redis.port:#{6379}}")
  30. private int port;
  31. @Value("${spring.redis.password:#{123456}}")
  32. private String password;
  33. @Value("${spring.redis.timeout:#{3000}}")
  34. private int timeout;
  35. @Value("${spring.redis.lettuce.pool.max-idle:#{16}}")
  36. private int maxIdle;
  37. @Value("${spring.redis.lettuce.pool.min-idle:#{1}}")
  38. private int minIdle;
  39. @Value("${spring.redis.lettuce.pool.max-wait:#{16}}")
  40. private long maxWaitMillis;
  41. @Value("${spring.redis.lettuce.pool.max-active:#{16}}")
  42. private int maxActive;
  43. @Value("${spring.redis.database:#{0}}")
  44. private int databaseId;
  45. @Bean
  46. public LettuceConnectionFactory lettuceConnectionFactory() {
  47. RedisConfiguration redisConfiguration = new RedisStandaloneConfiguration(
  48. hostName, port
  49. );
  50. // 设置选用的数据库号码
  51. ((RedisStandaloneConfiguration) redisConfiguration).setDatabase(databaseId);
  52. // 设置 redis 数据库密码
  53. ((RedisStandaloneConfiguration) redisConfiguration).setPassword(password);
  54. // 连接池配置
  55. GenericObjectPoolConfig<Object> poolConfig = new GenericObjectPoolConfig<>();
  56. poolConfig.setMaxIdle(maxIdle);
  57. poolConfig.setMinIdle(minIdle);
  58. poolConfig.setMaxTotal(maxActive);
  59. poolConfig.setMaxWaitMillis(maxWaitMillis);
  60. LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder
  61. = LettucePoolingClientConfiguration.builder()
  62. .commandTimeout(Duration.ofMillis(timeout));
  63. LettucePoolingClientConfiguration lettucePoolingClientConfiguration = builder.build();
  64. builder.poolConfig(poolConfig);
  65. // 根据配置和客户端配置创建连接
  66. LettuceConnectionFactory factory = new LettuceConnectionFactory(redisConfiguration, lettucePoolingClientConfiguration);
  67. return factory;
  68. }
  69. /**
  70. * springboot2.x 使用LettuceConnectionFactory 代替 RedisConnectionFactory
  71. * application.yml配置基本信息后,springboot2.x RedisAutoConfiguration能够自动装配
  72. * LettuceConnectionFactory 和 RedisConnectionFactory 及其 RedisTemplate
  73. *
  74. * @param
  75. * @return
  76. */
  77. @Bean(name = "redisTemplate")
  78. public RedisTemplate<String, Object> redisTemplate(
  79. LettuceConnectionFactory lettuceConnectionFactory
  80. ) {
  81. RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
  82. redisTemplate.setConnectionFactory(lettuceConnectionFactory);
  83. // 使用 FastJsonRedisSerializer 来序列化和反序列化redis 的 value的值
  84. FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
  85. ParserConfig.getGlobalInstance().addAccept("com.muzz");
  86. FastJsonConfig fastJsonConfig = new FastJsonConfig();
  87. fastJsonConfig.setCharset(StandardCharsets.UTF_8);
  88. serializer.setFastJsonConfig(fastJsonConfig);
  89. // key 的 String 序列化采用 StringRedisSerializer
  90. StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
  91. redisTemplate.setKeySerializer(stringRedisSerializer);
  92. redisTemplate.setHashKeySerializer(stringRedisSerializer);
  93. // value 的值序列化采用 fastJsonRedisSerializer
  94. redisTemplate.setValueSerializer(serializer);
  95. redisTemplate.setHashValueSerializer(serializer);
  96. redisTemplate.afterPropertiesSet();
  97. System.out.println(redisTemplate.getDefaultSerializer());
  98. return redisTemplate;
  99. }
  100. @Bean
  101. public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
  102. // 使用 FastJsonRedisSerializer 来序列化和反序列化redis 的 value的值
  103. FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
  104. ParserConfig.getGlobalInstance().addAccept("com.muzz");
  105. FastJsonConfig fastJsonConfig = new FastJsonConfig();
  106. fastJsonConfig.setCharset(StandardCharsets.UTF_8);
  107. serializer.setFastJsonConfig(fastJsonConfig);
  108. return serializer;
  109. }
  110. }

4、 RedisUtil工具类:

  1. package com.cn.util;
  2. import lombok.RequiredArgsConstructor;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.data.redis.core.RedisTemplate;
  5. import org.springframework.data.redis.core.StringRedisTemplate;
  6. import org.springframework.data.redis.serializer.RedisSerializer;
  7. import org.springframework.data.redis.serializer.StringRedisSerializer;
  8. import org.springframework.stereotype.Component;
  9. import org.springframework.util.CollectionUtils;
  10. import java.util.List;
  11. import java.util.Map;
  12. import java.util.Set;
  13. import java.util.concurrent.TimeUnit;
  14. /**
  15. * @ Description: 基于spring和redis的redisTemplate工具类
  16. * 针对所有的hash 都是以h开头的方法
  17. * 针对所有的Set 都是以s开头的方法 不含通用方法
  18. * 针对所有的List 都是以l开头的方法
  19. * @ Modified By:
  20. */
  21. @Component
  22. @RequiredArgsConstructor
  23. public class RedisUtils {
  24. private RedisTemplate redisTemplate;
  25. private final StringRedisTemplate stringRedisTemplate;
  26. @Autowired(required = false)
  27. public void setRedisTemplate(RedisTemplate redisTemplate) {
  28. RedisSerializer stringSerializer = new StringRedisSerializer();
  29. redisTemplate.setKeySerializer(stringSerializer);
  30. redisTemplate.setHashKeySerializer(stringSerializer);
  31. this.redisTemplate = redisTemplate;
  32. }
  33. /**
  34. * 获取key
  35. * @param patten
  36. * @return
  37. */
  38. public Set keys(String patten){
  39. return stringRedisTemplate.keys(patten);
  40. }
  41. /**
  42. * 指定缓存失效时间
  43. *
  44. * @param key 键
  45. * @param time 时间(秒)
  46. *
  47. */
  48. public boolean expire(String key, long time) {
  49. try {
  50. if (time > 0) {
  51. redisTemplate.expire(key, time, TimeUnit.SECONDS);
  52. }
  53. return true;
  54. } catch (Exception e) {
  55. e.printStackTrace();
  56. return false;
  57. }
  58. }
  59. /**
  60. * 根据key 获取过期时间
  61. *
  62. * @param key 键 不能为null
  63. * @return 时间(秒) 返回0代表为永久有效
  64. */
  65. public long getExpire(String key) {
  66. return redisTemplate.getExpire(key, TimeUnit.SECONDS);
  67. }
  68. /**
  69. * 判断key是否存在
  70. *
  71. * @param key 键
  72. * @return true 存在 false不存在
  73. */
  74. public boolean hasKey(String key) {
  75. try {
  76. return redisTemplate.hasKey(key);
  77. } catch (Exception e) {
  78. e.printStackTrace();
  79. return false;
  80. }
  81. }
  82. /**
  83. * 删除缓存
  84. *
  85. * @param key 可以传一个值 或多个
  86. */
  87. @SuppressWarnings("unchecked")
  88. public void del(String... key) {
  89. if (key != null && key.length > 0) {
  90. if (key.length == 1) {
  91. redisTemplate.delete(key[0]);
  92. } else {
  93. redisTemplate.delete(CollectionUtils.arrayToList(key));
  94. }
  95. }
  96. }
  97. //============================String=============================
  98. /**
  99. * 普通缓存获取
  100. *
  101. * @param key 键
  102. * @return 值
  103. */
  104. public Object get(String key) {
  105. return key == null ? null : redisTemplate.opsForValue().get(key);
  106. }
  107. /**
  108. * 普通缓存放入
  109. *
  110. * @param key 键
  111. * @param value 值
  112. * @return true成功 false失败
  113. */
  114. public boolean set(String key, Object value) {
  115. try {
  116. redisTemplate.opsForValue().set(key, value);
  117. return true;
  118. } catch (Exception e) {
  119. e.printStackTrace();
  120. return false;
  121. }
  122. }
  123. /**
  124. * 普通缓存放入并设置时间
  125. *
  126. * @param key 键
  127. * @param value 值
  128. * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
  129. * @return true成功 false 失败
  130. */
  131. public boolean set(String key, Object value, long time) {
  132. try {
  133. if (time > 0) {
  134. redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
  135. } else {
  136. set(key, value);
  137. }
  138. return true;
  139. } catch (Exception e) {
  140. e.printStackTrace();
  141. return false;
  142. }
  143. }
  144. /**
  145. * 递增
  146. *
  147. * @param key 键
  148. * @param delta 要增加几(大于0)
  149. * @return
  150. */
  151. public long incr(String key, long delta) {
  152. if (delta < 0) {
  153. throw new RuntimeException("递增因子必须大于0");
  154. }
  155. return redisTemplate.opsForValue().increment(key, delta);
  156. }
  157. /**
  158. * 递减
  159. *
  160. * @param key 键
  161. * @param delta 要减少几(小于0)
  162. * @return
  163. */
  164. public long decr(String key, long delta) {
  165. if (delta < 0) {
  166. throw new RuntimeException("递减因子必须大于0");
  167. }
  168. return redisTemplate.opsForValue().increment(key, -delta);
  169. }
  170. //================================Map=================================
  171. /**
  172. * HashGet
  173. *
  174. * @param key 键 不能为null
  175. * @param item 项 不能为null
  176. * @return 值
  177. */
  178. public Object hget(String key, String item) {
  179. return redisTemplate.opsForHash().get(key, item);
  180. }
  181. /**
  182. * 获取hashKey对应的所有键值
  183. *
  184. * @param key 键
  185. * @return 对应的多个键值
  186. */
  187. public Map<Object, Object> hmget(String key) {
  188. return redisTemplate.opsForHash().entries(key);
  189. }
  190. /**
  191. * HashSet
  192. *
  193. * @param key 键
  194. * @param map 对应多个键值
  195. * @return true 成功 false 失败
  196. */
  197. public boolean hmset(String key, Map<String, Object> map) {
  198. try {
  199. redisTemplate.opsForHash().putAll(key, map);
  200. return true;
  201. } catch (Exception e) {
  202. e.printStackTrace();
  203. return false;
  204. }
  205. }
  206. /**
  207. * HashSet 并设置时间
  208. *
  209. * @param key 键
  210. * @param map 对应多个键值
  211. * @param time 时间(秒)
  212. * @return true成功 false失败
  213. */
  214. public boolean hmset(String key, Map<String, Object> map, long time) {
  215. try {
  216. redisTemplate.opsForHash().putAll(key, map);
  217. if (time > 0) {
  218. expire(key, time);
  219. }
  220. return true;
  221. } catch (Exception e) {
  222. e.printStackTrace();
  223. return false;
  224. }
  225. }
  226. /**
  227. * 向一张hash表中放入数据,如果不存在将创建
  228. *
  229. * @param key 键
  230. * @param item 项
  231. * @param value 值
  232. * @return true 成功 false失败
  233. */
  234. public boolean hset(String key, String item, Object value) {
  235. try {
  236. redisTemplate.opsForHash().put(key, item, value);
  237. return true;
  238. } catch (Exception e) {
  239. e.printStackTrace();
  240. return false;
  241. }
  242. }
  243. /**
  244. * 向一张hash表中放入数据,如果不存在将创建
  245. *
  246. * @param key 键
  247. * @param item 项
  248. * @param value 值
  249. * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
  250. * @return true 成功 false失败
  251. */
  252. public boolean hset(String key, String item, Object value, long time) {
  253. try {
  254. redisTemplate.opsForHash().put(key, item, value);
  255. if (time > 0) {
  256. expire(key, time);
  257. }
  258. return true;
  259. } catch (Exception e) {
  260. e.printStackTrace();
  261. return false;
  262. }
  263. }
  264. /**
  265. * 删除hash表中的值
  266. *
  267. * @param key 键 不能为null
  268. * @param item 项 可以使多个 不能为null
  269. */
  270. public void hdel(String key, Object... item) {
  271. redisTemplate.opsForHash().delete(key, item);
  272. }
  273. /**
  274. * 判断hash表中是否有该项的值
  275. *
  276. * @param key 键 不能为null
  277. * @param item 项 不能为null
  278. * @return true 存在 false不存在
  279. */
  280. public boolean hHasKey(String key, String item) {
  281. return redisTemplate.opsForHash().hasKey(key, item);
  282. }
  283. /**
  284. * hash递增 如果不存在,就会创建一个 并把新增后的值返回
  285. *
  286. * @param key 键
  287. * @param item 项
  288. * @param by 要增加几(大于0)
  289. * @return
  290. */
  291. public double hincr(String key, String item, double by) {
  292. return redisTemplate.opsForHash().increment(key, item, by);
  293. }
  294. /**
  295. * hash递减
  296. *
  297. * @param key 键
  298. * @param item 项
  299. * @param by 要减少记(小于0)
  300. * @return
  301. */
  302. public double hdecr(String key, String item, double by) {
  303. return redisTemplate.opsForHash().increment(key, item, -by);
  304. }
  305. //============================set=============================
  306. /**
  307. * 根据key获取Set中的所有值
  308. *
  309. * @param key 键
  310. * @return
  311. */
  312. public Set<Object> sGet(String key) {
  313. try {
  314. return redisTemplate.opsForSet().members(key);
  315. } catch (Exception e) {
  316. e.printStackTrace();
  317. return null;
  318. }
  319. }
  320. /**
  321. * 根据value从一个set中查询,是否存在
  322. *
  323. * @param key 键
  324. * @param value 值
  325. * @return true 存在 false不存在
  326. */
  327. public boolean sHasKey(String key, Object value) {
  328. try {
  329. return redisTemplate.opsForSet().isMember(key, value);
  330. } catch (Exception e) {
  331. e.printStackTrace();
  332. return false;
  333. }
  334. }
  335. /**
  336. * 将数据放入set缓存
  337. *
  338. * @param key 键
  339. * @param values 值 可以是多个
  340. * @return 成功个数
  341. */
  342. public long sSet(String key, Object... values) {
  343. try {
  344. return redisTemplate.opsForSet().add(key, values);
  345. } catch (Exception e) {
  346. e.printStackTrace();
  347. return 0;
  348. }
  349. }
  350. /**
  351. * 将set数据放入缓存
  352. *
  353. * @param key 键
  354. * @param time 时间(秒)
  355. * @param values 值 可以是多个
  356. * @return 成功个数
  357. */
  358. public long sSetAndTime(String key, long time, Object... values) {
  359. try {
  360. Long count = redisTemplate.opsForSet().add(key, values);
  361. if (time > 0) expire(key, time);
  362. return count;
  363. } catch (Exception e) {
  364. e.printStackTrace();
  365. return 0;
  366. }
  367. }
  368. /**
  369. * 获取set缓存的长度
  370. *
  371. * @param key 键
  372. * @return
  373. */
  374. public long sGetSetSize(String key) {
  375. try {
  376. return redisTemplate.opsForSet().size(key);
  377. } catch (Exception e) {
  378. e.printStackTrace();
  379. return 0;
  380. }
  381. }
  382. /**
  383. * 移除值为value的
  384. *
  385. * @param key 键
  386. * @param values 值 可以是多个
  387. * @return 移除的个数
  388. */
  389. public long setRemove(String key, Object... values) {
  390. try {
  391. Long count = redisTemplate.opsForSet().remove(key, values);
  392. return count;
  393. } catch (Exception e) {
  394. e.printStackTrace();
  395. return 0;
  396. }
  397. }
  398. //===============================list=================================
  399. /**
  400. * 获取list缓存的内容
  401. *
  402. * @param key 键
  403. * @param start 开始
  404. * @param end 结束 0 到 -1代表所有值
  405. * @return
  406. */
  407. public List<Object> lGet(String key, long start, long end) {
  408. try {
  409. return redisTemplate.opsForList().range(key, start, end);
  410. } catch (Exception e) {
  411. e.printStackTrace();
  412. return null;
  413. }
  414. }
  415. /**
  416. * 获取list缓存的长度
  417. *
  418. * @param key 键
  419. * @return
  420. */
  421. public long lGetListSize(String key) {
  422. try {
  423. return redisTemplate.opsForList().size(key);
  424. } catch (Exception e) {
  425. e.printStackTrace();
  426. return 0;
  427. }
  428. }
  429. /**
  430. * 通过索引 获取list中的值
  431. *
  432. * @param key 键
  433. * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
  434. * @return
  435. */
  436. public Object lGetIndex(String key, long index) {
  437. try {
  438. return redisTemplate.opsForList().index(key, index);
  439. } catch (Exception e) {
  440. e.printStackTrace();
  441. return null;
  442. }
  443. }
  444. /**
  445. * 将list放入缓存
  446. *
  447. * @param key 键
  448. * @param value 值
  449. * @return
  450. */
  451. public boolean lSet(String key, Object value) {
  452. try {
  453. redisTemplate.opsForList().rightPush(key, value);
  454. return true;
  455. } catch (Exception e) {
  456. e.printStackTrace();
  457. return false;
  458. }
  459. }
  460. /**
  461. * 将list放入缓存
  462. *
  463. * @param key 键
  464. * @param value 值
  465. * @param time 时间(秒)
  466. * @return
  467. */
  468. public boolean lSet(String key, Object value, long time) {
  469. try {
  470. redisTemplate.opsForList().rightPush(key, value);
  471. if (time > 0) expire(key, time);
  472. return true;
  473. } catch (Exception e) {
  474. e.printStackTrace();
  475. return false;
  476. }
  477. }
  478. /**
  479. * 将list放入缓存
  480. *
  481. * @param key 键
  482. * @param value 值
  483. * @return
  484. */
  485. public boolean lSet(String key, List<Object> value) {
  486. try {
  487. redisTemplate.opsForList().rightPushAll(key, value);
  488. return true;
  489. } catch (Exception e) {
  490. e.printStackTrace();
  491. return false;
  492. }
  493. }
  494. /**
  495. * 将list放入缓存
  496. *
  497. * @param key 键
  498. * @param value 值
  499. * @param time 时间(秒)
  500. * @return
  501. */
  502. public boolean lSet(String key, List<Object> value, long time) {
  503. try {
  504. redisTemplate.opsForList().rightPushAll(key, value);
  505. if (time > 0) expire(key, time);
  506. return true;
  507. } catch (Exception e) {
  508. e.printStackTrace();
  509. return false;
  510. }
  511. }
  512. /**
  513. * 根据索引修改list中的某条数据
  514. *
  515. * @param key 键
  516. * @param index 索引
  517. * @param value 值
  518. * @return
  519. */
  520. public boolean lUpdateIndex(String key, long index, Object value) {
  521. try {
  522. redisTemplate.opsForList().set(key, index, value);
  523. return true;
  524. } catch (Exception e) {
  525. e.printStackTrace();
  526. return false;
  527. }
  528. }
  529. /**
  530. * 移除N个值为value
  531. *
  532. * @param key 键
  533. * @param count 移除多少个
  534. * @param value 值
  535. * @return 移除的个数
  536. */
  537. public long lRemove(String key, long count, Object value) {
  538. try {
  539. Long remove = redisTemplate.opsForList().remove(key, count, value);
  540. return remove;
  541. } catch (Exception e) {
  542. e.printStackTrace();
  543. return 0;
  544. }
  545. }
  546. }

发表评论

表情:
评论列表 (有 0 条评论,211人围观)

还没有评论,来说两句吧...

相关阅读