Redis(五)整合:SpringBoot如何整合Redis?

比眉伴天荒 2023-01-09 03:57 264阅读 0赞

前言

SpringBoot应该不用过多介绍了吧!是Spring当前最火的一个框架,既然学习了Redis,我们肯定是要在实际项目中使用,那么肯定首选整合SpringBoot啦!

简单介绍下SpringBoot对Jedis的支持吧,在1.×版本的时候,SpringBoot的底层还是使用Jedis来连接Redis的,但是在2.×版本后,就换成了Lettuce。两者的区别如下:
Jedis: 采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用 jedis pool 连接池! 更像 BIO 模式!
Lettuce: 采用netty,实例可以再多个线程中进行共享,不存在线程不安全的情况!可以减少线程数据了,更像 NIO 模式!

  1. 添加POM依赖:

    1. <!--集成redis-->
    2. <dependency>
    3. <groupId>org.springframework.boot</groupId>
    4. <artifactId>spring-boot-starter-data-redis</artifactId>
    5. <version>2.1.7.RELEASE</version>
    6. </dependency>
    7. <!--序列化-->
    8. <dependency>
    9. <groupId>com.alibaba</groupId>
    10. <artifactId>fastjson</artifactId>
    11. <version>1.2.54</version>
    12. <scope>compile</scope>
    13. </dependency>
    14. <!--lombok,自动生成set、get等方法-->
    15. <dependency>
    16. <groupId>org.projectlombok</groupId>
    17. <artifactId>lombok</artifactId>
    18. <version>1.18.10</version>
    19. <scope>compile</scope>
    20. </dependency>
  2. 配置连接的application.yml文件:

    server:
    port: 10001

    spring:
    redis:

    1. host: 127.0.0.1
    2. port: 6379
  3. 测试连接:我们写个测试方法来进行最基本的连接测试!

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.RedisTemplate;

    @SpringBootTest
    public class testRedis {

    1. @Autowired(required = false)
    2. private RedisTemplate redisTemplate;
    3. @Test
    4. void getName(){
    5. redisTemplate.opsForValue().set("name","dadadingdada!");
    6. System.out.println(redisTemplate.opsForValue().get("name"));
    7. }

    }

运行效果如下!证明Redis连接成功!并且加数据获取数据也成功了!
在这里插入图片描述

  1. 其他方法如下:

    // redisTemplate #操作不同的数据类型,api和我们的指令是一样的
    // opsForValue #操作字符串 类似String
    // opsForList #操作List 类似List
    // opsForSet #操作set
    // opsForHash #操作hash
    // opsForZSet #操作zset
    // opsForGeo #操作geo
    // opsForHyperLogLog #操作HyperLogLog
    // 除了进本的操作,我们常用的方法都可以直接通过redisTemplate操作,比如事务,和基本的 CRUD
    // 获取redis的连接对象
    // RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
    // connection.flushDb();
    // connection.flushAll();

证明如果是用基本RedisTemplate类来操作Redis的话,是基本上可以达到所有的效果的,因为具体方法和命令大体一致!

  1. 对象的保存和读取
    新增一个User类:

    import lombok.Data;

    @Data
    public class User {

    1. private String name;
    2. private Integer age;
    3. private Integer high;

    }

测试代码如下:

  1. @Test
  2. void setObject(){
  3. User user = new User();
  4. user.setName("dingdada");
  5. user.setAge(23);
  6. user.setHigh(172);
  7. redisTemplate.opsForValue().set("user",user);
  8. System.out.println(redisTemplate.opsForValue().get("user"));
  9. }

报错如下:
在这里插入图片描述
结论:所以在操作Redis中,关于对象的保存我们得序列化才可以正常操作!

  1. 自定义封装RedisTemplate类
    上面说了大体上可以实现,但是为了在工作中更容易操作Redis,我们一般重新封装RedisTemplate类,如下所示:

    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;

    @Configuration
    public class RedisConfig {

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

    }

