spring-data-redis 整合,以及使用kryo序列化代替jdk原生序列化机制

2018-05-28

实验发现,kryo序列化后,如果类字段改动,容易报错,现在仔细想想其实我们没有特别大的对象,没必要使用kryo序列化,也有很多公司都是先json 然后"{json对象}".getBytes()存储

1. 引入 spring-data-redis maven依赖

<dependency>
    <groupId>org.springframework.datagroupId>
    <artifactId>spring-data-redisartifactId>
    <version>1.8.0.RELEASEversion>
dependency>
<!-redisclients一定要2.9以上啊,注意项目中引入的jedis版本已经是否被其他依赖替换了->
<dependency>
    <groupId>redis.clientsgroupId>
    <artifactId>jedisartifactId>
    <version>2.9.0version>
dependency>

2.配置文件

xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">


    
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        
        <property name="maxTotal" value="30" />
        
        <property name="maxIdle" value="10" />
        
        <property name="numTestsPerEvictionRun" value="1024" />
        
        <property name="timeBetweenEvictionRunsMillis" value="30000" />
        
        <property name="minEvictableIdleTimeMillis" value="1800000" />
        
        <property name="softMinEvictableIdleTimeMillis" value="10000" />
        
        <property name="maxWaitMillis" value="1500" />
        
        <property name="testOnBorrow" value="true" />
        
        <property name="testWhileIdle" value="true" />
        
        <property name="blockWhenExhausted" value="false" />
    bean>
    
    <bean id="jedisClient" class="cn.deepfashion.manager.cache.impl.JedisClientTem">
        <property name="prefix" value="${redis.key.prefix}">property>
    bean>


    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
        <property name="poolConfig" ref="jedisPoolConfig">property>
        <property name="hostName" value="${redis.host}">property>
        <property name="port" value="${redis.port}">property>
        <property name="timeout" value="${redis.timeout}">property>
        <property name="password" value="${redis.password}">property>
    bean>


    <bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <property name="keySerializer">
        
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        property>
        <property name="defaultSerializer">
        
            <bean class="cn.deepfashion.redis.serializer.KryoRedisSerializer">bean>
        property>
    bean>


    <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" parent="jedisTemplate" />


beans>

3. 下面开始贴出来简单封装的模板


import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.util.CollectionUtils;

import cn.deepfashion.manager.cache.JedisClient;
import cn.deepfashion.manager.logger.DeepFashionLoggerFactory;

/**
 * jedis客户端
 * 
 * @author zmh
 * 
 * @param 
 *            2017年4月2日
 */
public class JedisClientTem<V> implements JedisClient<V> {

    private static String prefix;
    private static final Logger logger = DeepFashionLoggerFactory.getLogger(JedisClientTem.class);

    @Resource
    RedisTemplate jedisTemplate;
    @Resource
    StringRedisTemplate stringRedisTemplate;

    /**
     * 缓存基本的对象
     * 
     * @param key
     *            缓存的键值
     * @param value
     *            缓存的值
     * @return 缓存的对象
     */
    @Override
    public void set(String key, V value) {
        try {
            jedisTemplate.opsForValue().set(getKey(key), value);
        } catch (Exception e) {
            logger.warn("RedisTemplate::set,key={},value={}", key, value, e);
        }
    }

    /**
     * 缓存对象
     * 
     * @param key
     * @param seconds
     *            秒
     * @param value
     *            2017年3月26日
     */
    @Override
    public void set(String key, int seconds, V value) {
        try {

            jedisTemplate.opsForValue().set(getKey(key), value, seconds, TimeUnit.SECONDS);
        } catch (Exception e) {
            logger.warn("RedisTemplate::set,key={},value={},seconds={}", key, value, seconds, e);
        }
    }

    /**
     * 获得缓存的基本对象。
     * 
     * @param key
     *            缓存键值
     * @return 缓存键值对应的数据
     */
    @Override
    public V get(String key) {
        V value = null;
        try {
            value = jedisTemplate.opsForValue().get(getKey(key));
        } catch (Exception e) {
            logger.warn("RedisTemplate::get, key={}", key, e);
        }
        return value;
    }

    /**
     * 缓存 基本 Integer、String、实体类等
     * 
     * @param key
     * @param value
     *            2017年4月2日
     */
    @Override
    public void setString(String key, int seconds, String value) {
        try {
            stringRedisTemplate.opsForValue().set(getKey(key), value, seconds, TimeUnit.SECONDS);
        } catch (Exception e) {
            logger.warn("RedisTemplate::setString,key={},value={},seconds={}", key, value, seconds, e);
        }
    }

    /**
     * 获取基本类型值
     * 
     * @param key
     * @return 2017年4月2日
     */
    @Override
    public String getString(String key) {
        String value = null;
        try {
            value = stringRedisTemplate.opsForValue().get(getKey(key));
        } catch (Exception e) {
            logger.warn("RedisTemplate::getString, key={}", key, e);
        }
        return value;
    }

    /**
     * 设置值的有效时间
     * 
     * @param key
     * @param second
     * @return 2017年3月26日
     */
    @Override
    public Boolean expire(String key, long second) {
        boolean result = false;

        try {
            result = jedisTemplate.expire(getKey(key), second, TimeUnit.SECONDS);
        } catch (Exception e) {
            logger.warn("RedisTemplate::expire, key={}, second={}", key, second, e);
        }

        return result;
    }

    /**
     * 获取值的有效时间
     * 
     * @param key
     * @return 2017年3月26日
     */
    @Override
    public long getExpire(String key) {
        long result = 0;
        try {
            result = jedisTemplate.getExpire(getKey(key), TimeUnit.SECONDS);
        } catch (Exception e) {
            logger.warn("RedisTemplate::getExpire, key={}", key, e);
        }

        return result;
    }

    /**
     * 删除值
     * 
     * @param key
     *            2017年3月26日
     */
    @Override
    public void delete(String key) {
        try {

            jedisTemplate.delete(getKey(key));
        } catch (Exception e) {
            logger.warn("RedisTemplate::delete, key={}", key, e);
        }
    }

    /**
     * 对象是否存在
     * 
     * @param key
     * @return 2017年3月26日
     */
    @Override
    public Boolean hasKey(String key) {
        boolean result = false;
        try {

            result = jedisTemplate.hasKey(getKey(key));
        } catch (Exception e) {
            logger.warn("RedisTemplate::hasKey, key={}", key, e);
        }

        return result;
    }

    /**
     * 缓存List数据
     * 
     * @param key
     *            缓存的键值
     * @param dataList
     *            待缓存的List数据
     * @return 缓存的对象
     */
    @Override
    public void listAddAll(String key, List dataList) {
        if (CollectionUtils.isEmpty(dataList)) {
            return;
        }

        try {
            ListOperations listOperation = jedisTemplate.opsForList();
            String pfKey = getKey(key);
            
        } catch (Exception e) {
            logger.warn("RedisTemplate::listAddAll, key={}, dataList={}", key, dataList, e);
        }
    }

    /**
     * 缓存List数据(从右侧依次添加 不会覆盖原来的数据)
     * 
     * @param key
     *            缓存的键值
     * @param dataList
     *            待缓存的List数据
     * @return 缓存的对象
     */
    @Override
    public void listAddAll(String key, int seconds, List dataList) {
        if (CollectionUtils.isEmpty(dataList)) {
            return;
        }
        try {
            ListOperations listOperation = jedisTemplate.opsForList();

            String pfKey = getKey(key);
            
        

            this.expire(getKey(key), seconds);
        } catch (Exception e) {
            logger.warn("RedisTemplate::listAddAll, key={}, dataList={},seconds={}", key, dataList, seconds, e);
        }
    }

    /**
     * 获得缓存的list对象
     * 
     * @param key
     *            缓存的键值
     * @return 缓存键值对应的数据
     */
    @Override
    public List listGetAll(String key) {
        List result = null;
        try {
            ListOperations listOperation = jedisTemplate.opsForList();
            result = listOperation.range(getKey(key), 0, -1);
        } catch (Exception e) {
            result = Collections.emptyList();
            logger.warn("RedisTemplate::getList, key={}", key, e);
        }
        return result;
    }

    /**
     * 用指定元素替换此列表中指定位置的元素(可选操作)
     */
    @Override
    public void listSet(String key, long index, V value) {
        try {
            ListOperations listOperation = jedisTemplate.opsForList();
            listOperation.set(getKey(key), index, value);
        } catch (Exception e) {
            logger.warn("RedisTemplate::listSet, key={}, dataList={}, value={}", key, value, e);
        }
    }

    /**
     * 缓存Map
     * 
     * @param key
     * @param dataMap
     * @return
     */
    @Override
    public void mapPutAll(String key, Map dataMap) {
        try {

            HashOperations hashOperations = jedisTemplate.opsForHash();
            hashOperations.putAll(getKey(key), dataMap);
        } catch (Exception e) {
            logger.warn("RedisTemplate::mapPutAll, key={},dataMap={}", key, dataMap, e);
        }
    }

    @Override
    public void mapPutAll(String key, int seconds, Map dataMap) {
        try {

            HashOperations hashOperations = jedisTemplate.opsForHash();
            hashOperations.putAll(getKey(key), dataMap);
            this.expire(getKey(key), seconds);
        } catch (Exception e) {
            logger.warn("RedisTemplate::mapPutAll, key={},dataMap={}", key, dataMap, e);
        }
    }

    /**
     * 获得缓存的Map
     * 
     * @param key
     * @param hashOperation
     * @return
     */
    @Override
    public Map mapGetAll(String key) {
        Map result = null;
        try {
            result = jedisTemplate.opsForHash().entries(getKey(key));
        } catch (Exception e) {
            result = Collections.emptyMap();
            logger.warn("RedisTemplate::getMap, key={}", key, e);
        }
        return result;
    }

    /**
     * 获取map中指定的值
     * 
     * @param key
     * @param hashKey
     * @return 2017年3月26日
     */
    @Override
    public Object mapGet(String key, Object hashKey) {
        Object result = null;
        try {
            result = jedisTemplate.opsForHash().hasKey(getKey(key), hashKey);
        } catch (Exception e) {
            logger.warn("RedisTemplate::getMapValue, key={},mapKey={}", key, hashKey, e);
        }
        return result;
    }

    @Override
    public void mapPut(String key, String hashKey, V value) {
        try {
            HashOperations hashOperations = jedisTemplate.opsForHash();
            hashOperations.put(getKey(key), hashKey, value);
        } catch (Exception e) {
            logger.warn("RedisTemplate::mapPutAll, key={},value={}", key, value, e);
        }

    }

    /**
     * 缓存Set
     * 
     * @param key
     *            缓存键值
     * @param dataSet
     *            缓存的数据
     * @return 缓存数据的对象
     */
    @SuppressWarnings("unchecked")
    @Override
    public void setAddAll(String key, Set dataSet) {
        try {

            BoundSetOperations setOperation = jedisTemplate.boundSetOps(getKey(key));
            Iterator it = dataSet.iterator();
            while (it.hasNext()) {
                setOperation.add(it.next());
            }
        } catch (Exception e) {
            logger.warn("RedisTemplate::setAddAll, key={},dataSet={}", key, dataSet, e);
        }
    }

    /**
     * 获得缓存的set
     * 
     * @param key
     * @param operation
     * @return
     */
    @Override
    public Set getSet(String key) {
        Set result = null;
        try {
            BoundSetOperations operation = jedisTemplate.boundSetOps(getKey(key));
            result = operation.members();
        } catch (Exception e) {
            result = Collections.emptySet();
            logger.warn("RedisTemplate::getSet, key={}", key, e);
        }
        return result;
    }

    /**
     * 获取list模板操作list集合
     * 
     * @return 2017年3月26日
     */
    @Override
    public ListOperations listTemplate() {
        return jedisTemplate.opsForList();
    }

    /**
     * 获取map模板操作map
     * 
     * @return 2017年3月26日
     */
    @Override
    public HashOperations mapTemplate() {
        return jedisTemplate.opsForHash();
    }

    /**
     * 获取有序集合模板
     * 
     * @return 2017年3月26日
     */
    @Override
    public ZSetOperations zSetTemplate() {
        return jedisTemplate.opsForZSet();
    }

    @Override
    public ValueOperations valueTemplate() {
        return jedisTemplate.opsForValue();
    }

    public static String getKey(String key) {
        return prefix + key;
    }

    public static String getPrefix() {
        return prefix;
    }

    public static void setPrefix(String prefix) {
        JedisClientTem.prefix = prefix;
    }

    public RedisTemplate getJedisTemplate() {
        return jedisTemplate;
    }

    public void setJedisTemplate(RedisTemplate jedisTemplate) {
        this.jedisTemplate = jedisTemplate;
    }

    @Override
    public StringRedisTemplate getStringTemplate() {
        return stringRedisTemplate;
    }

    public ValueOperations stringValueTemplate() {
        return stringRedisTemplate.opsForValue();
    }

}



import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;

public interface JedisClient<V> {

    /**
     * 缓存对象
     * 
     * @param key
     *            缓存的键值
     * @param value
     *            缓存的值
     * @return 缓存的对象
     */
    public void set(String key, V value);

    /**
     * 缓存对象
     * 
     * @param key
     * @param seconds
     *            秒
     * @param value
     *            2017年3月26日
     */
    public void set(String key, int seconds, V value);

    /**
     * 缓存 基本 Integer、String、实体类等
     * 
     * @param key
     * @param value
     *            2017年4月2日
     */
    public void setString(String key, int seconds, String value);

    /**
     * 获取基本类型值
     * 
     * @param key
     * @return 2017年4月2日
     */
    public String getString(String key);

    /**
     * 获得缓存的基本对象。
     * 
     * @param key
     *            缓存键值
     * @return 缓存键值对应的数据
     */
    public V get(String key);

    /**
     * 设置值的有效时间
     * 
     * @param key
     * @param second
     * @return 2017年3月26日
     */
    public Boolean expire(String key, long second);

    /**
     * 获取值的有效时间
     * 
     * @param key
     * @return 2017年3月26日
     */
    public long getExpire(String key);

    /**
     * 删除值
     * 
     * @param key
     *            2017年3月26日
     */
    public void delete(String key);

    /**
     * 对象是否存在
     * 
     * @param key
     * @return 2017年3月26日
     */
    public Boolean hasKey(String key);

    /**
     * 缓存List数据(从右侧依次添加 不会覆盖原来的数据)
     * 
     * @param key
     *            缓存的键值
     * @param dataList
     *            待缓存的List数据
     * @return 缓存的对象
     */
    public void listAddAll(String key, List dataList);

    /**
     * 缓存List数据(从右侧依次添加 不会覆盖原来的数据)
     * 
     * @param key
     *            缓存的键值
     * @param dataList
     *            待缓存的List数据
     * @return 缓存的对象
     */
    public void listAddAll(String key, int seconds, List dataList);

    /**
     * 获得缓存的list对象
     * 
     * @param key
     *            缓存的键值
     * @return 缓存键值对应的数据
     */
    public List listGetAll(String key);

    /**
     * 用指定元素替换此列表中指定位置的元素(可选操作)
     * 
     * @param key
     * @param value
     *            2017年3月31日
     */
    public void listSet(String key, long index, V value);

