背景
在使用RedisTemplate的时候,有两个点让我头疼不已
- 其中key的管理,每次写冒号的时候,都需要一个单独的工具类对key进行拼接
- 成功获取数据时,另外的工具类转成对应的实体
能不能改动不需要太大,两个又都能兼容的方法呢。刚好最近又喜欢上了Builder链式编程的写法,又利用上了Java8中的新特性来完成一个RedisTemplate的调用工具
依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
RedisTemplate序列化
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
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.StringRedisSerializer;
/**
* RedisTemplate序列化
*
* @author 苦瓜不苦
* @date 2022/8/17 21:04
**/
@Configuration
public class RedisTemplateConfigurer {
/**
* 重写redis序列化方式,使用json方式
* 使用fastJson,避免出现双引号
*
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
FastJsonRedisSerializer<Object> fastJson = new FastJsonRedisSerializer<>(Object.class);
redisTemplate.setDefaultSerializer(fastJson);
redisTemplate.setConnectionFactory(redisConnectionFactory);
StringRedisSerializer serializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(serializer);
redisTemplate.setHashKeySerializer(serializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
RedisClient工具
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* RedisTemplate客户端
*
* @author 苦瓜不苦
* @date 2023/9/24 23:13
**/
@Component
public class SpringRedisClient {
/**
* 字符串结构-opsForValue
* hash结构-opsForValue
* cluster结构-opsForCluster
* geo结构-opsForGeo
* list结构-opsForList
* set结构-opsForSet
* zSet结构-opsForZSet
*/
private final RedisTemplate<String, Object> redisTemplate;
public SpringRedisClient(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public Builder builder() {
return new Builder(this.redisTemplate);
}
public static class Builder {
private final Source source;
private Object value;
public Builder(RedisTemplate<String, Object> redisTemplate) {
this.source = new Source(redisTemplate);
}
public Builder apply(Function<Source, Object> function) {
this.value = function.apply(this.source);
return this;
}
public Builder keys(Object... keys) {
StringBuilder builder = new StringBuilder();
for (Object key : keys) {
builder.append(key)
.append(":");
}
builder.deleteCharAt(builder.length() - 1);
this.source.key = builder.toString();
return this;
}
public void build(Consumer<Source> consumer) {
consumer.accept(this.source);
}
public Result build() {
return new Result(value);
}
}
public static class Source {
private String key;
private final RedisTemplate<String, Object> redisTemplate;
public Source(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public RedisTemplate<String, Object> redis() {
return redisTemplate;
}
public String key() {
return key;
}
}
public static class Result {
private final Object value;
public Result(Object value) {
this.value = value;
}
public boolean isNull() {
return Objects.isNull(this.value);
}
public boolean nonNull() {
return Objects.nonNull(this.value);
}
public String toJson() {
return isNull() ? null : this.value.toString();
}
public Boolean toBoolean() {
return isNull() ? null : Boolean.valueOf(this.value.toString());
}
public Integer toInteger() {
return isNull() ? null : Integer.valueOf(this.value.toString());
}
public Long toLong() {
return isNull() ? null : Long.valueOf(this.value.toString());
}
public <T> T toBean(Class<T> tClass) {
return isNull() ? null : JSONObject.parseObject(JSONObject.toJSONString(this.value), tClass);
}
public <T> List<T> toList(Class<T> tClass) {
return isNull() ? null : JSONArray.parseArray(JSONObject.toJSONString(this.value), tClass);
}
}
}
使用方式
使用方式分为两种,一种是调用apply()方法,有响应值的接收,可转化成对应的实体类。另外一种是build()方法,一般是作为设置key的有效期等,无响应值返回
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* @author 苦瓜不苦
* @date 2024/3/11 11:21
**/
@Slf4j
@SpringBootTest
public class LinkApiServerTest {
@Autowired
private SpringRedisClient redisClient;
/**
* 有响应值
*/
@Test
void test01() {
JSONObject result = redisClient.builder()
.keys("a", "b", "c", "d")
.apply(source -> {
if (Objects.equals(Boolean.TRUE, source.redis().hasKey(source.key()))) {
return source.redis().opsForValue().get(source.key());
}
return null;
}).build().toBean(JSONObject.class);
log.info("获取结果 {}", result);
}
/**
* 无响应值
*/
@Test
void test02() {
redisClient.builder()
.keys("a", "b", "c", "d")
.build(source -> {
source.redis().opsForValue().set(source.key(), "value", 10, TimeUnit.SECONDS);
});
}
}