SpringBoot整合Redis及Redis工具类撰写

        SpringBoot整合Redis的博客很多,但是很多都不是我想要的结果。因为我只需要整合完成后,可以操作Redis就可以了,并不需要配合缓存相关的注解使用(如 @Cacheable )。看了很多博客后,我成功的整合了,并写了个Redis操作工具类。特意在此记录一下,方便后续查阅。

一、Maven依赖

(1)本文所采用的SpringBoot的版本如下
   
   
  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.0.2.RELEASE</version>
  5. <relativePath/> <!-- lookup parent from repository -->
  6. </parent>
(2)加入Redis相关依赖
   
   
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-redis</artifactId>
  4. </dependency>

二、application.properties中加入redis相关配置

   
   
  1. # Redis数据库索引(默认为0)
  2. spring.redis.database=0
  3. # Redis服务器地址
  4. spring.redis.host=192.168.0.24
  5. # Redis服务器连接端口
  6. spring.redis.port=6379
  7. # Redis服务器连接密码(默认为空)
  8. spring.redis.password=
  9. # 连接池最大连接数(使用负值表示没有限制)
  10. spring.redis.pool.max-active=200
  11. # 连接池最大阻塞等待时间(使用负值表示没有限制)
  12. spring.redis.pool.max-wait=-1
  13. # 连接池中的最大空闲连接
  14. spring.redis.pool.max-idle=10
  15. # 连接池中的最小空闲连接
  16. spring.redis.pool.min-idle=0
  17. # 连接超时时间(毫秒)
  18. spring.redis.timeout=1000

三、写一个redis配置类

(1)聊聊RedisTemplate的自动配置
        其实现在就可以在代码中注入 RedisTemplate,为啥可以直接注入呢?先看下源码吧。下图为 RedisAutoConfiguration类中的截图,为了防止图片失效,代码也贴上 。
         
        代码:
   
   
  1. @Configuration
  2. @ConditionalOnClass(RedisOperations.class)
  3. @EnableConfigurationProperties(RedisProperties.class)
  4. @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
  5. public class RedisAutoConfiguration {
  6. @Bean
  7. @ConditionalOnMissingBean(name = "redisTemplate")
  8. public RedisTemplate<Object, Object> redisTemplate(
  9. RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
  10. RedisTemplate<Object, Object> template = new RedisTemplate<>();
  11. template.setConnectionFactory(redisConnectionFactory);
  12. return template;
  13. }
  14. @Bean
  15. @ConditionalOnMissingBean
  16. public StringRedisTemplate stringRedisTemplate(
  17. RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
  18. StringRedisTemplate template = new StringRedisTemplate();
  19. template.setConnectionFactory(redisConnectionFactory);
  20. return template;
  21. }
  22. }
        通过源码可以看出,SpringBoot自动帮我们在容器中生成了一个RedisTemplate和一个StringRedisTemplate但是,这个 RedisTemplate的泛型是 <Object,Object>,写代码不方便,需要写好多类型转换的代码;我们需要一个泛型为 <String,Object>形式的 RedisTemplate。并且,这个 RedisTemplate没有设置数据存在Redis时,key及value的序列化方式。
        看到这个 @ConditionalOnMissingBean 注解后,就知道 如果Spring容器中有了RedisTemplate对象了,这个自动配置的RedisTemplate不会实例化 。因此我们可以直接自己写个配置类,配置RedisTemplate


(2)既然自动配置不好用,就重新配置一个RedisTemplate
        代码如下:
   
   
  1. package com.zxy.demo.redis;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.data.redis.connection.RedisConnectionFactory;
  5. import org.springframework.data.redis.core.RedisTemplate;
  6. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
  7. import org.springframework.data.redis.serializer.StringRedisSerializer;
  8. import com.fasterxml.jackson.annotation.JsonAutoDetect;
  9. import com.fasterxml.jackson.annotation.PropertyAccessor;
  10. import com.fasterxml.jackson.databind.ObjectMapper;
  11. /**
  12. * redis配置类
  13. * @author ZENG.XIAO.YAN
  14. * @date 2018年6月6日
  15. *
  16. */
  17. @Configuration
  18. public class RedisConfig {
  19. @Bean
  20. @SuppressWarnings("all")
  21. public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
  22. RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
  23. template.setConnectionFactory(factory);
  24. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
  25. ObjectMapper om = new ObjectMapper();
  26. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  27. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  28. jackson2JsonRedisSerializer.setObjectMapper(om);
  29. StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
  30. // key采用String的序列化方式
  31. template.setKeySerializer(stringRedisSerializer);
  32. // hash的key也采用String的序列化方式
  33. template.setHashKeySerializer(stringRedisSerializer);
  34. // value序列化方式采用jackson
  35. template.setValueSerializer(jackson2JsonRedisSerializer);
  36. // hash的value序列化方式采用jackson
  37. template.setHashValueSerializer(jackson2JsonRedisSerializer);
  38. template.afterPropertiesSet();
  39. return template;
  40. }
  41. }


四、写一个Redis工具类

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

五、小结

        整合其实不麻烦,网上好多博文都有。注意设置下key和value的序列化方式,不然存到Redis的中数据看起来像乱码一下。

猜你喜欢

转载自www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html