去年的项目用的就是Redis集群做外围数据的接收存储,再定时发送给主系统,最近打算将一部分
对象的缓存也放到Redis上,就趁着这个时间点,将代码梳理下,好于将来再用。
此项目用的dubbo+maven架构的,项目结构图
配置文件
redis_faction.xml,项目主要配置文件主要存于service项目中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- redis 配置线程池 -->
<bean name="genericObjectPoolConfig" class="org.apache.commons.pool2.impl.GenericObjectPoolConfig">
<property name="maxWaitMillis" value="-1" />
<property name="maxTotal" value="1000" />
<property name="minIdle" value="8" />
<property name="maxIdle" value="100" />
</bean>
<!-- 初始化JedisClusterFactory -->
<bean id="jedisCluster" class="com.ljp.Faction.JedisClusterFactory">
<property name="addressKeyPrefix" value="address" />
<property name="timeout" value="300000" />
<property name="maxRedirections" value="6" />
<property name="genericObjectPoolConfig" ref="genericObjectPoolConfig" />
</bean>
</beans>
JedisClusterFactory.java
package com.ljp.Faction;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
public class JedisClusterFactory implements FactoryBean<JedisCluster>, InitializingBean {
private String addressKeyPrefix;
private JedisCluster jedisCluster;
private String timeout;
private String maxRedirections;
private GenericObjectPoolConfig genericObjectPoolConfig;
// 非空初始化
public GenericObjectPoolConfig getGenericObjectPoolConfig() {
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
genericObjectPoolConfig.setMaxWaitMillis(1000);
genericObjectPoolConfig.setMaxTotal(20000);
genericObjectPoolConfig.setMaxIdle(20);
genericObjectPoolConfig.setTestOnBorrow(true);
return genericObjectPoolConfig;
}
private Pattern p = Pattern.compile("^.+[:]\\d{1,5}\\s*$");
public JedisCluster getObject() throws Exception {
afterPropertiesSet();
return jedisCluster;
}
public Class<? extends JedisCluster> getObjectType() {
return (this.jedisCluster != null ? this.jedisCluster.getClass() : JedisCluster.class);
}
public boolean isSingleton() {
return true;
}
private Set<HostAndPort> parseHostAndPort() throws Exception {
try {
Properties prop = new Properties();
// 读取属性文件 PS:我的项目有问题,Spring 注入不进去 不知道咋回事,所以我就用了这种方式 给redis 做了初始化
InputStream in = getClass().getClassLoader().getResourceAsStream("connect-redis.properties");
prop.load(in);
Set<HostAndPort> haps = new HashSet<HostAndPort>();
if (addressKeyPrefix == null) {
addressKeyPrefix = "address";
}
for (Object key : prop.keySet()) {
if (!((String) key).startsWith(addressKeyPrefix)) {
continue;
}
String val = (String) prop.get(key);
boolean isIpPort = p.matcher(val).matches();
if (!isIpPort) {
throw new IllegalArgumentException("ip 或 port 不合法");
}
String[] ipAndPort = val.split(":");
HostAndPort hap = new HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
haps.add(hap);
}
return haps;
} catch (IllegalArgumentException ex) {
throw ex;
} catch (Exception ex) {
throw new Exception("解析 redis 配置文件失败", ex);
}
}
public void afterPropertiesSet() throws Exception {
Set<HostAndPort> haps = this.parseHostAndPort();
if (genericObjectPoolConfig == null) {
genericObjectPoolConfig = getGenericObjectPoolConfig();
}
jedisCluster = new JedisCluster(haps, genericObjectPoolConfig);
}
public void setTimeout(String timeout) {
this.timeout = timeout;
}
public void setMaxRedirections(String maxRedirections) {
this.maxRedirections = maxRedirections;
}
public void setAddressKeyPrefix(String addressKeyPrefix) {
this.addressKeyPrefix = addressKeyPrefix;
}
public void setGenericObjectPoolConfig(GenericObjectPoolConfig genericObjectPoolConfig) {
this.genericObjectPoolConfig = genericObjectPoolConfig;
}
}
connect-redis.properties配置文件
address1=20.4.16.10:6379
address2=20.4.16.10:7002
address3=20.4.16.10:7003
address4=20.4.16.10:7004
address5=20.4.16.10:7005
address6=20.4.16.10:7006
然后是对象序列化和反序列化的SerializerUtil.java
package com.ljp.Faction;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import Entity.Man;
public class SerializerUtil {
/**
* 序列化
*
* @param object
* @return
*/
public static byte[] serializeObj(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
throw new RuntimeException("序列化失败!", e);
}
}
public static void main(String[] args) {
Man m = new Man();
m.setAge(121223);
m.setId(35135334L);
m.setName("zhangsan");
byte[] serializeObj = SerializerUtil.serializeObj(m);
Man deserializeObj = (Man) deserializeObj(serializeObj);
System.out.println(deserializeObj.getAge());
System.out.println(deserializeObj.getName());
System.out.println(deserializeObj.getId());
}
/**
* 反序列化
*
* @param bytes
* @return
*/
public static Object deserializeObj(byte[] bytes) {
if (bytes == null) {
return null;
}
ByteArrayInputStream bais = null;
try {
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
throw new RuntimeException("反序列化失败!", e);
}
}
}
这个是我测试序列化的结果
然后就是dao层的持久化了,测试代码,此处省略了dao层,持久化东西放到了sevice中
RedisImp.java
package com.ljp;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
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.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.ljp.Faction.SerializerUtil;
import Entity.Man;
import redis.clients.jedis.JedisCluster;
@Service("redisService")
@Transactional
public class RedisImp implements RedisInterface {
@Autowired
private JedisCluster jedisCluster;
public String set(String... content) {
for (String string : content) {
System.out.println(string);
}
String set = jedisCluster.set(content[0], content[1]);
System.out.println("Redis setString value---- " + set);
return "set";
}
// 序列化存储对象定时时间
public String set(String id, Man m) {
byte[] serializeObj = SerializerUtil.serializeObj(id);
byte[] serialize = SerializerUtil.serializeObj(m);
jedisCluster.setex(serializeObj, 60, serializeObj);
String set = " ";
System.out.println("Redis setString value---- " + set);
return "set";
}
public String get(String... content) {
System.out.println(content[0]);
String string = jedisCluster.get(content[0]);
System.out.println("redis getString value----" + string);
if (StringUtils.isEmpty("string")) {
return null;
}
return string;
}
public Long lpush(String... content) {
Long lpush = jedisCluster.lpush(content[0], content[1]);
return lpush;
}
public List<String> lrange(String... content) {
List<String> lrange = jedisCluster.lrange(content[0], Long.valueOf(content[1]), Long.valueOf(content[1]));
return lrange;
}
public Long sadd(String... content) {
Long sadd = jedisCluster.sadd(content[0], content[1]);
return sadd;
}
public Set<String> smembers(String... content) {
Set<String> smembers = jedisCluster.smembers(content[0]);
// TODO Auto-generated method stub
return smembers;
}
public Long zadd(String... content) {
// TODO Auto-generated method stub
return null;
}
public Set<String> zrange(String... content) {
// TODO Auto-generated method stub
return null;
}
public long delByKey(String key) {
// TODO Auto-generated method stub
return 0;
}
public long delByValue(String... content) {
// TODO Auto-generated method stub
return 0;
}
}
这个操作存储我也看了不少博客才总结的,这是我自己整理出来的可以用的,直接粘贴复制
就行,代码中实现了对象Man的存储。这个和sessian是一样的,想必都会自己转换,如果异常,如果有什么地方不懂或者需要优化的可以联系我