丝滑调用RedisTemplate客户端

632 阅读2分钟

背景

在使用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);
                });
    }



}