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

com.yuweix.kuafu.data.cache.redis.jedis.JedisCache Maven / Gradle / Ivy

The newest version!
package com.yuweix.kuafu.data.cache.redis.jedis;


import com.yuweix.kuafu.data.cache.AbstractCache;
import com.yuweix.kuafu.data.cache.MessageHandler;
import com.yuweix.kuafu.data.cache.redis.RedisCache;
import com.yuweix.kuafu.data.serializer.Serializer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
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.ZSetOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.scripting.support.ResourceScriptSource;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @author yuwei
 */
public class JedisCache extends AbstractCache implements RedisCache {
	protected RedisTemplate redisTemplate;
	protected Serializer serializer;
	protected RedisMessageListenerContainer messageContainer;


	public JedisCache(RedisTemplate redisTemplate, Serializer serializer) {
		this.redisTemplate = redisTemplate;
		this.serializer = serializer;
	}


	public void setRedisTemplate(RedisTemplate redisTemplate) {
		this.redisTemplate = redisTemplate;
	}

	public void setSerializer(Serializer serializer) {
		this.serializer = serializer;
	}

	public void setMessageContainer(RedisMessageListenerContainer messageContainer) {
		this.messageContainer = messageContainer;
	}

	@Override
	public void subscribe(final String channel, final MessageHandler handler) {
		subscribe(Collections.singletonList(channel), handler);
	}

	@Override
	public void subscribe(List channels, final MessageHandler handler) {
		List topics = new ArrayList<>();
		for (String channel: channels) {
			topics.add(new PatternTopic(channel));
		}
		messageContainer.addMessageListener(new MessageListener() {
			@Override
			public void onMessage(Message message, byte[] pattern) {
				String channel = new String(message.getChannel(), StandardCharsets.UTF_8);
				String msg = new String(message.getBody(), StandardCharsets.UTF_8);
				handler.handle(channel, msg);
			}
		}, topics);
	}

