• 21 Spring Boot整合Redis


       目录

    一、Redis简介

    二、创建springboot整合redis工程

    三、添加依赖

    四、配置Yml

    五、创建Redis配置类 

    六、创建Redis工具类,封装Redis的api

    七、操作Redis 

    八、验证


         

    一、Redis简介


    简单来说 Redis 就是一个使用 C 语言开发的数据库,不过与传统数据库不同的是 Redis 的数据是存在内存中的 ,也就是它是内存数据库,所以读写速度非常快,因此 Redis 被广泛应用于缓存方向。

    另外,Redis 除了做缓存之外,Redis 也经常用来做分布式锁,甚至是消息队列。

    Redis 提供了多种数据类型来支持不同的业务场景。Redis 还支持事务 、持久化、Lua 脚本、多种集群方案。

    接口幂等性:防止重复提交

    (在互联网API接口中,由于网络超时、手动刷新等经常导致客户端重复提交数据到服务端)比如说添加一次和添加多次结果是一样的,只会执行一次

    如何防止重复提交:用注解 + AOP。通过在自定义注解里定义一些相关的字段,比如过期时间即该时间内同一用户不能重复提交请求。然后把注解按需加在接口上,最后在拦截器里判断接口上是否有该接口,如果存在则拦截。
     

    目前主流的 Java 项目都在使用 Spring Boot,那么我们就来在 Spring Boot 中整合 Redis。

             Spring Boot 使用“约定大于配置”的方式逐步的取代了早起通过 XML 进行配置的方式,使得在 Spring Boot 中整合各种库或者依赖都非常的方便。

    二、创建springboot整合redis工程

       在我们创建 Spring Boot 项目时,选择相关的 Starter 时,在 “NoSQL” 中把 “Spring Data Redis” 项勾选即可

    三、添加依赖

           org.springframework.boot

           spring-boot-starter-data-redis

    四、配置Yml

    spring:
      redis:
        # Redis服务器地址
        host: 127.0.0.1
        # Redis服务器端口号
        port: 6379
        # 使用的数据库索引,默认是0
        database: 0
        # 连接超时时间
        timeout: 1800000
        # 设置密码
        password: "123456"
        lettuce:
          pool:
            # 最大阻塞等待时间,负数表示没有限制
            max-wait: -1
            # 连接池中的最大空闲连接
            max-idle: 5
            # 连接池中的最小空闲连接
            min-idle: 0
            # 连接池中最大连接数,负数表示没有限制
            max-active: 20

    五、创建Redis配置类 

    1. package com.crazyk.redisboot.config;
    2. import com.fasterxml.jackson.annotation.JsonAutoDetect;
    3. import com.fasterxml.jackson.annotation.PropertyAccessor;
    4. import com.fasterxml.jackson.databind.ObjectMapper;
    5. import org.springframework.cache.annotation.CachingConfigurerSupport;
    6. import org.springframework.cache.annotation.EnableCaching;
    7. import org.springframework.context.annotation.Bean;
    8. import org.springframework.context.annotation.Configuration;
    9. import org.springframework.data.redis.connection.RedisConnectionFactory;
    10. import org.springframework.data.redis.core.*;
    11. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    12. import org.springframework.data.redis.serializer.StringRedisSerializer;
    13. /**
    14. * @program: RedisBoot
    15. * @description: redis配置类
    16. * @author: CrazyK
    17. * @create: 2023-06-28 15:29
    18. **/
    19. @Configuration
    20. @EnableCaching //开启注解
    21. public class RedisConfig extends CachingConfigurerSupport {
    22. /**
    23. * retemplate相关配置
    24. */
    25. @Bean
    26. public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
    27. RedisTemplate template = new RedisTemplate<>();
    28. // 配置连接工厂
    29. template.setConnectionFactory(factory);
    30. //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
    31. Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
    32. ObjectMapper om = new ObjectMapper();
    33. // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
    34. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    35. // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
    36. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    37. jacksonSeial.setObjectMapper(om);
    38. // 值采用json序列化
    39. template.setValueSerializer(jacksonSeial);
    40. //使用StringRedisSerializer来序列化和反序列化redis的key值
    41. template.setKeySerializer(new StringRedisSerializer());
    42. // 设置hash key 和value序列化模式
    43. template.setHashKeySerializer(new StringRedisSerializer());
    44. template.setHashValueSerializer(jacksonSeial);
    45. template.afterPropertiesSet();
    46. return template;
    47. }
    48. /**
    49. * 对hash类型的数据操作
    50. */
    51. @Bean
    52. public HashOperations hashOperations(RedisTemplate redisTemplate) {
    53. return redisTemplate.opsForHash();
    54. }
    55. /**
    56. * 对redis字符串类型数据操作
    57. */
    58. @Bean
    59. public ValueOperations valueOperations(RedisTemplate redisTemplate) {
    60. return redisTemplate.opsForValue();
    61. }
    62. /**
    63. * 对链表类型的数据操作
    64. */
    65. @Bean
    66. public ListOperations listOperations(RedisTemplate redisTemplate) {
    67. return redisTemplate.opsForList();
    68. }
    69. /**
    70. * 对无序集合类型的数据操作
    71. */
    72. @Bean
    73. public SetOperations setOperations(RedisTemplate redisTemplate) {
    74. return redisTemplate.opsForSet();
    75. }
    76. /**
    77. * 对有序集合类型的数据操作
    78. */
    79. @Bean
    80. public ZSetOperations zSetOperations(RedisTemplate redisTemplate) {
    81. return redisTemplate.opsForZSet();
    82. }
    83. }

    六、创建Redis工具类,封装Redis的api

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

             使用redis工具类,本质上是使用 redis api操作。

      1. package com.crazyk.redisboot.controller;
      2. import com.crazyk.redisboot.util.RedisUtil;
      3. import lombok.extern.slf4j.Slf4j;
      4. import org.springframework.web.bind.annotation.RequestMapping;
      5. import org.springframework.web.bind.annotation.RestController;
      6. import javax.annotation.Resource;
      7. @Slf4j
      8. @RequestMapping("/redis")
      9. @RestController
      10. public class RedisController {
      11. @Resource
      12. private RedisUtil redisUtil;
      13. @RequestMapping("set")
      14. public boolean redisset(String key, String value){
      15. System.out.println(key+"--"+value);
      16. return redisUtil.set(key,value);
      17. }
      18. @RequestMapping("get")
      19. public Object redisget(String key){
      20. System.out.println(redisUtil.get(key));
      21. return redisUtil.get(key);
      22. }
      23. @RequestMapping("expire")
      24. public boolean expire(String key,long ExpireTime){
      25. return redisUtil.expire(key,ExpireTime);
      26. }
      27. }

      八、验证

      使用浏览器发送一个请求

      去redis中自己验证

    497. 相关阅读:
      2023年,想要靠做软件测试获得高薪,还有机会吗?
      数据结构之队列
      全面了解三极管——三极管用作开关管2
      统信UOS技术开放日:四大领域全面接入AI大模型能力
      【QT】Hello World!
      备战数学建模1——MATLAB矩阵相关
      圆角矩形不是圆:圆角的画法和二阶连续性
      electron初学
      ICE常见编译和运行(异常)错误
      dubbo 接口的测试方法汇总
    498. 原文地址:https://blog.csdn.net/qq_41946216/article/details/132765059