序列化完成后我们再试试对象的添加获取:
在这里插入图片描述
NICE!一切正常!

  1. 封装RedisUtils类:
    在实际工作中,我们不可能用RedisTemplate 来操作Redis的,因为实在太繁琐,所以我们一般自定义一个RedisUtils工具类来操作Redis!

    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Component;
    import org.springframework.util.CollectionUtils;

    import javax.annotation.Resource;
    import java.util.Collection;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;

    @Component
    public final class RedisUtil {

    1. @Resource
    2. private RedisTemplate<String, Object> redisTemplate;
  1. public Set<String> keys(String keys){
  2. try {
  3. return redisTemplate.keys(keys);
  4. }catch (Exception e){
  5. e.printStackTrace();
  6. return null;
  7. }
  8. }
  9. /** * 指定缓存失效时间 * @param key 键 * @param time 时间(秒) * @return */
  10. public boolean expire(String key, long time) {
  11. try {
  12. if (time > 0) {
  13. redisTemplate.expire(key, time, TimeUnit.SECONDS);
  14. }
  15. return true;
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. return false;
  19. }
  20. }
  21. /** * 根据key 获取过期时间 * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */
  22. public long getExpire(String key) {
  23. return redisTemplate.getExpire(key, TimeUnit.SECONDS);
  24. }
  25. /** * 判断key是否存在 * @param key 键 * @return true 存在 false不存在 */
  26. public boolean hasKey(String key) {
  27. try {
  28. return redisTemplate.hasKey(key);
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. return false;
  32. }
  33. }
  34. /** * 删除缓存 * @param key 可以传一个值 或多个 */
  35. @SuppressWarnings("unchecked")
  36. public void del(String... key) {
  37. if (key != null && key.length > 0) {
  38. if (key.length == 1) {
  39. redisTemplate.delete(key[0]);
  40. } else {
  41. redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
  42. }
  43. }
  44. }
  45. /** * 普通缓存获取 * @param key 键 * @return 值 */
  46. public Object get(String key) {
  47. return key == null ? null : redisTemplate.opsForValue().get(key);
  48. }
  49. /** * 普通缓存放入 * @param key 键 * @param value 值 * @return true成功 false失败 */
  50. public boolean set(String key, Object value) {
  51. try {
  52. redisTemplate.opsForValue().set(key, value);
  53. return true;
  54. } catch (Exception e) {
  55. e.printStackTrace();
  56. return false;
  57. }
  58. }
  59. /** * 普通缓存放入, 不存在放入,存在返回 * @param key 键 * @param value 值 * @return true成功 false失败 */
  60. public boolean setnx(String key, Object value) {
  61. try {
  62. redisTemplate.opsForValue().setIfAbsent(key,value);
  63. return true;
  64. } catch (Exception e) {
  65. e.printStackTrace();
  66. return false;
  67. }
  68. }
  69. /** * 普通缓存放入并设置时间 * @param key 键 * @param value 值 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */
  70. public boolean set(String key, Object value, long time) {
  71. try {
  72. if (time > 0) {
  73. redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
  74. } else {
  75. set(key, value);
  76. }
  77. return true;
  78. } catch (Exception e) {
  79. e.printStackTrace();
  80. return false;
  81. }
  82. }
  83. /** * 普通缓存放入并设置时间,不存在放入,存在返回 * @param key 键 * @param value 值 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */
  84. public boolean setnx(String key, Object value, long time) {
  85. try {
  86. if (time > 0) {
  87. redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);
  88. } else {
  89. set(key, value);
  90. }
  91. return true;
  92. } catch (Exception e) {
  93. e.printStackTrace();
  94. return false;
  95. }
  96. }
  97. /** * 递增 * @param key 键 * @param delta 要增加几(大于0) * @return */
  98. public long incr(String key, long delta) {
  99. if (delta < 0) {
  100. throw new RuntimeException("递增因子必须大于0");
  101. }
  102. return redisTemplate.opsForValue().increment(key, delta);
  103. }
  104. /** * 递减 * @param key 键 * @param delta 要减少几(小于0) * @return */
  105. public long decr(String key, long delta) {
  106. if (delta < 0) {
  107. throw new RuntimeException("递减因子必须大于0");
  108. }
  109. return redisTemplate.opsForValue().increment(key, -delta);
  110. }
  111. /** * HashGet * @param key 键 不能为null * @param item 项 不能为null * @return 值 */
  112. public Object hget(String key, String item) {
  113. return redisTemplate.opsForHash().get(key, item);
  114. }
  115. /** * 获取hashKey对应的所有键值 * @param key 键 * @return 对应的多个键值 */
  116. public Map<Object, Object> hmget(String key) {
  117. return redisTemplate.opsForHash().entries(key);
  118. }
  119. /** * HashSet * @param key 键 * @param map 对应多个键值 * @return true 成功 false 失败 */
  120. public boolean hmset(String key, Map<String, Object> map) {
  121. try {
  122. redisTemplate.opsForHash().putAll(key, map);
  123. return true;
  124. } catch (Exception e) {
  125. e.printStackTrace();
  126. return false;
  127. }
  128. }
  129. /** * HashSet 并设置时间 * @param key 键 * @param map 对应多个键值 * @param time 时间(秒) * @return true成功 false失败 */
  130. public boolean hmset(String key, Map<String, Object> map, long time) {
  131. try {
  132. redisTemplate.opsForHash().putAll(key, map);
  133. if (time > 0) {
  134. expire(key, time);
  135. }
  136. return true;
  137. } catch (Exception e) {
  138. e.printStackTrace();
  139. return false;
  140. }
  141. }
  142. /** * 向一张hash表中放入数据,如果不存在将创建 * @param key 键 * @param item 项 * @param value 值 * @return true 成功 false失败 */
  143. public boolean hset(String key, String item, Object value) {
  144. try {
  145. redisTemplate.opsForHash().put(key, item, value);
  146. return true;
  147. } catch (Exception e) {
  148. e.printStackTrace();
  149. return false;
  150. }
  151. }
  152. /** * 向一张hash表中放入数据,如果不存在将创建 * @param key 键 * @param item 项 * @param value 值 * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 * @return true 成功 false失败 */
  153. public boolean hset(String key, String item, Object value, long time) {
  154. try {
  155. redisTemplate.opsForHash().put(key, item, value);
  156. if (time > 0) {
  157. expire(key, time);
  158. }
  159. return true;
  160. } catch (Exception e) {
  161. e.printStackTrace();
  162. return false;
  163. }
  164. }
  165. /** * 删除hash表中的值 * @param key 键 不能为null * @param item 项 可以使多个 不能为null */
  166. public void hdel(String key, Object... item) {
  167. redisTemplate.opsForHash().delete(key, item);
  168. }
  169. /** * 判断hash表中是否有该项的值 * @param key 键 不能为null * @param item 项 不能为null * @return true 存在 false不存在 */
  170. public boolean hHasKey(String key, String item) {
  171. return redisTemplate.opsForHash().hasKey(key, item);
  172. }
  173. /** * hash递增 如果不存在,就会创建一个 并把新增后的值返回 * @param key 键 * @param item 项 * @param by 要增加几(大于0) * @return */
  174. public double hincr(String key, String item, double by) {
  175. return redisTemplate.opsForHash().increment(key, item, by);
  176. }
  177. /** * hash递减 * @param key 键 * @param item 项 * @param by 要减少记(小于0) * @return */
  178. public double hdecr(String key, String item, double by) {
  179. return redisTemplate.opsForHash().increment(key, item, -by);
  180. }
  181. /** * 根据key获取Set中的所有值 * @param key 键 * @return */
  182. public Set<Object> sGet(String key) {
  183. try {
  184. return redisTemplate.opsForSet().members(key);
  185. } catch (Exception e) {
  186. e.printStackTrace();
  187. return null;
  188. }
  189. }
  190. /** * 根据value从一个set中查询,是否存在 * @param key 键 * @param value 值 * @return true 存在 false不存在 */
  191. public boolean sHasKey(String key, Object value) {
  192. try {
  193. return redisTemplate.opsForSet().isMember(key, value);
  194. } catch (Exception e) {
  195. e.printStackTrace();
  196. return false;
  197. }
  198. }
  199. /** * 将数据放入set缓存 * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */
  200. public long sSet(String key, Object... values) {
  201. try {
  202. return redisTemplate.opsForSet().add(key, values);
  203. } catch (Exception e) {
  204. e.printStackTrace();
  205. return 0;
  206. }
  207. }
  208. /** * 将set数据放入缓存 * @param key 键 * @param time 时间(秒) * @param values 值 可以是多个 * @return 成功个数 */
  209. public long sSetAndTime(String key, long time, Object... values) {
  210. try {
  211. Long count = redisTemplate.opsForSet().add(key, values);
  212. if (time > 0){
  213. expire(key, time);
  214. }
  215. return count;
  216. } catch (Exception e) {
  217. e.printStackTrace();
  218. return 0;
  219. }
  220. }
  221. /** * 获取set缓存的长度 * @param key 键 * @return */
  222. public long sGetSetSize(String key) {
  223. try {
  224. return redisTemplate.opsForSet().size(key);
  225. } catch (Exception e) {
  226. e.printStackTrace();
  227. return 0;
  228. }
  229. }
  230. /** * 移除值为value的 * @param key 键 * @param values 值 可以是多个 * @return 移除的个数 */
  231. public long setRemove(String key, Object... values) {
  232. try {
  233. Long count = redisTemplate.opsForSet().remove(key, values);
  234. return count;
  235. } catch (Exception e) {
  236. e.printStackTrace();
  237. return 0;
  238. }
  239. }
  240. // ===============================list=================================
  241. /** * 获取list缓存的内容 * @param key 键 * @param start 开始 * @param end 结束 0 到 -1代表所有值 * @return */
  242. public List<Object> lGet(String key, long start, long end) {
  243. try {
  244. return redisTemplate.opsForList().range(key, start, end);
  245. } catch (Exception e) {
  246. e.printStackTrace();
  247. return null;
  248. }
  249. }
  250. /** * 获取list缓存的长度 * @param key 键 * @return */
  251. public long lGetListSize(String key) {
  252. try {
  253. return redisTemplate.opsForList().size(key);
  254. } catch (Exception e) {
  255. e.printStackTrace();
  256. return 0;
  257. }
  258. }
  259. /** * 通过索引 获取list中的值 * @param key 键 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 * @return */
  260. public Object lGetIndex(String key, long index) {
  261. try {
  262. return redisTemplate.opsForList().index(key, index);
  263. } catch (Exception e) {
  264. e.printStackTrace();
  265. return null;
  266. }
  267. }
  268. /** * 将list放入缓存 * @param key 键 * @param value 值 * @return */
  269. public boolean lSet(String key, Object value) {
  270. try {
  271. redisTemplate.opsForList().rightPush(key, value);
  272. return true;
  273. } catch (Exception e) {
  274. e.printStackTrace();
  275. return false;
  276. }
  277. }
  278. /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */
  279. public boolean lSet(String key, Object value, long time) {
  280. try {
  281. redisTemplate.opsForList().rightPush(key, value);
  282. if (time > 0){
  283. expire(key, time);
  284. }
  285. return true;
  286. } catch (Exception e) {
  287. e.printStackTrace();
  288. return false;
  289. }
  290. }
  291. /** * 将list放入缓存 * @param key 键 * @param value 值 * @return */
  292. public boolean lSet(String key, List<Object> value) {
  293. try {
  294. redisTemplate.opsForList().rightPushAll(key, value);
  295. return true;
  296. } catch (Exception e) {
  297. e.printStackTrace();
  298. return false;
  299. }
  300. }
  301. /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */
  302. public boolean lSet(String key, List<Object> value, long time) {
  303. try {
  304. redisTemplate.opsForList().rightPushAll(key, value);
  305. if (time > 0){
  306. expire(key, time);
  307. }
  308. return true;
  309. } catch (Exception e) {
  310. e.printStackTrace();
  311. return false;
  312. }
  313. }
  314. /** * 根据索引修改list中的某条数据 * @param key 键 * @param index 索引 * @param value 值 * @return */
  315. public boolean lUpdateIndex(String key, long index, Object value) {
  316. try {
  317. redisTemplate.opsForList().set(key, index, value);
  318. return true;
  319. } catch (Exception e) {
  320. e.printStackTrace();
  321. return false;
  322. }
  323. }
  324. /** * 移除N个值为value * @param key 键 * @param count 移除多少个 * @param value 值 * @return 移除的个数 */
  325. public long lRemove(String key, long count, Object value) {
  326. try {
  327. Long remove = redisTemplate.opsForList().remove(key, count, value);
  328. return remove;
  329. } catch (Exception e) {
  330. e.printStackTrace();
  331. return 0;
  332. }
  333. }
  334. }

基本上常用的Redis操作都写在这里了,我们在工作中需要用什么,直接通过RedisUtils来使用即可!

  1. 使用RedisUtils
    ①首先将springboot项目启动起来:
    在这里插入图片描述
    ②添加Contoller在web上测试添加和获取!
    在这里插入图片描述

③测试工具类的基本使用:
在谷歌浏览器输入:返回成功
在这里插入图片描述
测试获取:获取成功!
在这里插入图片描述

9.总结:其实这篇讲了这么多,大家可以发现,SpringBoot真的是极度方便,整合Redis之后我们只需要简单的操作即可完美使用Redis!
但是,前面的内容还都是Redis相关的基础,接下来我将继续整理关于Redis的进阶知识!

Redis扩展:Redis学习汇总

路漫漫其修远兮,吾必将上下求索~
到此关于SpringBoot如何整合Redis的讲解就算告一段落了,如果你认为i博主写的不错!写作不易,请点赞、关注、评论给博主一个鼓励吧**转载请注明出处哦**

发表评论

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

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

相关阅读