自己的项目不敢用公司的redis,只好用java原生的方法,做了一个序列化和反序列化,加了一个简单的泛型,可以实现redis缓存java原生对象了。中间还出现了一个比较奇怪的错误。
上周周末的时候我提交了代码,一切OK,这周周一来的时候,重新跑了一次,出现了空指针
//redisService里面的代码
@Autowired
private JedisSingleFactory jedisSingleFactory;
private Jedis jedis=jedisSingleFactory.getResource();
理论上,这样写,java是要按照从上到下的顺序加载的,也就是说,jedisSingleFactory不可能在还是空的情况下,就被调用getResource方法,来生成jedis。不幸的是,这件事确实发生了,而且由于上周还可以跑通,所以我有道理相信这个加载顺序是不稳定的。本来想在jedisSingleFactory前面加上static,保证加载顺序,可静态成员变量貌似又不能被set,也就不能被spring注入,只好用下面这种方法了
//每个用到jedis链接的地方,都调用该方法,该方法会调用
//jedisSingleFactory(jedisSingleFactory.getJedis()里面是一个单例模式)
public Jedis getJedis() {
if(jedis==null){
jedis=jedisSingleFactory.getJedis();
}
return jedis;
}
解决这个问题,下面就是序列化的事情了,其实也蛮简单的
@Override
public <T> boolean set(String key, T value, int liveTime) {
boolean isGood = true;
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
byte[] bytes = null;
if (value != null) {
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(value);
bytes = baos.toByteArray();
this.getJedis().setex(key.getBytes(), liveTime, bytes);
} catch (Exception e) {
logger.error("序列化对象:{} 出错:{}", value, e.getMessage());
isGood = false;
}
}
return isGood;
}
@Override
public <T> T get(String key) {
ByteArrayInputStream bais = null;
T object = null;
byte[] bytes=this.getJedis().get(key.getBytes());
if(bytes!=null&&bytes.length>0){
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(bais);
object = (T) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
logger.error("反序列化对象:{} 出错:{}", key, e.getMessage());
}catch (ClassNotFoundException e){
logger.error("反序列化对象:{} 出错:{}", key, e.getMessage());
}finally {
return null;//鸡肋一下
}
}
return object;
}
还有就是意识到,在mock数据的时候(主要是在单元测试里面),context.xml里面,需要手动import servlet.xml,不然找不到,因为它本身没有web.xml配置servle的选项。
至于redis的依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.5.0.RELEASE</version>
</dependency>
context.xml配置
<context:property-placeholder location="classpath:redis.properties" />
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:hostName="${redis.host}"
p:port="${redis.port}"
p:password="${redis.pass}"
p:poolConfig-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="connectionFactory" />
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="poolConfig" ref="poolConfig"></constructor-arg>
<constructor-arg name="host" value="localhost"></constructor-arg>
</bean>
<bean id="jedisSingleFactory" class="com.liushuqing.wechat.web.jedis.JedisSingleFactory">
<property name="jedisPool" ref="jedisPool"/>
</bean>
大概就酱紫~其实redisTemplate是不需要配置的,因为我已经手动实现了一个jedis的序列化~ redis的配置是我抄的别人的。。。
\# Redis settings
\#redis的服务器地址
redis.host=localhost
\#redis的服务端口
redis.port=6379
\#密码
redis.pass=**
\#链接数据库
redis.default.db= 0
\#客户端超时时间单位是毫秒
redis.timeout=100000
\#最大连接数
redis.maxTotal=300
\#最大空闲数
redis.maxIdle=100
\#最大建立连接等待时间
redis.maxWaitMillis=1000
\#指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
redis.testOnBorrow=true
写一个单元测试跑一下
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:test-context.xml")
public class SpringRedisTest{
private static final Logger logger= LoggerFactory.getLogger(SpringRedisTest.class);
@Autowired
RedisService redisService;
@Test
public void 测试对象(){
SearchTask searchTask=new SearchTask();
searchTask.setCreateTime(new Date());
searchTask.setFinishTime(new Date());
searchTask.setName("hahahahhaNiha");
String name="Object";
redisService.set(name,searchTask);
SearchTask task= redisService.get(name);
logger.debug("拿到一个对象{},应该是对的!",task.toString());
}
}
一切OK了~