	@Override
	public void publish(final String channel, final String message) {
		redisTemplate.execute(new RedisCallback() {
			@Override
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				connection.publish(channel.getBytes(StandardCharsets.UTF_8), message.getBytes(StandardCharsets.UTF_8));
				return null;
			}
		});
	}

	@Override
	public boolean contains(String key) {
		Object object = redisTemplate.opsForValue().get(key);
		return object != null;
	}

	@Override
	public void expire(String key, long timeout) {
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
	}

	@Override
	public  boolean put(String key, T value, long timeout) {
		if (timeout <= 0) {
			throw new RuntimeException("Invalid parameter[timeout].");
		}

		redisTemplate.opsForValue().set(key, serializer.serialize(value), timeout, TimeUnit.SECONDS);
		return true;
	}

	@Override
	public T get(String key) {
		return serializer.deserialize((String) redisTemplate.opsForValue().get(key));
	}

	@Override
	public void remove(String key) {
		redisTemplate.delete(key);
	}

	@Override
	public boolean hset(String key, String field, T value, long timeout) {
		redisTemplate.opsForHash().put(key, field, serializer.serialize(value));
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
		return true;
	}

	@Override
	public boolean hmset(String key, Map entries, long timeout) {
		if (entries == null || entries.isEmpty()) {
			return true;
		}
		Map strMap = new HashMap<>();
		for (Map.Entry entry: entries.entrySet()) {
			strMap.put(entry.getKey(), serializer.serialize(entry.getValue()));
		}
		redisTemplate.opsForHash().putAll(key, strMap);
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
		return true;
	}

	@Override
	public T hget(String key, String field) {
		return serializer.deserialize((String) redisTemplate.opsForHash().get(key, field));
	}

	@Override
	public Map hgetAll(String key) {
		Map entries = redisTemplate.opsForHash().entries(key);
		Map strMap = (Map) entries;
		Map resMap = new HashMap<>();
		if (strMap.isEmpty()) {
			return resMap;
		}
		for (Map.Entry strEntry: strMap.entrySet()) {
			resMap.put(strEntry.getKey(), serializer.deserialize(strEntry.getValue()));
		}
		return resMap;
	}

	@Override
	public void remove(String key, String field) {
		redisTemplate.opsForHash().delete(key, field);
	}

	@Override
	public boolean lpush(String key, T value, long timeout) {
		redisTemplate.opsForList().leftPush(key, serializer.serialize(value));
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
		return true;
	}

	@Override
	public boolean lpush(String key, List valList, long timeout) {
		if (valList == null || valList.size() <= 0) {
			return true;
		}
		List strList = new ArrayList<>();
		for (T t: valList) {
			strList.add(serializer.serialize(t));
		}
		redisTemplate.opsForList().leftPushAll(key, strList.toArray(new String[0]));
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
		return true;
	}

	@Override
	public boolean rpush(String key, T value, long timeout) {
		redisTemplate.opsForList().rightPush(key, serializer.serialize(value));
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
		return true;
	}

	@Override
	public boolean rpush(String key, List valList, long timeout) {
		if (valList == null || valList.size() <= 0) {
			return true;
		}
		List strList = new ArrayList<>();
		for (T t: valList) {
			strList.add(serializer.serialize(t));
		}
		redisTemplate.opsForList().rightPushAll(key, strList.toArray(new String[0]));
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
		return true;
	}

	@Override
	public long lsize(String key) {
		Long size = redisTemplate.opsForList().size(key);
		return size == null ? 0 : size;
	}

	@Override
	public T lindex(String key, long index) {
		return serializer.deserialize((String) redisTemplate.opsForList().index(key, index));
	}

	@Override
	public List lrange(String key, long start, long end) {
		List strList = redisTemplate.opsForList().range(key, start, end);
		List tList = new ArrayList<>();
		if (strList == null || strList.size() <= 0) {
			return tList;
		}
		for (Object str: strList) {
			tList.add(serializer.deserialize((String) str));
		}
		return tList;
	}

	@Override
	public void ltrim(String key, long start, long end) {
		redisTemplate.opsForList().trim(key, start, end);
	}

	@Override
	public void lset(String key, long index, T value) {
		redisTemplate.opsForList().set(key, index, serializer.serialize(value));
	}

	@Override
	public T lpop(String key) {
		return serializer.deserialize((String) redisTemplate.opsForList().leftPop(key));
	}

	@Override
	public T rpop(String key) {
		return serializer.deserialize((String) redisTemplate.opsForList().rightPop(key));
	}

	@Override
	public void sadd(String key, T t, long timeout) {
		redisTemplate.opsForSet().add(key, serializer.serialize(t));
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
	}

	@Override
	public void sadd(String key, List valList, long timeout) {
		if (valList == null || valList.size() <= 0) {
			return;
		}
		List strList = new ArrayList<>();
		for (T t: valList) {
			strList.add(serializer.serialize(t));
		}
		redisTemplate.opsForSet().add(key, strList.toArray(new String[0]));
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
	}

	@Override
	public long slen(String key) {
		Long size = redisTemplate.opsForSet().size(key);
		return size == null ? 0 : size;
	}

	@Override
	public Set sdiff(String key, Collection otherKeys) {
		Set strSet = redisTemplate.opsForSet().difference(key, otherKeys);
		Set tSet = new HashSet<>();
		if (strSet == null || strSet.isEmpty()) {
			return tSet;
		}
		for (Object str: strSet) {
			tSet.add(serializer.deserialize((String) str));
		}
		return tSet;
	}

	@Override
	public void sdiffStore(String key, Collection otherKeys, String destKey) {
		redisTemplate.opsForSet().differenceAndStore(key, otherKeys, destKey);
	}

	@Override
	public Set sinter(String key, Collection otherKeys) {
		Set strSet = redisTemplate.opsForSet().intersect(key, otherKeys);
		Set tSet = new HashSet<>();
		if (strSet == null || strSet.isEmpty()) {
			return tSet;
		}
		for (Object str: strSet) {
			tSet.add(serializer.deserialize((String) str));
		}
		return tSet;
	}

	@Override
	public void sinterStore(String key, Collection otherKeys, String destKey) {
		redisTemplate.opsForSet().intersectAndStore(key, otherKeys, destKey);
	}

	@Override
	public Set sunion(String key, Collection otherKeys) {
		Set strSet = redisTemplate.opsForSet().union(key, otherKeys);
		Set tSet = new HashSet<>();
		if (strSet == null || strSet.isEmpty()) {
			return tSet;
		}
		for (Object str: strSet) {
			tSet.add(serializer.deserialize((String) str));
		}
		return tSet;
	}

	@Override
	public void sunionStore(String key, Collection otherKeys, String destKey) {
		redisTemplate.opsForSet().unionAndStore(key, otherKeys, destKey);
	}

	@Override
	public boolean sisMember(String key, T member) {
		Boolean aBoolean = redisTemplate.opsForSet().isMember(key, serializer.serialize(member));
		return aBoolean != null && aBoolean;
	}

	@Override
	public Set smembers(String key) {
		Set strSet = redisTemplate.opsForSet().members(key);
		Set tSet = new HashSet<>();
		if (strSet == null || strSet.isEmpty()) {
			return tSet;
		}
		for (Object str: strSet) {
			tSet.add(serializer.deserialize((String) str));
		}
		return tSet;
	}

	@Override
	public boolean smove(String sourceKey, String destKey, T member) {
		Boolean aBoolean = redisTemplate.opsForSet().move(sourceKey, serializer.serialize(member), destKey);
		return aBoolean != null && aBoolean;
	}

	@Override
	public boolean sremove(String key, Collection members) {
		if (members == null || members.size() <= 0) {
			return false;
		}
		List strList = new ArrayList<>();
		for (T t: members) {
			strList.add(serializer.serialize(t));
		}
		Long aLong = redisTemplate.opsForSet().remove(key, strList.toArray());
		return aLong != null && aLong > 0;
	}

	@Override
	public void zadd(String key, T value, double score, long timeout) {
		redisTemplate.opsForZSet().add(key, serializer.serialize(value), score);
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
	}

	@Override
	public void zadd(String key, Map memScore, long timeout) {
		Set> tuples = new HashSet<>();
		for (Map.Entry entry: memScore.entrySet()) {
			tuples.add(new ZSetOperations.TypedTuple() {
				@Override
				public int compareTo(ZSetOperations.TypedTuple o) {
					Double score = this.getScore();
					score = score == null ? 0 : score;
					Double score2 = o.getScore();
					score2 = score2 == null ? 0 : score2;
					return score > score2 ? 1 : -1;
				}

				@Override
				public Object getValue() {
					return serializer.serialize(entry.getKey());
				}

				@Override
				public Double getScore() {
					return entry.getValue();
				}
			});
		}
		redisTemplate.opsForZSet().add(key, tuples);
		redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
	}

	@Override
	public long zlen(String key) {
		Long size = redisTemplate.opsForZSet().size(key);
		return size == null ? 0 : size;
	}

	@Override
	public long zcount(String key, double min, double max) {
		Long count = redisTemplate.opsForZSet().count(key, min, max);
		return count == null ? 0 : count;
	}

	@Override
	public void zincrby(String key, T member, double increment) {
		redisTemplate.opsForZSet().incrementScore(key, serializer.serialize(member), increment);
	}

	@Override
	public void zinterStore(String key, Collection otherKeys, String destKey) {
		redisTemplate.opsForZSet().intersectAndStore(key, otherKeys, destKey);
	}

	@Override
	public void zunionStore(String key, Collection otherKeys, String destKey) {
		redisTemplate.opsForZSet().unionAndStore(key, otherKeys, destKey);
	}

	@Override
	public boolean zremove(String key, Collection members) {
		if (members == null || members.size() <= 0) {
			return false;
		}
		List strList = new ArrayList<>();
		for (T t: members) {
			strList.add(serializer.serialize(t));
		}
		Long aLong = redisTemplate.opsForZSet().remove(key, strList.toArray());
		return aLong != null && aLong > 0;
	}

	@Override
	public Double zscore(String key, T member) {
		return redisTemplate.opsForZSet().score(key, serializer.serialize(member));
	}

	@Override
	public Long zrank(String key, T member) {
		return redisTemplate.opsForZSet().rank(key, serializer.serialize(member));
	}

	@Override
	public boolean lock(String key, T owner, long timeout) {
		return lock(key, owner, timeout, false);
	}

	@Override
	public boolean lock(String key, T owner, long timeout, boolean reentrant) {
		if (owner == null) {
			return false;
		}
		DefaultRedisScript redisScript = new DefaultRedisScript<>();
		redisScript.setResultType(String.class);
		redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/getLock.lua")));
		String result = redisTemplate.execute(redisScript, Collections.singletonList(key)
				, String.valueOf(reentrant), serializer.serialize(owner), String.valueOf(timeout));
		return "OK".equalsIgnoreCase(result);
	}

	@Override
	public  T tlock(String key, T owner, long timeout) {
		if (owner == null) {
			return null;
		}
		DefaultRedisScript redisScript = new DefaultRedisScript<>();
		redisScript.setResultType(String.class);
		redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/getLockt.lua")));
		String result = redisTemplate.execute(redisScript, Collections.singletonList(key)
				, serializer.serialize(owner), String.valueOf(timeout));
		return result == null ? null : serializer.deserialize(result);
	}

	@Override
	public boolean unlock(String key, T owner) {
		if (owner == null) {
			return false;
		}
		if (!contains(key)) {
			return true;
		}
		DefaultRedisScript redisScript = new DefaultRedisScript<>();
		redisScript.setResultType(Long.class);
		redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/releaseLock.lua")));
		Long result = redisTemplate.execute(redisScript, Collections.singletonList(key), serializer.serialize(owner));
		return result != null && "1".equals(result.toString());
	}

	@Override
	public String execute(String script, List keyList, List argList) {
		return execute(script, keyList, argList, String.class);
	}

	@Override
	public S execute(String script, List keyList, List argList, Class returnType) {
		List strArgList = new ArrayList<>();
		if (argList != null && argList.size() > 0) {
			for (T t: argList) {
				strArgList.add(serializer.serialize(t));
			}
		}
		DefaultRedisScript redisScript = new DefaultRedisScript<>();
		redisScript.setResultType(returnType);
		redisScript.setScriptText(script);
		return redisTemplate.execute(redisScript, keyList, strArgList.toArray());
	}
}