springboot2.x整合redis模块

柔情只为你懂 2021-12-09 05:07 382阅读 0赞

本文是基于springboot2.x版本对于redis服务的模块整合。

pom.xml

  1. <!-- cache-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-cache</artifactId>
  5. </dependency>
  6. <!--redis-->
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter-data-redis</artifactId>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.apache.commons</groupId>
  13. <artifactId>commons-pool2</artifactId>
  14. </dependency>

application.yml

  1. #redis配置
  2. spring:
  3. redis:
  4. database: 0 #默认使用0号库
  5. host: 47.105.83.58 #redis服务地址
  6. port: 6379 #端口
  7. password: zrsupply #密码
  8. lettuce:
  9. pool:
  10. max-active: 16 #最大连接数
  11. max-wait: 30s #最长等待时间
  12. max-idle: 8 #最大空闲连接
  13. min-idle: 1 #最小空闲连接
  14. timeout: 10s #连接超时时间
  15. cache:
  16. type: redis

定义redis的配置类

  1. @EnableCaching:启用缓存
  2. package com.ruoyi.common.config;
  3. import com.fasterxml.jackson.annotation.JsonAutoDetect;
  4. import com.fasterxml.jackson.annotation.PropertyAccessor;
  5. import com.fasterxml.jackson.databind.ObjectMapper;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.cache.CacheManager;
  10. import org.springframework.cache.annotation.CachingConfigurerSupport;
  11. import org.springframework.cache.annotation.EnableCaching;
  12. import org.springframework.cache.interceptor.KeyGenerator;
  13. import org.springframework.context.annotation.Bean;
  14. import org.springframework.context.annotation.Configuration;
  15. import org.springframework.data.redis.cache.RedisCacheConfiguration;
  16. import org.springframework.data.redis.cache.RedisCacheManager;
  17. import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
  18. import org.springframework.data.redis.core.RedisTemplate;
  19. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
  20. import org.springframework.data.redis.serializer.RedisSerializationContext;
  21. import org.springframework.data.redis.serializer.RedisSerializer;
  22. import org.springframework.data.redis.serializer.StringRedisSerializer;
  23. import java.lang.reflect.Method;
  24. import java.time.Duration;
  25. /**
  26. * created by py on 2019/7/11
  27. */
  28. @EnableCaching
  29. @Configuration
  30. public class RedisConfig extends CachingConfigurerSupport {
  31. private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
  32. @Autowired
  33. private LettuceConnectionFactory lettuceConnectionFactory;
  34. @Bean
  35. public KeyGenerator keyGenerator() {
  36. return new KeyGenerator() {
  37. @Override
  38. public Object generate(Object target, Method method, Object... params) {
  39. StringBuffer sb = new StringBuffer();
  40. sb.append(target.getClass().getName());
  41. sb.append(method.getName());
  42. for (Object obj : params) {
  43. sb.append(obj.toString());
  44. }
  45. return sb.toString();
  46. }
  47. };
  48. }
  49. // key键序列化方式
  50. private RedisSerializer<String> keySerializer() {
  51. return new StringRedisSerializer();
  52. }
  53. /**
  54. * json序列化
  55. * @return
  56. */
  57. @Bean
  58. public RedisSerializer<Object> jackson2JsonRedisSerializer() {
  59. //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
  60. Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
  61. ObjectMapper mapper = new ObjectMapper();
  62. mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  63. mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  64. serializer.setObjectMapper(mapper);
  65. return serializer;
  66. }
  67. /**
  68. * 配置缓存管理器
  69. * @return
  70. */
  71. @Bean
  72. public CacheManager cacheManager() {
  73. // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
  74. RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
  75. // 设置缓存的默认过期时间,也是使用Duration设置
  76. config = config.entryTtl(Duration.ofMinutes(60*12))
  77. // 设置 key为string序列化
  78. .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
  79. // 设置value为json序列化
  80. .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()))
  81. // 不缓存空值
  82. .disableCachingNullValues();
  83. // 使用自定义的缓存配置初始化一个cacheManager
  84. return RedisCacheManager
  85. .builder(lettuceConnectionFactory)
  86. .cacheDefaults(config)
  87. .transactionAware()
  88. .build();
  89. }
  90. /**
  91. * RedisTemplate配置
  92. */
  93. @Bean
  94. public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
  95. RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
  96. //todo 设置连接工厂(lettuceConnectionFactory为springboot2.0之后添加的新工厂)
  97. redisTemplate.setConnectionFactory(lettuceConnectionFactory);
  98. //todo 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
  99. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
  100. ObjectMapper objectMapper = new ObjectMapper();
  101. //todo 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
  102. objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  103. //todo 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
  104. objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  105. jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
  106. //使用StringRedisSerializer来序列化和反序列化redis的key值
  107. RedisSerializer redisSerializer = new StringRedisSerializer();
  108. //key
  109. redisTemplate.setKeySerializer(redisSerializer);
  110. redisTemplate.setHashKeySerializer(redisSerializer);
  111. //value 值采用json序列化
  112. redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
  113. redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
  114. redisTemplate.afterPropertiesSet();
  115. return redisTemplate;
  116. }
  117. }

使用缓存注解的话此时只需要在你的方法上添加对应的注释即可(更多缓存注解请自行研究)

PS将对象放置缓存中时对象需要实现序列化**(实现 Serializable 接口)**

@Cacheable:设置缓存(调用方法时判断是否存在缓存,存在直接取缓存,否则查询后将数据存放至缓存中供下次使用)

@CachePut:修改缓存的数据

@CacheEvict:删除缓存数据

PS:缓存使用的时候在service中调用方法A调用方法B时无法触发缓存的调用

缓存调用失败参考文章:

原因

Aop的原理图如下:

70

也就是说我们首先调用的是AOP代理对象而不是目标对象。但是我们使用this.getInstalledApk(imeiSnCodes.get(i))时,this表示的是当前的对象,而不是代理对象,因此注解失效。

class:serviceimpl

method:A

method:B(注解缓存)

public Json A(){

Json o = this.B();//此时缓存失效

}

PS:【在使用注解的时候无法在注解上指定key的失效时间,需要实现自定义注解来了设置key的失效时间

参考文章1:

参考文章2:

参考文章3:

RedisTemplate模板

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

发表评论

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

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

相关阅读

    相关 springboot2.X整合redis

    趁着今天休息就学习了一下redis,刚开始配置的时候遇到一些坑,现在写下来记一下,首先springboot使用的版本是2.X(我使用的是2.1.6)我的是在本地配置的,环境是w