当前位置:   article > 正文

SpringBoot整合Redis_springboot redis

springboot redis

SpringBoot中的Redis

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

jedis : 采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用 jedis pool 连接 池! 更像 BIO 模式

lettuce : 采用netty,实例可以再多个线程中进行共享,不存在线程不安全的情况!可以减少线程数据 了,更像 NIO 模式

环境搭建与测试

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

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

3.在测试类中进行测试

五大数据类型

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

特殊数据类型

  • opsForGeo()
  • opsForHyperLogLog()
  1. @Test
  2. void contextLoads() {
  3. //五大数据类型
  4. //opsForValue() 操作字符串 类似String
  5. //opsForList() 操作List 类似List
  6. //opsForSet() 操作Set 类似Set
  7. //opsForZSet() 操作ZSet 类似ZSet
  8. //opsForHash() 操作Hash 类似Hash
  9. //特殊数据类型
  10. //opsForGeo()
  11. //opsForHyperLogLog()
  12. //除了基本的操作,我们常用的方法都可以通过redisTemplate操作。比如事务,和基本的CRUD
  13. redisTemplate.opsForValue().set("mykey", "kylin");
  14. System.out.println(redisTemplate.opsForValue().get("mykey"));
  15. }
  16. 复制代码

自定义RedisTemplate

  1. @Bean
  2. @ConditionalOnMissingBean(name = "redisTemplate")
  3. public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
  4. throws UnknownHostException {
  5. // 默认的 RedisTemplate 没有过多的设置,redis 对象都是需要序列化!
  6. // 两个泛型都是 Object, Object 的类型,我们后使用需要强制转换 <String, Object>
  7. RedisTemplate<Object, Object> template = new RedisTemplate<>();
  8. template.setConnectionFactory(redisConnectionFactory);
  9. return template;
  10. }
  11. @Bean
  12. @ConditionalOnMissingBean
  13. // 由于 String 是redis中最常使用的类型,所以说单独提出来了一个bean!
  14. public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
  15. throws UnknownHostException {
  16. StringRedisTemplate template = new StringRedisTemplate();
  17. template.setConnectionFactory(redisConnectionFactory);
  18. return template;
  19. }
  20. 复制代码

首先我们编写一个实体类User

  1. @Component
  2. @Data
  3. @AllArgsConstructor
  4. @NoArgsConstructor
  5. //所有的pojo都要序列化
  6. public class User implements Serializable {
  7. private String name;
  8. private int age;
  9. }
  10. 复制代码

在测试类中测试像Redis存储一个User对象

  1. @Test
  2. void test2() {
  3. //真实的开发一般都是用Json来传递对象
  4. User user = new User("kylin", 18);
  5. //String jsonUser = new ObjectMapper().writeValueAsString(user)
  6. redisTemplate.opsForValue().set("user", user);
  7. System.out.println(redisTemplate.opsForValue().get("user"));
  8. }
  9. 复制代码

成功存储并获取到~

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

只是因为redis默认序列化时会使用jdk序列化器。要想解决这样的问题题我们就要自定义配置RedisTemplate

1.首先我们创建一个config包在包下编写一个RedisConfig配置类。以后使用直接复制就行。

  1. @Configuration
  2. public class RedisConfig {
  3. // 这是我给大家写好的一个固定模板,大家在企业中,拿去就可以直接使用!
  4. // 自己定义了一个 RedisTemplate
  5. @Bean
  6. @SuppressWarnings("all")
  7. public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
  8. // 我们为了自己开发方便,一般直接使用 <String, Object>
  9. RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
  10. template.setConnectionFactory(factory);
  11. // Json序列化配置
  12. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
  13. ObjectMapper om = new ObjectMapper();
  14. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  15. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  16. jackson2JsonRedisSerializer.setObjectMapper(om);
  17. // String 的序列化
  18. StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
  19. // key采用String的序列化方式
  20. template.setKeySerializer(stringRedisSerializer);
  21. // hash的key也采用String的序列化方式
  22. template.setHashKeySerializer(stringRedisSerializer);
  23. // value序列化方式采用jackson
  24. template.setValueSerializer(jackson2JsonRedisSerializer);
  25. // hash的value序列化方式采用jackson
  26. template.setHashValueSerializer(jackson2JsonRedisSerializer);
  27. template.afterPropertiesSet();
  28. return template;
  29. }
  30. }
  31. 复制代码

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

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/152058
推荐阅读
相关标签
  

闽ICP备14008679号