SpringBoot整合Redis步骤,手把手教你一步步实现
mhr18 2024-11-12 11:16 13 浏览 0 评论
前言:
关于Spring的知识点总结了一个思维导图分享给大家:
一、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类中的截图,为了防止图片失效,代码也贴上。
代码:
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
通过源码可以看出,SpringBoot自动帮我们在容器中生成了一个RedisTemplate和一个StringRedisTemplate。但是,这个RedisTemplate的泛型是<Object,Object>,写代码不方便,需要写好多类型转换的代码;我们需要一个泛型为<String,Object>形式的RedisTemplate。并且,这个RedisTemplate没有设置数据存在Redis时,key及value的序列化方式。 看到这个@ConditionalOnMissingBean注解后,就知道如果Spring容器中有了RedisTemplate对象了,这个自动配置的RedisTemplate不会实例化。因此我们可以直接自己写个配置类,配置RedisTemplate。
(2)既然自动配置不好用,就重新配置一个RedisTemplate
代码如下:
package com.zxy.demo.redis;
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;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* redis配置类
* @author ZENG.XIAO.YAN
* @date 2018年6月6日
*
*/
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
四、写一个Redis工具类
直接用RedisTemplate操作Redis,需要很多行代码,因此直接封装好一个RedisUtils,这样写代码更方便点。这个RedisUtils交给Spring容器实例化,使用时直接注解注入。
工具类代码如下:
package com.zxy.demo.redis;
2
3
import java.util.List;
4
import java.util.Map;
5
import java.util.Set;
6
import java.util.concurrent.TimeUnit;
7
8
import org.springframework.beans.factory.annotation.Autowired;
9
import org.springframework.data.redis.core.RedisTemplate;
10
import org.springframework.stereotype.Component;
11
import org.springframework.util.CollectionUtils;
12
13
/**
14
* Redis工具类
15
* @author ZENG.XIAO.YAN
16
* @date 2018年6月7日
17
*/
18
@Component
19
public final class RedisUtil {
20
21
@Autowired
22
private RedisTemplate<String, Object> redisTemplate;
23
24
// =============================common============================
25
/**
26
* 指定缓存失效时间
27
* @param key 键
28
* @param time 时间(秒)
29
* @return
30
*/
31
public boolean expire(String key, long time) {
32
try {
33
if (time > 0) {
34
redisTemplate.expire(key, time, TimeUnit.SECONDS);
35
}
36
return true;
37
} catch (Exception e) {
38
e.printStackTrace();
39
return false;
40
}
41
}
42
43
/**
44
* 根据key 获取过期时间
45
* @param key 键 不能为null
46
* @return 时间(秒) 返回0代表为永久有效
47
*/
48
public long getExpire(String key) {
49
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
50
}
51
52
/**
53
* 判断key是否存在
54
* @param key 键
55
* @return true 存在 false不存在
56
*/
57
public boolean hasKey(String key) {
58
try {
59
return redisTemplate.hasKey(key);
60
} catch (Exception e) {
61
e.printStackTrace();
62
return false;
63
}
64
}
65
66
/**
67
* 删除缓存
68
* @param key 可以传一个值 或多个
69
*/
70
@SuppressWarnings("unchecked")
71
public void del(String... key) {
72
if (key != null && key.length > 0) {
73
if (key.length == 1) {
74
redisTemplate.delete(key[0]);
75
} else {
76
redisTemplate.delete(CollectionUtils.arrayToList(key));
77
}
78
}
79
}
80
81
// ============================String=============================
82
/**
83
* 普通缓存获取
84
* @param key 键
85
* @return 值
86
*/
87
public Object get(String key) {
88
return key == null ? null : redisTemplate.opsForValue().get(key);
89
}
90
91
/**
92
* 普通缓存放入
93
* @param key 键
94
* @param value 值
95
* @return true成功 false失败
96
*/
97
public boolean set(String key, Object value) {
98
try {
99
redisTemplate.opsForValue().set(key, value);
100
return true;
101
} catch (Exception e) {
102
e.printStackTrace();
103
return false;
104
}
105
106
}
107
108
/**
109
* 普通缓存放入并设置时间
110
* @param key 键
111
* @param value 值
112
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
113
* @return true成功 false 失败
114
*/
115
public boolean set(String key, Object value, long time) {
116
try {
117
if (time > 0) {
118
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
119
} else {
120
set(key, value);
121
}
122
return true;
123
} catch (Exception e) {
124
e.printStackTrace();
125
return false;
126
}
127
}
128
129
/**
130
* 递增
131
* @param key 键
132
* @param delta 要增加几(大于0)
133
* @return
134
*/
135
public long incr(String key, long delta) {
136
if (delta < 0) {
137
throw new RuntimeException("递增因子必须大于0");
138
}
139
return redisTemplate.opsForValue().increment(key, delta);
140
}
141
142
/**
143
* 递减
144
* @param key 键
145
* @param delta 要减少几(小于0)
146
* @return
147
*/
148
public long decr(String key, long delta) {
149
if (delta < 0) {
150
throw new RuntimeException("递减因子必须大于0");
151
}
152
return redisTemplate.opsForValue().increment(key, -delta);
153
}
154
155
// ================================Map=================================
156
/**
157
* HashGet
158
* @param key 键 不能为null
159
* @param item 项 不能为null
160
* @return 值
161
*/
162
public Object hget(String key, String item) {
163
return redisTemplate.opsForHash().get(key, item);
164
}
165
166
/**
167
* 获取hashKey对应的所有键值
168
* @param key 键
169
* @return 对应的多个键值
170
*/
171
public Map<Object, Object> hmget(String key) {
172
return redisTemplate.opsForHash().entries(key);
173
}
174
175
/**
176
* HashSet
177
* @param key 键
178
* @param map 对应多个键值
179
* @return true 成功 false 失败
180
*/
181
public boolean hmset(String key, Map<String, Object> map) {
182
try {
183
redisTemplate.opsForHash().putAll(key, map);
184
return true;
185
} catch (Exception e) {
186
e.printStackTrace();
187
return false;
188
}
189
}
190
191
/**
192
* HashSet 并设置时间
193
* @param key 键
194
* @param map 对应多个键值
195
* @param time 时间(秒)
196
* @return true成功 false失败
197
*/
198
public boolean hmset(String key, Map<String, Object> map, long time) {
199
try {
200
redisTemplate.opsForHash().putAll(key, map);
201
if (time > 0) {
202
expire(key, time);
203
}
204
return true;
205
} catch (Exception e) {
206
e.printStackTrace();
207
return false;
208
}
209
}
210
211
/**
212
* 向一张hash表中放入数据,如果不存在将创建
213
* @param key 键
214
* @param item 项
215
* @param value 值
216
* @return true 成功 false失败
217
*/
218
public boolean hset(String key, String item, Object value) {
219
try {
220
redisTemplate.opsForHash().put(key, item, value);
221
return true;
222
} catch (Exception e) {
223
e.printStackTrace();
224
return false;
225
}
226
}
227
228
/**
229
* 向一张hash表中放入数据,如果不存在将创建
230
* @param key 键
231
* @param item 项
232
* @param value 值
233
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
234
* @return true 成功 false失败
235
*/
236
public boolean hset(String key, String item, Object value, long time) {
237
try {
238
redisTemplate.opsForHash().put(key, item, value);
239
if (time > 0) {
240
expire(key, time);
241
}
242
return true;
243
} catch (Exception e) {
244
e.printStackTrace();
245
return false;
246
}
247
}
248
249
/**
250
* 删除hash表中的值
251
* @param key 键 不能为null
252
* @param item 项 可以使多个 不能为null
253
*/
254
public void hdel(String key, Object... item) {
255
redisTemplate.opsForHash().delete(key, item);
256
}
257
258
/**
259
* 判断hash表中是否有该项的值
260
* @param key 键 不能为null
261
* @param item 项 不能为null
262
* @return true 存在 false不存在
263
*/
264
public boolean hHasKey(String key, String item) {
265
return redisTemplate.opsForHash().hasKey(key, item);
266
}
267
268
/**
269
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
270
* @param key 键
271
* @param item 项
272
* @param by 要增加几(大于0)
273
* @return
274
*/
275
public double hincr(String key, String item, double by) {
276
return redisTemplate.opsForHash().increment(key, item, by);
277
}
278
279
/**
280
* hash递减
281
* @param key 键
282
* @param item 项
283
* @param by 要减少记(小于0)
284
* @return
285
*/
286
public double hdecr(String key, String item, double by) {
287
return redisTemplate.opsForHash().increment(key, item, -by);
288
}
289
290
// ============================set=============================
291
/**
292
* 根据key获取Set中的所有值
293
* @param key 键
294
* @return
295
*/
296
public Set<Object> sGet(String key) {
297
try {
298
return redisTemplate.opsForSet().members(key);
299
} catch (Exception e) {
300
e.printStackTrace();
301
return null;
302
}
303
}
304
305
/**
306
* 根据value从一个set中查询,是否存在
307
* @param key 键
308
* @param value 值
309
* @return true 存在 false不存在
310
*/
311
public boolean sHasKey(String key, Object value) {
312
try {
313
return redisTemplate.opsForSet().isMember(key, value);
314
} catch (Exception e) {
315
e.printStackTrace();
316
return false;
317
}
318
}
319
320
/**
321
* 将数据放入set缓存
322
* @param key 键
323
* @param values 值 可以是多个
324
* @return 成功个数
325
*/
326
public long sSet(String key, Object... values) {
327
try {
328
return redisTemplate.opsForSet().add(key, values);
329
} catch (Exception e) {
330
e.printStackTrace();
331
return 0;
332
}
333
}
334
335
/**
336
* 将set数据放入缓存
337
* @param key 键
338
* @param time 时间(秒)
339
* @param values 值 可以是多个
340
* @return 成功个数
341
*/
342
public long sSetAndTime(String key, long time, Object... values) {
343
try {
344
Long count = redisTemplate.opsForSet().add(key, values);
345
if (time > 0)
346
expire(key, time);
347
return count;
348
} catch (Exception e) {
349
e.printStackTrace();
350
return 0;
351
}
352
}
353
354
/**
355
* 获取set缓存的长度
356
* @param key 键
357
* @return
358
*/
359
public long sGetSetSize(String key) {
360
try {
361
return redisTemplate.opsForSet().size(key);
362
} catch (Exception e) {
363
e.printStackTrace();
364
return 0;
365
}
366
}
367
368
/**
369
* 移除值为value的
370
* @param key 键
371
* @param values 值 可以是多个
372
* @return 移除的个数
373
*/
374
public long setRemove(String key, Object... values) {
375
try {
376
Long count = redisTemplate.opsForSet().remove(key, values);
377
return count;
378
} catch (Exception e) {
379
e.printStackTrace();
380
return 0;
381
}
382
}
383
// ===============================list=================================
384
385
/**
386
* 获取list缓存的内容
387
* @param key 键
388
* @param start 开始
389
* @param end 结束 0 到 -1代表所有值
390
* @return
391
*/
392
public List<Object> lGet(String key, long start, long end) {
393
try {
394
return redisTemplate.opsForList().range(key, start, end);
395
} catch (Exception e) {
396
e.printStackTrace();
397
return null;
398
}
399
}
400
401
/**
402
* 获取list缓存的长度
403
* @param key 键
404
* @return
405
*/
406
public long lGetListSize(String key) {
407
try {
408
return redisTemplate.opsForList().size(key);
409
} catch (Exception e) {
410
e.printStackTrace();
411
return 0;
412
}
413
}
414
415
/**
416
* 通过索引 获取list中的值
417
* @param key 键
418
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
419
* @return
420
*/
421
public Object lGetIndex(String key, long index) {
422
try {
423
return redisTemplate.opsForList().index(key, index);
424
} catch (Exception e) {
425
e.printStackTrace();
426
return null;
427
}
428
}
429
430
/**
431
* 将list放入缓存
432
* @param key 键
433
* @param value 值
434
* @param time 时间(秒)
435
* @return
436
*/
437
public boolean lSet(String key, Object value) {
438
try {
439
redisTemplate.opsForList().rightPush(key, value);
440
return true;
441
} catch (Exception e) {
442
e.printStackTrace();
443
return false;
444
}
445
}
446
447
/**
448
* 将list放入缓存
449
* @param key 键
450
* @param value 值
451
* @param time 时间(秒)
452
* @return
453
*/
454
public boolean lSet(String key, Object value, long time) {
455
try {
456
redisTemplate.opsForList().rightPush(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
/**
467
* 将list放入缓存
468
* @param key 键
469
* @param value 值
470
* @param time 时间(秒)
471
* @return
472
*/
473
public boolean lSet(String key, List<Object> value) {
474
try {
475
redisTemplate.opsForList().rightPushAll(key, value);
476
return true;
477
} catch (Exception e) {
478
e.printStackTrace();
479
return false;
480
}
481
}
482
483
/**
484
* 将list放入缓存
485
*
486
* @param key 键
487
* @param value 值
488
* @param time 时间(秒)
489
* @return
490
*/
491
public boolean lSet(String key, List<Object> value, long time) {
492
try {
493
redisTemplate.opsForList().rightPushAll(key, value);
494
if (time > 0)
495
expire(key, time);
496
return true;
497
} catch (Exception e) {
498
e.printStackTrace();
499
return false;
500
}
501
}
502
503
/**
504
* 根据索引修改list中的某条数据
505
* @param key 键
506
* @param index 索引
507
* @param value 值
508
* @return
509
*/
510
public boolean lUpdateIndex(String key, long index, Object value) {
511
try {
512
redisTemplate.opsForList().set(key, index, value);
513
return true;
514
} catch (Exception e) {
515
e.printStackTrace();
516
return false;
517
}
518
}
519
520
/**
521
* 移除N个值为value
522
* @param key 键
523
* @param count 移除多少个
524
* @param value 值
525
* @return 移除的个数
526
*/
527
public long lRemove(String key, long count, Object value) {
528
try {
529
Long remove = redisTemplate.opsForList().remove(key, count, value);
530
return remove;
531
} catch (Exception e) {
532
e.printStackTrace();
533
return 0;
534
}
535
}
536
}
最后
我这边整理了一份:Spring相关资料文档、Spring全家桶系列,Java的系统化资料,(包括Java核心知识点、面试专题和20年最新的互联网真题、电子书等)有需要的朋友可以私信回复【面试题】即可获取。
相关推荐
- 几种 TCP 连接中出现 RST 的情况
-
现在是一个网络时代了。应该不少程序员在编程中需要考虑多机、局域网、广域网的各种问题。所以网络知识也是避免不了学习的。而且笔者一直觉得TCP/IP网络知识在一个程序员知识体系中必需占有一席之地的。在...
- Redis连接使用报RDB error错误
-
该错误信息:Errorinexecution;nestedexceptionisio.lettuce.core.RedisCommandExecutionException:MISC...
- lua 语法介绍与 NGINX lua 高级用法实战操作
-
一、概述lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。官网:https://www.lua.org/二、l...
- Python教程——20.协程 - 2
-
异步编程asyncio.Future对象Task继承Future,Task对象内部中的await结果的处理基于Future对象来的在Future对象中会保存当前执行的这个协程任务的状态,如果当...
- “我的足迹”、“浏览历史”,Redis如何快速记录与展示?
-
咱们在网上“买买买”、“逛逛逛”的时候,总会留下各种各样的“足迹”。无论是电商APP里你最近浏览过的商品,视频网站上你刚刚看过的剧集,还是新闻客户端里你点开过的文章……这些“历史记录”,有时候还真挺有...
- 你手机上的“消息推送”,Redis可能参与其中
-
手机上那些时不时就“叮咚”一下的消息推送,确实是咱们数字生活里不可或缺的一部分。这篇咱们就来聊聊,Redis这位“消息灵通人士”,是如何在这场“信息接力赛”中大显身手,确保那些重要的、有趣的通知,能够...
- 短视频APP的“附近的人”,Redis如何快速匹配?
-
刷短视频,除了看各种搞笑段子、才艺展示,有时候是不是也想看看“同城”或者“附近”的人都在发些啥有意思的内容?或者,平台也会时不时地给你推荐一些“附近正在直播”的主播,让你感觉一下子拉近了和这个虚拟世界...
- 微信朋友圈的点赞、评论,Redis在背后默默付出
-
微信朋友圈,这片小小的“自留地”,承载了我们多少喜怒哀乐、生活点滴啊!一张精心修饰的照片,一段随感而发的文字,发出去之后,最期待的是什么?那必须是屏幕下方不断冒出来的小红心和一条条真诚(或者商业互吹)...
- 网站登录老是掉线?Redis帮你记住你是谁!
-
有没有过这样的糟心体验?你好不容易登录了一个网站,刚看了两篇帖子,或者购物车里刚加了几件宝贝,结果一刷新页面,或者稍微离开了一会儿,回来就发现——“哎?我怎么又退出了?!”又得重新输入用户名、密码、...
- 你常用的APP,哪些地方可能用到了Redis?(猜想与分析)
-
咱们现在的生活,简直是离不开各种各样的手机APP了!从早上睁眼刷新闻,到中午点外卖,再到晚上刷短视频、玩游戏,一天到头,指尖在屏幕上就没停过。这些APP为了让我们用得爽、用得顺心,背后可是使出了浑身解...
- Redis是啥?为啥程序员天天挂嘴边?小白也能看懂!
-
这Redis到底是何方神圣?为啥那些天天在电脑前敲代码的程序员小哥哥小姐姐们,老是把它挂在嘴边,好像离了它地球都不转了似的?别担心,咱们今天不说那些听了就头大的代码和术语,就用大白话,保证你听完一拍大...
- 面试官:请你说说Redis为什么这么快?
-
1)Redis是基于内存的存储数据库,绝大部分的命令处理只是纯粹的内存操作,内存的读写速度非常快。2)Redis是单进程线程的服务(实际上一个正在运行的RedisServer肯定不止一个线程,但只有...
- 有了强大的关系型数据库,为什么还需要Redis?
-
在数字世界的浩瀚海洋中,关系型数据库,例如我们熟知的MySQL、PostgreSQL或Oracle,无疑是那些承载着核心业务数据、坚如磐石的“国家图书馆”或“银行金库”。它们以严谨的结构、强大的事务处...
- Java 中间件数据可靠性串讲:从 MQ 、MySQL、Redis 不丢失的保障之道
-
引言在现代分布式系统中,中间件扮演着至关重要的角色,它们是构建高可用、高性能、高可扩展应用架构的基石。消息队列(MQ)、数据库(如MySQL)、缓存(如Redis)等是其中最具代表性的组件。然而,...
- 运维部署方式之——虚机部署
-
标准化使用作業系统:LinuxCentOS7自动化方式通过Ansible系统初始化playbook来管理。目的系统初始化工作是一个简单、繁复的工作,从云网得到的虚拟主机只是一个基础的系统环境,...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)