All Downloads are FREE. Search and download functionalities are using the official Maven repository.

group.rober.base.adapter.SpringRedisCache Maven / Gradle / Ivy

package group.rober.base.adapter;


import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.*;

public class SpringRedisCache extends RedisCache implements ShiroCacheParitalInterface{
    private final byte[] WILD_CARD = new StringRedisSerializer().serialize("*");
    private final boolean usePrefix;
    private final byte[] prefix;
    private final byte[] setOfKnownKeys;
    private final RedisOperations redisOperations;

    public SpringRedisCache(String name, byte[] prefix, RedisOperations redisOperations,
                            long expiration) {
        super(name, prefix, redisOperations, expiration);
        this.redisOperations = redisOperations;
        this.usePrefix = prefix != null && prefix.length > 0;
        this.prefix = prefix;
        this.setOfKnownKeys = usePrefix ? new byte[] {} : new StringRedisSerializer().serialize(name + "~keys");
    }


    public SpringRedisCache(String name, byte[] prefix, RedisOperations redisOperations,
                            long expiration, boolean allowNullValues) {
        super(name, prefix, redisOperations, expiration, allowNullValues);
        this.redisOperations = redisOperations;
        this.usePrefix = prefix != null && prefix.length > 0;
        this.prefix = prefix;
        this.setOfKnownKeys = usePrefix ? new byte[] {} : new StringRedisSerializer().serialize(name + "~keys");
    }

    public boolean isUsePrefix() {
        return usePrefix;
    }

    @Override
    public int size() {
        if(usePrefix)
            return (Integer) redisOperations.execute(new RedisKeySizeByPrefixCallback());
        else
            return (Integer) redisOperations.execute(new RedisKeySizeByKeysCallback());
    }

    @Override
    public Set keys() {
        if(usePrefix)
            return (Set)redisOperations.execute(new RedisKeysByPrefixCallback());
        else
            return (Set)redisOperations.execute(new RedisKeysByKeysCallback());
    }

    @Override
    public Collection values() {
        @SuppressWarnings({"unchecked"})
        Set keys = (Set)redisOperations.execute(new RedisCallback>() {
            @Override
            public Set doInRedis(RedisConnection connection) throws DataAccessException {
                if (usePrefix) {
                    byte[] prefixToUse = Arrays.copyOf(prefix, prefix.length + WILD_CARD.length);
                    System.arraycopy(WILD_CARD, 0, prefixToUse, prefix.length, WILD_CARD.length);
                    return connection.keys(prefixToUse);
                } else {
                    return connection.zRevRangeByScore(setOfKnownKeys, RedisZSetCommands.Range.unbounded());
                }
            }
        });
        if(null == keys || keys.isEmpty()) return Collections.EMPTY_LIST;
        List result = new ArrayList<>(keys.size());
        keys.forEach(key ->
            result.add(redisOperations.execute(new RedisCallback() {
                @Override
                public Object doInRedis(RedisConnection connection) throws DataAccessException {
                    return redisOperations.getValueSerializer().deserialize(connection.get(key));
                }
            }))
        );
        return result;
    }

    class RedisKeySizeByPrefixCallback implements RedisCallback {



        @Override
        public Integer doInRedis(RedisConnection connection) throws DataAccessException {
            byte[] prefixToUse = Arrays.copyOf(prefix, prefix.length + WILD_CARD.length);
            System.arraycopy(WILD_CARD, 0, prefixToUse, prefix.length, WILD_CARD.length);
            Set keys = connection.keys(prefixToUse);
            return keys.size();
        }
    }

    class RedisKeySizeByKeysCallback implements RedisCallback {

        @Override
        public Integer doInRedis(RedisConnection connection) throws DataAccessException {
            return connection.zCount(setOfKnownKeys, RedisZSetCommands.Range.unbounded()).intValue();
        }
    }



    class RedisKeysByPrefixCallback implements RedisCallback> {
        @Override
        public Set doInRedis(RedisConnection connection) throws DataAccessException {
            byte[] prefixToUse = Arrays.copyOf(prefix, prefix.length + WILD_CARD.length);
            System.arraycopy(WILD_CARD, 0, prefixToUse, prefix.length, WILD_CARD.length);
            Set keys = connection.keys(prefixToUse);
            return deserializeByte2String(keys);
        }
    }

    class RedisKeysByKeysCallback implements RedisCallback> {
        @Override
        public Set doInRedis(RedisConnection connection) throws DataAccessException {
            return deserializeByte2String(connection.zRevRangeByScore(setOfKnownKeys, RedisZSetCommands.Range.unbounded()));
        }
    }

    private static Set deserializeByte2String(Set set) {
        if (null == set || set.isEmpty()) return Collections.emptySet();
        Set result = new HashSet<>(set.size());
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        for (byte[] key : set) {
            result.add(stringRedisSerializer.deserialize(key));
        }
        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy