Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
H
HYH.APSJ
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
佟礼
HYH.APSJ
Commits
ed06e909
Commit
ed06e909
authored
Dec 19, 2025
by
DESKTOP-VKRD9QF\Administration
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
redis 设置
parent
2a8e9ba8
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1264 additions
and
3 deletions
+1264
-3
pom.xml
pom.xml
+9
-2
RedisLockUtil.java
src/main/java/com/aps/common/util/redis/RedisLockUtil.java
+53
-0
RedisUtils.java
src/main/java/com/aps/common/util/redis/RedisUtils.java
+817
-0
RedisConfiguration.java
src/main/java/com/aps/config/RedisConfiguration.java
+64
-0
application.yml
src/main/resources/application.yml
+6
-1
RedisUtilsTest.java
src/test/java/com/aps/demo/RedisUtilsTest.java
+315
-0
No files found.
pom.xml
View file @
ed06e909
...
...
@@ -41,14 +41,21 @@
<artifactId>
dynamic-datasource-spring-boot-starter
</artifactId>
<version>
${dynamic-datasource.version}
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
<version>
2.0.33
</version>
</dependency>
<!-- 代码生成器 -->
<dependency>
<groupId>
com.baomidou
</groupId>
<artifactId>
mybatis-plus-generator
</artifactId>
<version>
${mybatis-plus.version}
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-data-redis
</artifactId>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupId>
org.apache.velocity
</groupId>
...
...
src/main/java/com/aps/common/util/redis/RedisLockUtil.java
0 → 100644
View file @
ed06e909
package
com
.
aps
.
common
.
util
.
redis
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.data.redis.connection.RedisStringCommands
;
import
org.springframework.data.redis.connection.ReturnType
;
import
org.springframework.data.redis.core.RedisCallback
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.types.Expiration
;
import
org.springframework.stereotype.Component
;
import
java.util.concurrent.TimeUnit
;
/**
* Redis分布式锁
*
* @author Administrator
*/
@Slf4j
@Component
@Import
(
RedisUtils
.
class
)
public
class
RedisLockUtil
{
public
RedisLockUtil
(
RedisTemplate
<
String
,
Object
>
redisTemplate
)
{
this
.
redisTemplate
=
redisTemplate
;
}
private
RedisTemplate
<
String
,
Object
>
redisTemplate
;
private
static
final
byte
[]
SCRIPT_RELEASE_LOCK
=
"if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"
.
getBytes
();
/**
* 尝试获取分布式锁
*
* @param key 键
* @param requestId 请求ID
* @param expire 锁的有效时间(秒)
*/
public
Boolean
tryLock
(
String
key
,
String
requestId
,
long
expire
)
{
return
redisTemplate
.
execute
((
RedisCallback
<
Boolean
>)
redisConnection
->
redisConnection
.
set
(
key
.
getBytes
(),
requestId
.
getBytes
(),
Expiration
.
from
(
expire
,
TimeUnit
.
SECONDS
),
RedisStringCommands
.
SetOption
.
SET_IF_ABSENT
));
}
/**
* 释放分布式锁
*
* @param key 键
* @param requestId 请求ID
*/
public
Boolean
releaseLock
(
String
key
,
String
requestId
)
{
return
redisTemplate
.
execute
((
RedisCallback
<
Boolean
>)
redisConnection
->
redisConnection
.
eval
(
SCRIPT_RELEASE_LOCK
,
ReturnType
.
BOOLEAN
,
1
,
key
.
getBytes
(),
requestId
.
getBytes
()));
}
}
\ No newline at end of file
src/main/java/com/aps/common/util/redis/RedisUtils.java
0 → 100644
View file @
ed06e909
package
com
.
aps
.
common
.
util
.
redis
;
import
com.alibaba.fastjson2.JSONObject
;
import
lombok.Getter
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.dao.DataAccessException
;
import
org.springframework.data.redis.connection.RedisConnection
;
import
org.springframework.data.redis.core.RedisCallback
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.TimeoutUtils
;
import
org.springframework.data.redis.serializer.RedisSerializer
;
import
org.springframework.data.redis.serializer.SerializationUtils
;
import
org.springframework.util.Assert
;
import
java.time.Duration
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
import
java.util.stream.Collectors
;
/**
* 或者使用${@link RedisUtils#setPrefix(String)} 设置统一的key前缀
* 1. Key的命名应该具有可读性,方便开发者理解和维护。可以使用类似于命名空间的方式,将相关的key放在同一个前缀下,例如"user:id"和"order:id"。
* <p>
* 2. Key的命名应该尽量简短,以减少内存占用和提高查询效率。
* <p>
* 3. Key的命名应该避免使用特殊字符和空格,可以使用下划线或者破折号代替。
* <p>
* 4. Key的命名应该避免使用过于具体的词汇,例如"order:2021-01-01:customer:123",应该改为"order:123",并将日期信息存储在其他字段中。
*
* @author guojing
*/
@Slf4j
public
class
RedisUtils
{
@Autowired
@SuppressWarnings
(
"all"
)
private
RedisTemplate
<
String
,
Object
>
redisTemplate
;
@Autowired
private
RedisLockUtil
redisLockUtil
;
/**
* 所有key的前缀
*/
@Getter
public
static
String
prefix
=
"aps:"
;
/**
* 设置redis前缀进行操作
*
* @param prefix
*/
public
static
void
setPrefix
(
String
prefix
)
{
RedisUtils
.
prefix
=
prefix
;
}
/**
* 判断是否有这个缓存key
*
* @param key 缓存key
* @author: guojing
* @return: boolean
*/
public
boolean
exists
(
final
String
key
)
{
return
redisTemplate
.
hasKey
(
prefix
+
key
);
}
public
Set
<
String
>
keys
(
final
String
pattern
)
{
return
redisTemplate
.
keys
(
prefix
+
pattern
);
}
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return Boolean
*/
public
void
expire
(
String
key
,
int
time
,
TimeUnit
timeUnit
)
{
redisTemplate
.
expire
(
prefix
+
key
,
time
,
timeUnit
);
}
public
Boolean
expire
(
String
key
,
Long
time
)
{
try
{
if
(
time
>
0
)
{
redisTemplate
.
expire
(
prefix
+
key
,
time
,
TimeUnit
.
SECONDS
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 添加到带有 过期时间的 缓存
*
* @param key redis主键
* @param value 值
* @param time 过期时间
* @param timeUnit 过期时间单位
*/
public
void
setExpire
(
final
String
key
,
final
Object
value
,
final
long
time
,
final
TimeUnit
timeUnit
)
{
redisTemplate
.
opsForValue
().
set
(
prefix
+
key
,
value
,
time
,
timeUnit
);
}
public
void
setExpire
(
final
String
key
,
final
Object
value
,
final
long
time
,
final
TimeUnit
timeUnit
,
RedisSerializer
<
Object
>
valueSerializer
)
{
byte
[]
rawKey
=
rawKey
(
prefix
+
key
);
byte
[]
rawValue
=
rawValue
(
value
,
valueSerializer
);
redisTemplate
.
execute
(
new
RedisCallback
<
Object
>()
{
@Override
public
Object
doInRedis
(
RedisConnection
connection
)
throws
DataAccessException
{
potentiallyUsePsetEx
(
connection
);
return
null
;
}
public
void
potentiallyUsePsetEx
(
RedisConnection
connection
)
{
if
(!
TimeUnit
.
MILLISECONDS
.
equals
(
timeUnit
)
||
!
failsafeInvokePsetEx
(
connection
))
{
connection
.
setEx
(
rawKey
,
TimeoutUtils
.
toSeconds
(
time
,
timeUnit
),
rawValue
);
}
}
private
boolean
failsafeInvokePsetEx
(
RedisConnection
connection
)
{
boolean
failed
=
false
;
try
{
connection
.
pSetEx
(
rawKey
,
time
,
rawValue
);
}
catch
(
UnsupportedOperationException
e
)
{
failed
=
true
;
}
return
!
failed
;
}
},
true
);
}
/**
* 根据key获取过期时间
*
* @param key 键 不能为 null
* @return 时间(秒) 返回 0代表为永久有效
*/
public
Long
getExpire
(
String
key
)
{
return
redisTemplate
.
getExpire
(
prefix
+
key
,
TimeUnit
.
SECONDS
);
}
/**
* 判断 key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public
Boolean
hasKey
(
String
key
)
{
try
{
return
redisTemplate
.
hasKey
(
prefix
+
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
public
void
del
(
String
...
key
)
{
if
(
key
!=
null
&&
key
.
length
>
0
)
{
if
(
key
.
length
==
1
)
{
redisTemplate
.
delete
(
prefix
+
key
[
0
]);
}
else
{
redisTemplate
.
delete
(
Arrays
.
asList
(
key
).
stream
().
map
(
e
->
prefix
+
e
).
collect
(
Collectors
.
toList
()));
}
}
}
public
void
del
(
Collection
<
String
>
keys
)
{
redisTemplate
.
delete
(
keys
.
stream
().
map
(
e
->
prefix
+
e
).
collect
(
Collectors
.
toList
()));
}
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public
Object
get
(
String
key
)
{
return
key
==
null
?
null
:
redisTemplate
.
opsForValue
().
get
(
prefix
+
key
);
}
/**
* 根据key获取对象
*
* @param key the key
* @param valueSerializer 序列化
* @return the string
*/
public
Object
get
(
final
String
key
,
RedisSerializer
<
Object
>
valueSerializer
)
{
byte
[]
rawKey
=
rawKey
(
prefix
+
key
);
return
redisTemplate
.
execute
(
connection
->
deserializeValue
(
connection
.
get
(
rawKey
),
valueSerializer
),
true
);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public
Boolean
set
(
String
key
,
Object
value
)
{
try
{
redisTemplate
.
opsForValue
().
set
(
prefix
+
key
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public
Boolean
set
(
String
key
,
Object
value
,
Long
time
)
{
try
{
if
(
time
>
0
)
{
redisTemplate
.
opsForValue
().
set
(
prefix
+
key
,
value
,
time
,
TimeUnit
.
SECONDS
);
}
else
{
set
(
key
,
value
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @return true成功 false 失败
*/
public
Boolean
set
(
String
key
,
Object
value
,
Duration
timeout
)
{
try
{
Assert
.
notNull
(
timeout
,
"Timeout must not be null!"
);
if
(
TimeoutUtils
.
hasMillis
(
timeout
))
{
redisTemplate
.
opsForValue
().
set
(
prefix
+
key
,
value
,
timeout
.
toMillis
(),
TimeUnit
.
MILLISECONDS
);
}
else
{
redisTemplate
.
opsForValue
().
set
(
prefix
+
key
,
value
,
timeout
.
getSeconds
(),
TimeUnit
.
SECONDS
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 递增
*
* @param key 键
* @param delta 要增加几(大于0)
* @return Long
*/
public
Long
incr
(
String
key
,
Long
delta
)
{
return
redisTemplate
.
opsForValue
().
increment
(
prefix
+
key
,
delta
);
}
/**
* 递减
*
* @param key 键
* @param delta 要减少几(小于0)
* @return Long
*/
public
Long
decr
(
String
key
,
Long
delta
)
{
return
redisTemplate
.
opsForValue
().
increment
(
prefix
+
key
,
-
delta
);
}
/**
* HashGet
*
* @param key 键 不能为 null
* @param item 项 不能为 null
* @return 值
*/
public
Object
hget
(
String
key
,
String
item
)
{
return
redisTemplate
.
opsForHash
().
get
(
prefix
+
key
,
item
);
}
/**
* 获取 hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public
Map
<
Object
,
Object
>
hmget
(
String
key
)
{
return
redisTemplate
.
opsForHash
().
entries
(
prefix
+
key
);
}
/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public
Boolean
hmset
(
String
key
,
Map
<
String
,
Object
>
map
)
{
try
{
redisTemplate
.
opsForHash
().
putAll
(
prefix
+
key
,
map
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* HashSet 并设置时间
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public
Boolean
hmset
(
String
key
,
Map
<
String
,
Object
>
map
,
Long
time
)
{
try
{
redisTemplate
.
opsForHash
().
putAll
(
prefix
+
key
,
map
);
if
(
time
>
0
)
{
expire
(
key
,
time
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public
Boolean
hset
(
String
key
,
String
item
,
Object
value
)
{
try
{
redisTemplate
.
opsForHash
().
put
(
prefix
+
key
,
item
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public
Boolean
hset
(
String
key
,
String
item
,
Object
value
,
Long
time
)
{
try
{
redisTemplate
.
opsForHash
().
put
(
prefix
+
key
,
item
,
value
);
if
(
time
>
0
)
{
expire
(
key
,
time
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 删除hash表中的值
*
* @param key 键 不能为 null
* @param item 项 可以使多个不能为 null
*/
public
void
hdel
(
String
key
,
Object
...
item
)
{
redisTemplate
.
opsForHash
().
delete
(
prefix
+
key
,
item
);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为 null
* @param item 项 不能为 null
* @return true 存在 false不存在
*/
public
Boolean
hHasKey
(
String
key
,
String
item
)
{
return
redisTemplate
.
opsForHash
().
hasKey
(
prefix
+
key
,
item
);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
* @return Double
*/
public
Double
hincr
(
String
key
,
String
item
,
Double
by
)
{
return
redisTemplate
.
opsForHash
().
increment
(
prefix
+
key
,
item
,
by
);
}
/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
* @return Double
*/
public
Double
hdecr
(
String
key
,
String
item
,
Double
by
)
{
return
redisTemplate
.
opsForHash
().
increment
(
prefix
+
key
,
item
,
-
by
);
}
/**
* 根据 key获取 Set中的所有值
*
* @param key 键
* @return Set
*/
public
Set
<
Object
>
sGet
(
String
key
)
{
try
{
return
redisTemplate
.
opsForSet
().
members
(
prefix
+
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
null
;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public
Boolean
sHasKey
(
String
key
,
Object
value
)
{
try
{
return
redisTemplate
.
opsForSet
().
isMember
(
prefix
+
key
,
value
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public
Long
sSet
(
String
key
,
Object
...
values
)
{
try
{
return
redisTemplate
.
opsForSet
().
add
(
prefix
+
key
,
values
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
0L
;
}
}
/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public
Long
sSetAndTime
(
String
key
,
Long
time
,
Object
...
values
)
{
try
{
Long
count
=
redisTemplate
.
opsForSet
().
add
(
prefix
+
key
,
values
);
if
(
time
>
0
)
{
expire
(
key
,
time
);
}
return
count
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
0L
;
}
}
/**
* 获取set缓存的长度
*
* @param key 键
* @return Long
*/
public
Long
sGetSetSize
(
String
key
)
{
try
{
return
redisTemplate
.
opsForSet
().
size
(
prefix
+
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
0L
;
}
}
/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public
Long
setRemove
(
String
key
,
Object
...
values
)
{
try
{
return
redisTemplate
.
opsForSet
().
remove
(
prefix
+
key
,
values
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
0L
;
}
}
/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return List
*/
public
List
<
Object
>
lGet
(
String
key
,
int
start
,
int
end
)
{
try
{
return
redisTemplate
.
opsForList
().
range
(
prefix
+
key
,
start
,
end
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
null
;
}
}
/**
* 获取list缓存的长度
*
* @param key 键
* @return Long
*/
public
Long
lGetListSize
(
String
key
)
{
try
{
return
redisTemplate
.
opsForList
().
size
(
prefix
+
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
0L
;
}
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;
* index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return Object
*/
public
Object
lGetIndex
(
String
key
,
Long
index
)
{
try
{
return
redisTemplate
.
opsForList
().
index
(
prefix
+
key
,
index
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
null
;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return Boolean
*/
public
Boolean
lSet
(
String
key
,
Object
value
)
{
try
{
redisTemplate
.
opsForSet
().
add
(
prefix
+
key
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return Boolean
*/
public
Boolean
lSet
(
String
key
,
Object
value
,
Long
time
)
{
try
{
redisTemplate
.
opsForSet
().
add
(
prefix
+
key
,
value
);
if
(
time
>
0
)
{
expire
(
key
,
time
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 往list头部插入值
*
* @param key 键
* @param value 值
* @return Boolean
*/
public
Boolean
lSetList
(
String
key
,
Object
value
)
{
try
{
redisTemplate
.
opsForList
().
leftPush
(
prefix
+
key
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 往list尾部插入值
*
* @param key 键
* @param value 值
* @return Boolean
*/
public
Boolean
lSetListRight
(
String
key
,
Object
value
)
{
try
{
redisTemplate
.
opsForList
().
rightPush
(
prefix
+
key
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
public
List
<
Object
>
getSetList
(
String
key
)
{
try
{
return
redisTemplate
.
opsForList
().
range
(
prefix
+
key
,
0
,
-
1
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
new
ArrayList
<>();
}
}
public
List
<
Object
>
getSetList
(
String
key
,
long
start
,
long
end
)
{
try
{
return
redisTemplate
.
opsForList
().
range
(
prefix
+
key
,
start
,
end
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
new
ArrayList
<>();
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return Boolean
*/
public
Boolean
lSetList
(
String
key
,
List
<
Object
>
value
)
{
try
{
redisTemplate
.
opsForList
().
rightPushAll
(
prefix
+
key
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return Boolean
*/
public
Boolean
lSet
(
String
key
,
List
<
Object
>
value
,
Long
time
)
{
try
{
redisTemplate
.
opsForList
().
rightPushAll
(
prefix
+
key
,
value
);
if
(
time
>
0
)
{
expire
(
key
,
time
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return Boolean
*/
public
Boolean
lUpdateIndex
(
String
key
,
Long
index
,
Object
value
)
{
try
{
redisTemplate
.
opsForList
().
set
(
prefix
+
key
,
index
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
false
;
}
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public
Long
lRemove
(
String
key
,
Long
count
,
Object
value
)
{
try
{
return
redisTemplate
.
opsForList
().
remove
(
prefix
+
key
,
count
,
value
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Exception: {}"
,
e
.
getMessage
());
return
0L
;
}
}
/**
* redis List数据结构 : 返回列表 key 中指定区间内的元素,区间以偏移量 start 和 end 指定。
*
* @param key the key
* @param start the start
* @param end the end
* @param valueSerializer 序列化
* @return the list
*/
public
List
<
Object
>
getList
(
String
key
,
int
start
,
int
end
,
RedisSerializer
<
Object
>
valueSerializer
)
{
byte
[]
rawKey
=
rawKey
(
prefix
+
key
);
return
redisTemplate
.
execute
(
connection
->
deserializeValues
(
connection
.
lRange
(
rawKey
,
start
,
end
),
valueSerializer
),
true
);
}
private
byte
[]
rawKey
(
Object
key
)
{
Assert
.
notNull
(
key
,
"non null key required"
);
if
(
key
instanceof
byte
[])
{
return
(
byte
[])
key
;
}
RedisSerializer
<
Object
>
redisSerializer
=
(
RedisSerializer
<
Object
>)
redisTemplate
.
getKeySerializer
();
return
redisSerializer
.
serialize
(
key
);
}
private
byte
[]
rawValue
(
Object
value
,
RedisSerializer
valueSerializer
)
{
if
(
value
instanceof
byte
[])
{
return
(
byte
[])
value
;
}
return
valueSerializer
.
serialize
(
value
);
}
private
List
deserializeValues
(
List
<
byte
[]>
rawValues
,
RedisSerializer
<
Object
>
valueSerializer
)
{
if
(
valueSerializer
==
null
)
{
return
rawValues
;
}
return
SerializationUtils
.
deserialize
(
rawValues
,
valueSerializer
);
}
private
Object
deserializeValue
(
byte
[]
value
,
RedisSerializer
<
Object
>
valueSerializer
)
{
if
(
valueSerializer
==
null
)
{
return
value
;
}
return
valueSerializer
.
deserialize
(
value
);
}
public
void
publish
(
String
channal
,
Object
obj
)
{
redisTemplate
.
convertAndSend
(
channal
,
JSONObject
.
toJSONString
(
obj
));
}
public
void
publish
(
String
channal
,
String
obj
)
{
redisTemplate
.
convertAndSend
(
channal
,
obj
);
}
/**
* 分布式锁
*
* @param key 分布式锁key
* @param expireTime 持有锁的最长时间 (redis过期时间) 秒为单位
* @return 返回获取锁状态 成功失败
*/
public
boolean
tryLock
(
String
key
,
int
expireTime
)
{
final
JSONObject
lock
=
new
JSONObject
();
lock
.
put
(
"id"
,
key
);
// startTime
lock
.
put
(
"st"
,
System
.
currentTimeMillis
());
// keepSeconds
lock
.
put
(
"ks"
,
expireTime
);
return
redisLockUtil
.
tryLock
(
prefix
+
key
,
""
,
expireTime
);
}
public
void
unLock
(
String
key
)
{
redisLockUtil
.
releaseLock
(
prefix
+
key
,
""
);
}
}
src/main/java/com/aps/config/RedisConfiguration.java
0 → 100644
View file @
ed06e909
package
com
.
aps
.
config
;
import
com.fasterxml.jackson.annotation.JsonAutoDetect
;
import
com.fasterxml.jackson.annotation.PropertyAccessor
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.cache.annotation.EnableCaching
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Lazy
;
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.RedisSerializer
;
import
org.springframework.data.redis.serializer.StringRedisSerializer
;
/**
* Redis基础配置类
*
* @author pangu
*/
@Configuration
@Lazy
(
value
=
false
)
@EnableCaching
public
class
RedisConfiguration
{
@Bean
@ConditionalOnMissingBean
public
RedisSerializer
<
String
>
redisKeySerializer
()
{
return
new
Jackson2JsonRedisSerializer
(
String
.
class
);
}
@Bean
@ConditionalOnMissingBean
public
RedisSerializer
<
Object
>
redisValueSerializer
()
{
return
new
Jackson2JsonRedisSerializer
(
Object
.
class
);
}
@Bean
public
RedisTemplate
redisTemplate
(
RedisConnectionFactory
factory
)
{
RedisTemplate
template
=
new
RedisTemplate
();
//LettuceConnectionFactory
template
.
setConnectionFactory
(
factory
);
Jackson2JsonRedisSerializer
<
Object
>
jackson2JsonRedisSerializer
=
new
Jackson2JsonRedisSerializer
<
Object
>(
Object
.
class
);
ObjectMapper
om
=
new
ObjectMapper
();
om
.
setVisibility
(
PropertyAccessor
.
ALL
,
JsonAutoDetect
.
Visibility
.
ANY
);
om
.
activateDefaultTyping
(
om
.
getPolymorphicTypeValidator
(),
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
;
}
}
src/main/resources/application.yml
View file @
ed06e909
...
...
@@ -9,7 +9,12 @@ spring:
mvc
:
pathmatch
:
matching-strategy
:
ant_path_matcher
# Spring Boot 2.6+ 需要这个配置
redis
:
host
:
192.168.0.181
port
:
6380
timeout
:
10000
database
:
10
password
:
redis@228!
# Swagger 配置
doc
:
swagger-ui
:
...
...
src/test/java/com/aps/demo/RedisUtilsTest.java
0 → 100644
View file @
ed06e909
package
com
.
aps
.
demo
;
import
com.aps.common.util.redis.RedisUtils
;
import
org.junit.jupiter.api.BeforeEach
;
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
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.*;
@SpringBootTest
public
class
RedisUtilsTest
{
@Autowired
private
RedisUtils
redisUtils
;
@Autowired
private
RedisTemplate
<
String
,
Object
>
redisTemplate
;
@BeforeEach
void
setUp
()
{
// 清理可能存在的测试数据
Set
<
String
>
keys
=
redisTemplate
.
keys
(
"jvs:test:*"
);
if
(
keys
!=
null
&&
!
keys
.
isEmpty
())
{
redisTemplate
.
delete
(
keys
);
}
}
@Test
public
void
testSetAndGet
()
{
String
key
=
"test:setAndGet"
;
String
value
=
"testValue"
;
// 测试设置值
Boolean
setResult
=
redisUtils
.
set
(
key
,
value
);
assertTrue
(
setResult
,
"设置值应该成功"
);
// 测试获取值
Object
getResult
=
redisUtils
.
get
(
key
);
assertEquals
(
value
,
getResult
,
"获取的值应该与设置的值相同"
);
System
.
out
.
println
(
"获取的值:"
+
getResult
);
}
@Test
public
void
testSetWithExpire
()
{
String
key
=
"test:setWithExpire"
;
String
value
=
"testValue"
;
Long
expireTime
=
5L
;
// 测试设置带过期时间的值
Boolean
setResult
=
redisUtils
.
set
(
key
,
value
,
expireTime
);
assertTrue
(
setResult
,
"设置带过期时间的值应该成功"
);
// 验证值存在
Object
getResult
=
redisUtils
.
get
(
key
);
assertEquals
(
value
,
getResult
,
"获取的值应该与设置的值相同"
);
// 验证过期时间
Long
ttl
=
redisUtils
.
getExpire
(
key
);
assertTrue
(
ttl
>
0
&&
ttl
<=
expireTime
,
"过期时间应该在预期范围内"
);
}
@Test
public
void
testExistsAndHasKey
()
{
String
key
=
"test:exists"
;
String
value
=
"testValue"
;
// 初始状态下key不存在
assertFalse
(
redisUtils
.
exists
(
key
),
"初始状态下key不应该存在"
);
assertFalse
(
redisUtils
.
hasKey
(
key
),
"初始状态下key不应该存在"
);
// 设置值后key应该存在
redisUtils
.
set
(
key
,
value
);
assertTrue
(
redisUtils
.
exists
(
key
),
"设置值后key应该存在"
);
assertTrue
(
redisUtils
.
hasKey
(
key
),
"设置值后key应该存在"
);
}
@Test
public
void
testDel
()
{
String
key
=
"test:del"
;
String
value
=
"testValue"
;
// 设置值
redisUtils
.
set
(
key
,
value
);
assertTrue
(
redisUtils
.
exists
(
key
),
"设置值后key应该存在"
);
// 删除值
redisUtils
.
del
(
key
);
assertFalse
(
redisUtils
.
exists
(
key
),
"删除后key不应该存在"
);
// 测试批量删除
String
key1
=
"test:del1"
;
String
key2
=
"test:del2"
;
redisUtils
.
set
(
key1
,
value
);
redisUtils
.
set
(
key2
,
value
);
assertTrue
(
redisUtils
.
exists
(
key1
),
"设置值后key1应该存在"
);
assertTrue
(
redisUtils
.
exists
(
key2
),
"设置值后key2应该存在"
);
redisUtils
.
del
(
key1
,
key2
);
assertFalse
(
redisUtils
.
exists
(
key1
),
"批量删除后key1不应该存在"
);
assertFalse
(
redisUtils
.
exists
(
key2
),
"批量删除后key2不应该存在"
);
}
@Test
public
void
testExpire
()
{
String
key
=
"test:expire"
;
String
value
=
"testValue"
;
int
expireTime
=
10
;
redisUtils
.
set
(
key
,
value
);
redisUtils
.
expire
(
key
,
expireTime
,
TimeUnit
.
SECONDS
);
Long
ttl
=
redisUtils
.
getExpire
(
key
);
assertTrue
(
ttl
>
0
&&
ttl
<=
expireTime
,
"过期时间应该在预期范围内"
);
}
@Test
public
void
testKeys
()
{
String
key1
=
"test:keys1"
;
String
key2
=
"test:keys2"
;
String
value
=
"testValue"
;
redisUtils
.
set
(
key1
,
value
);
redisUtils
.
set
(
key2
,
value
);
Set
<
String
>
keys
=
redisUtils
.
keys
(
"test:keys*"
);
assertNotNull
(
keys
,
"返回的keys不应该为null"
);
assertTrue
(
keys
.
contains
(
"jvs:test:keys1"
),
"应该包含key1"
);
assertTrue
(
keys
.
contains
(
"jvs:test:keys2"
),
"应该包含key2"
);
}
@Test
public
void
testIncrAndDecr
()
{
String
key
=
"test:incrdecr"
;
Long
initialValue
=
10L
;
Long
delta
=
5L
;
redisUtils
.
set
(
key
,
initialValue
);
// 测试递增
Long
incrResult
=
redisUtils
.
incr
(
key
,
delta
);
assertEquals
(
initialValue
+
delta
,
incrResult
,
"递增结果应该正确"
);
// 测试递减
Long
decrResult
=
redisUtils
.
decr
(
key
,
delta
);
assertEquals
(
initialValue
,
decrResult
,
"递减结果应该正确"
);
}
@Test
public
void
testHashSetAndGet
()
{
String
key
=
"test:hash"
;
String
item1
=
"item1"
;
String
item2
=
"item2"
;
String
value1
=
"value1"
;
String
value2
=
"value2"
;
// 测试单个hash设置和获取
Boolean
hsetResult
=
redisUtils
.
hset
(
key
,
item1
,
value1
);
assertTrue
(
hsetResult
,
"Hash设置应该成功"
);
Object
hgetResult
=
redisUtils
.
hget
(
key
,
item1
);
assertEquals
(
value1
,
hgetResult
,
"Hash获取的值应该正确"
);
// 测试多个hash设置和获取
Map
<
String
,
Object
>
map
=
new
HashMap
<>();
map
.
put
(
item1
,
value1
);
map
.
put
(
item2
,
value2
);
Boolean
hmsetResult
=
redisUtils
.
hmset
(
key
,
map
);
assertTrue
(
hmsetResult
,
"批量Hash设置应该成功"
);
Map
<
Object
,
Object
>
hmgetResult
=
redisUtils
.
hmget
(
key
);
assertNotNull
(
hmgetResult
,
"批量Hash获取结果不应该为null"
);
assertEquals
(
value1
,
hmgetResult
.
get
(
item1
),
"Hash获取的值应该正确"
);
assertEquals
(
value2
,
hmgetResult
.
get
(
item2
),
"Hash获取的值应该正确"
);
// 测试hash是否存在
Boolean
hHasKeyResult
=
redisUtils
.
hHasKey
(
key
,
item1
);
assertTrue
(
hHasKeyResult
,
"Hash key应该存在"
);
}
@Test
public
void
testHashDelAndIncr
()
{
String
key
=
"test:hashdel"
;
String
item
=
"item"
;
String
value
=
"10"
;
redisUtils
.
hset
(
key
,
item
,
value
);
// 测试hash删除
redisUtils
.
hdel
(
key
,
item
);
Boolean
hHasKeyResult
=
redisUtils
.
hHasKey
(
key
,
item
);
assertFalse
(
hHasKeyResult
,
"删除后Hash key不应该存在"
);
// 测试hash递增
String
incrItem
=
"incrItem"
;
Double
incrValue
=
5.0
;
Double
hincrResult
=
redisUtils
.
hincr
(
key
,
incrItem
,
incrValue
);
assertEquals
(
incrValue
,
hincrResult
,
"Hash递增结果应该正确"
);
// 测试hash递减
Double
decrValue
=
3.0
;
Double
hdecrResult
=
redisUtils
.
hdecr
(
key
,
incrItem
,
decrValue
);
assertEquals
(
incrValue
-
decrValue
,
hdecrResult
,
"Hash递减结果应该正确"
);
}
@Test
public
void
testSetOperations
()
{
String
key
=
"test:set"
;
String
value1
=
"value1"
;
String
value2
=
"value2"
;
// 测试添加set元素
Long
sSetResult
=
redisUtils
.
sSet
(
key
,
value1
,
value2
);
assertEquals
(
2
,
sSetResult
,
"应该成功添加2个元素"
);
// 测试set大小
Long
sGetSizeResult
=
redisUtils
.
sGetSetSize
(
key
);
assertEquals
(
2
,
sGetSizeResult
,
"Set大小应该为2"
);
// 测试元素是否存在于set中
Boolean
sHasKeyResult
=
redisUtils
.
sHasKey
(
key
,
value1
);
assertTrue
(
sHasKeyResult
,
"value1应该存在于set中"
);
// 测试获取set所有元素
Set
<
Object
>
sGetResult
=
redisUtils
.
sGet
(
key
);
assertNotNull
(
sGetResult
,
"Set结果不应该为null"
);
assertTrue
(
sGetResult
.
contains
(
value1
),
"Set应该包含value1"
);
assertTrue
(
sGetResult
.
contains
(
value2
),
"Set应该包含value2"
);
// 测试从set中移除元素
Long
setRemoveResult
=
redisUtils
.
setRemove
(
key
,
value1
);
assertEquals
(
1
,
setRemoveResult
,
"应该成功移除1个元素"
);
sGetSizeResult
=
redisUtils
.
sGetSetSize
(
key
);
assertEquals
(
1
,
sGetSizeResult
,
"移除元素后Set大小应该为1"
);
}
@Test
public
void
testListOperations
()
{
String
key
=
"test:list"
;
String
value1
=
"value1"
;
String
value2
=
"value2"
;
String
value3
=
"value3"
;
// 测试往list头部插入值
Boolean
lSetListResult
=
redisUtils
.
lSetList
(
key
,
value1
);
assertTrue
(
lSetListResult
,
"往list头部插入值应该成功"
);
// 测试往list尾部插入值
Boolean
lSetListRightResult
=
redisUtils
.
lSetListRight
(
key
,
value2
);
assertTrue
(
lSetListRightResult
,
"往list尾部插入值应该成功"
);
// 测试获取list长度
Long
lGetListSizeResult
=
redisUtils
.
lGetListSize
(
key
);
assertEquals
(
2
,
lGetListSizeResult
,
"List长度应该为2"
);
// 测试通过索引获取list中的值
Object
lGetIndexResult
=
redisUtils
.
lGetIndex
(
key
,
0L
);
assertEquals
(
value1
,
lGetIndexResult
,
"索引0的值应该是value1"
);
lGetIndexResult
=
redisUtils
.
lGetIndex
(
key
,
-
1L
);
assertEquals
(
value2
,
lGetIndexResult
,
"索引-1的值应该是value2"
);
// 测试获取list缓存内容
List
<
Object
>
lGetResult
=
redisUtils
.
lGet
(
key
,
0
,
-
1
);
assertNotNull
(
lGetResult
,
"List结果不应该为null"
);
assertEquals
(
2
,
lGetResult
.
size
(),
"List大小应该为2"
);
assertEquals
(
value1
,
lGetResult
.
get
(
0
),
"第一个元素应该是value1"
);
assertEquals
(
value2
,
lGetResult
.
get
(
1
),
"第二个元素应该是value2"
);
// 测试批量设置list
List
<
Object
>
values
=
Arrays
.
asList
(
value1
,
value2
,
value3
);
Boolean
lSetListBatchResult
=
redisUtils
.
lSetList
(
key
,
values
);
assertTrue
(
lSetListBatchResult
,
"批量设置list应该成功"
);
lGetListSizeResult
=
redisUtils
.
lGetListSize
(
key
);
assertEquals
(
3
,
lGetListSizeResult
,
"批量设置后List长度应该为3"
);
// 测试根据索引修改list中的某条数据
String
newValue
=
"newValue"
;
Boolean
lUpdateIndexResult
=
redisUtils
.
lUpdateIndex
(
key
,
0L
,
newValue
);
assertTrue
(
lUpdateIndexResult
,
"根据索引修改list数据应该成功"
);
lGetIndexResult
=
redisUtils
.
lGetIndex
(
key
,
0L
);
assertEquals
(
newValue
,
lGetIndexResult
,
"索引0的值应该被更新"
);
// 测试移除N个值为value的元素
Long
lRemoveResult
=
redisUtils
.
lRemove
(
key
,
1L
,
value2
);
assertEquals
(
1
,
lRemoveResult
,
"应该成功移除1个元素"
);
}
@Test
public
void
testPrefix
()
{
String
originalPrefix
=
RedisUtils
.
getPrefix
();
String
newPrefix
=
"test_prefix:"
;
// 修改前缀
RedisUtils
.
setPrefix
(
newPrefix
);
assertEquals
(
newPrefix
,
RedisUtils
.
getPrefix
(),
"前缀应该被正确设置"
);
// 测试使用新前缀的操作
String
key
=
"test:prefix"
;
String
value
=
"testValue"
;
RedisUtils
redisUtilsWithoutAutowired
=
new
RedisUtils
();
// 恢复原始前缀
RedisUtils
.
setPrefix
(
originalPrefix
);
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment