17课:关于Springboot和JedisCluster结合使用,自定义缓存的序列化方式

17课:关于Springboot和JedisCluster结合使用,自定义缓存的序列化方式

简介

现在大部分项目多多少少都会碰到一下功能会使用到缓存的地方;本文通过redis集群进行演示
通过JedisCluster实现redis缓存操作的内容;同事自定义缓存的序列化方式,在通过客户端进行命令行操作方便查看对应的key-value 的值内容.

项目demo下载

项目结构

在这里插入图片描述

代码简介

1. redis.properties文件

主要是关于redis的一些配置项内容包含集群的服务器地址,密码等配置项内容
cache.redis.servers=51000:redis;51001:redis;51002:redis
cache.redis.password=gm2018

cache.redis.maxWaitMillis=1000
cache.redis.maxTotal=1000
cache.redis.minIdle=8
cache.redis.maxIdle=100
cache.redis.testOnBorrow=true
cache.redis.testOnReturn=true

cache.redis.connectionTimeout=10000
cache.redis.soTimeout=800
cache.redis.maxRedirections=6

2.pom.xml文件

引入JedisCluster
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
    		<version>3.3.0</version>
		</dependency>
		

3.RedisConfig.java

里面关于JedisCluster配置项内容然后主要通过RedisUtil 工具类中的方法实现里面的不同数据格式缓存的调用
@Configuration
@ConfigurationProperties(prefix="cache.redis")
@PropertySource(value = "classpath:redis.properties", encoding = "UTF-8")
public class RedisConfig {

	//redis服务
	private String  servers;
	//密码
	private String password;
	//poolConfig配置
	private boolean testOnBorrow;
	private boolean testOnReturn;
	private int maxTotal;
	private int maxIdle;
	private int minIdle;
	private long maxWaitMillis;
	private int connectionTimeout;
	private int soTimeout;
	private int maxRedirections;
	
	/**
	 * 通过获取配置文件进行JedisCluster配置.
	 * @author  khy
	 * @createTime 2020年11月20日下午3:51:45
	 * @return
	 */
	@Bean("jedisCluster")
	public JedisCluster createJedisCluster(){
		try {
			Set<HostAndPort> jedisClusterNode = new HashSet();
			//这个是切分redis集群的配置,因为是同一台机器所以端口不同所以端口放前面了
			Splitter.on(";").withKeyValueSeparator(":").split(servers).forEach((k,v)->{
				if(StringUtils.isNoneBlank(k,v)){
					jedisClusterNode.add(new HostAndPort(v, Integer.valueOf(k)));
				}
			});
            GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
            poolConfig.setMaxWaitMillis(maxWaitMillis);
            poolConfig.setMaxTotal(maxTotal);
            poolConfig.setMaxIdle(maxIdle);
            poolConfig.setMinIdle(minIdle);
            poolConfig.setTestOnBorrow(testOnBorrow);		
            poolConfig.setTestOnReturn(testOnReturn);
            JedisCluster cluster = new JedisCluster(jedisClusterNode, connectionTimeout, soTimeout,maxRedirections,password,poolConfig);
			return cluster;
		} catch (Exception e) {
			throw new RuntimeException("redis服务地址配置无效不符合条件");
		}
	}
	// get/set方法省略
}

4.SerializerUtil

默认的一般key 或者 字符串类型的value都可以通过 StringRedisSerializer 进行序列化操作
如果是实体类对象需要通过自定义FastjsonRedisSerializer 里面实际是通过 com.alibaba.fastjson.JSON
对实体对象进行序列化和反序列化;在通过命令获取redis中value值能看到具体的内容,默认的序列化方式则二进制码
public class SerializerUtil {

	/**
	 * key
	 */
	private static RedisSerializer<String> keySerializer = new StringRedisSerializer();
	/**
	 * Object value
	 */
	private static RedisSerializer<Object> valueSerializer = new FastjsonRedisSerializer();

	/**
	 * 序列化redis的key值
	 * @author  khy
	 * @createTime 2019年11月12日上午10:32:34
	 * @param key
	 * @return
	 */
	public static byte[] rawKey(String key) {
		return keySerializer.serialize(key);
	}
	
	/**
	 * 根据value的类型序列化value
	 * @author  khy
	 * @createTime 2019年11月11日下午9:21:07
	 * @param obj
	 * @return
	 */
	public static <V>byte[] rawValue(V obj){
		return valueSerializer.serialize(obj);
	}
	
	/**
	 * 批量序列化Object类型
	 * @author  khy
	 * @createTime 2019年11月12日上午10:48:22
	 * @param list
	 * @return
	 */
	public static <T> byte[][] rawValues(List<T>list) {
		final byte[][] rawValues = new byte[list.size()][];
		int i = 0;
		for (Object value : list) {
			rawValues[i++] = rawValue(value);  
		}
		return rawValues;
	}
	
	public static byte[][] rawKeys(List<String>list) {
		final byte[][] rawKeys = new byte[list.size()][];
		int i = 0;
		for (String value : list) {
			rawKeys[i++] = rawKey(value);  
		}
		return rawKeys;
	}
	
	public static<V>Map<byte[], byte[]> rawValues(Map<String,V> map) {
		final Map<byte[], byte[]> hashes = new LinkedHashMap<byte[], byte[]>(map.size());
		for (Entry<String, V> entry : map.entrySet()) {
			hashes.put(rawKey(entry.getKey()),rawValue(entry.getValue()));
		}
		return hashes;
	}
	
	/** 
		通过fastJson完成序列化操作
	*/
	public class FastjsonRedisSerializer implements RedisSerializer<Object> {
	
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private static SerializerFeature[] features = {SerializerFeature.WriteClassName};
    
    public Object deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        try {
            return JSON.parse(bytes);
        } catch (Exception ex) {
            throw new SerializationException("Could not read JSON: "
                    + ex.getMessage(), ex);
        }
    }
    
    public byte[] serialize(Object t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        try {
            return JSON.toJSONBytes(t, features);
        } catch (Exception ex) {
            throw new SerializationException("Could not write JSON: "
                    + ex.getMessage(), ex);
        }
    }

}
	/**字符串的操作*/
	public class StringRedisSerializer implements RedisSerializer<String>{
	private final Charset charset;

	public StringRedisSerializer() {
		this(Charset.forName("UTF8"));
	}

	public StringRedisSerializer(Charset charset) {
		Assert.notNull(charset, "Charset must not be null!");
		this.charset = charset;
	}

	public String deserialize(byte[] bytes) {
		return (bytes == null ? null : new String(bytes, charset));
	}

	public byte[] serialize(String string) {
		return (string == null ? null : string.getBytes(charset));
	}
}


	/反序列化//
	
	/**
	 * 反序列化String类型的key值
	 * @author  khy
	 * @createTime 2019年11月12日上午10:44:07
	 * @param bs
	 * @return
	 */
	public static String deserializeKey(byte[] bs) {
		return keySerializer.deserialize(bs);
	}
	/**
	 * 反序列化String类型的value值
	 * @author  khy
	 * @createTime 2019年11月12日上午10:44:07
	 * @param bs
	 * @return
	 */
	public static String deserializeStringValue(byte[] bs) {
		return keySerializer.deserialize(bs);
	}

	/**
	 * 反序列化Object类型的value值
	 * @author  khy
	 * @createTime 2019年11月12日上午11:38:21
	 * @param bs
	 * @return
	 */
	public static <V>V deserializeObjectValue(byte[] bs) {
		return (V) valueSerializer.deserialize(bs);
	}
		
	/**
	 * 反序列化多个key值
	 * @author  khy
	 * @createTime 2019年11月12日上午10:43:28
	 * @param rawValues
	 * @param type
	 * @return
	 */
	public static Set<String> deserializeKeys(Collection<byte[]> rawValues) {
		Set<String>set = new LinkedHashSet<String>(rawValues.size());
		for (byte[] bs : rawValues) {
			set.add(deserializeKey(bs));
		}
		return set;
	}
	
	/**
	 * 批量反序列化成指定集合
	 * @author  khy
	 * @createTime 2019年11月12日上午10:52:38
	 * @param rawValues
	 * @param type
	 * @return
	 */
	public static <T extends Collection<?>> T deserializeValues(Collection<byte[]> rawValues, Class<T> type) {
		Collection<Object> values = List.class.isAssignableFrom(type) ? new ArrayList<Object>(rawValues.size()) : new LinkedHashSet<Object>(rawValues.size());
		for (byte[] bs : rawValues) {
			values.add(deserializeObjectValue(bs));
		}
		return (T) values;
	}
	
	/**
	 * 反序列化成Map集合
	 * @author  khy
	 * @createTime 2019年11月13日下午2:59:20
	 * @param entries
	 * @return
	 */
	public static <V>Map<String, V> deserializeHashMap(Map<byte[], byte[]> entries) {
		if (entries == null) {
			return null;
		}
		Map<String, V> map = new LinkedHashMap<String, V>(entries.size());
		for (Map.Entry<byte[], byte[]> entry : entries.entrySet()) {
			map.put(deserializeKey(entry.getKey()),deserializeObjectValue(entry.getValue()));
		}
		return map;
	}

	

}

总结

项目中通过RedisUtil工具类完成我们对不同数据类型的缓存数据操作的
设置key/value 时将不同类型的数据进行序列化存储.整套的代码已经全部在上面的demo 里面可以自行下载使用;基本不需要动什么配置,修改一下自己的缓存服务器地址.密码即可

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值