    /**
     * 缓存Map
     * 
     * @param key
     * @param dataMap
     * @return
     */
    public void mapPutAll(String key, Map dataMap);

    /**
     * 添加map
     * 
     * @param key
     * @param seconds
     * @param dataMap
     *            2017年3月31日
     */
    public void mapPutAll(String key, int seconds, Map dataMap);

    /**
     * 获得缓存的Map
     * 
     * @param key
     * @param hashOperation
     * @return
     */
    public Map mapGetAll(String key);

    /**
     * map 添加数据
     * 
     * @param key
     * @param hashKey
     * @param value
     *            2017年3月31日
     */
    public void mapPut(String key, String hashKey, V value);

    /**
     * 获取map中指定的值
     * 
     * @param key
     * @param hashKey
     * @return 2017年3月26日
     */
    public Object mapGet(String key, Object hashKey);

    /**
     * 缓存Set
     * 
     * @param key
     *            缓存键值
     * @param dataSet
     *            缓存的数据
     * @return 缓存数据的对象
     */
    public void setAddAll(String key, Set dataSet);

    /**
     * 获得缓存的set
     * 
     * @param key
     * @param operation
     * @return
     */
    public Set getSet(String key);

    /**
     * 获取list模板操作list集合
     * 
     * @return 2017年3月26日
     */
    public ListOperations listTemplate();

    /**
     * 获取map模板操作map
     * 
     * @return 2017年3月26日
     */
    public HashOperations mapTemplate();

    /**
     * 获取有序集合模板
     * 
     * @return 2017年3月26日
     */
    public ZSetOperations zSetTemplate();

    /**
     * 获取基本value模板
     * 
     * @return 2017年3月27日
     */
    public ValueOperations valueTemplate();

    public RedisTemplate getJedisTemplate();

    public StringRedisTemplate getStringTemplate();

    public ValueOperations stringValueTemplate();
}

 

import java.io.InputStream;
import java.io.OutputStream;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;


import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;


import cn.deepfashion.common.util.SerializerUtils;


/**
 * 
 */
@SuppressWarnings("unchecked")
public class KryoRedisSerializer<T> implements RedisSerializer<T> {


    private final static Logger logger = LoggerFactory.getLogger(KryoRedisSerializer.class);


    @Override
    public byte[] serialize(Object obj) throws SerializationException {
        if (obj == null) {
            return SerializerUtils.EMPTY_ARRAY;
        }
        Kryo kryo = kryos.get();
        Output output = new Output(64, -1);


        try {
            kryo.writeClassAndObject(output, obj);
            return output.toBytes();
        } finally {
            closeOutputStream(output);
        }


    }


    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (SerializerUtils.isEmpty(bytes)) {
            return null;
        }
        Kryo kryo = kryos.get();
        Input input = null;
        try {
            input = new Input(bytes);
            return (T) kryo.readClassAndObject(input);
        } finally {
            closeInputStream(input);
        }
    }


    private static void closeOutputStream(OutputStream output) {
        if (output != null) {
            try {
                output.flush();
                output.close();
            } catch (Exception e) {
                logger.error("serialize object close outputStream exception", e);
            }
        }
    }


    private static void closeInputStream(InputStream input) {
        if (input != null) {
            try {
                input.close();
            } catch (Exception e) {
                logger.error("serialize object close inputStream exception", e);
            }
        }
    }


    private static final ThreadLocal kryos = new ThreadLocal() {
        protected Kryo initialValue() {
            Kryo kryo = new Kryo();
            return kryo;
        };
    };
}


    /**
     * 空byte数组
     */
    public static final byte[] EMPTY_ARRAY = new byte[0];
    public static boolean isEmpty(byte[] data) {
        return (data == null || data.length == 0);
    }

你可能感兴趣的:(spring)