首頁 > 軟體

Spring Cache整合Redis

2020-06-16 17:33:38

redis大家都耳熟能詳了,spring context預設沒有實現redis的cache相關介面,我們需要自己實現,並借助org.springframework.cache.support.SimpleCacheManager進行redis快取管理。

新增jar包:

<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
   <version>2.5.2</version>
  </dependency>cache介面實現:


package org.springframework.cache.demo.redis;

import Java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
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;

public class RedisCache implements Cache {

 private RedisTemplate<String, Object> redisTemplate;
 private String name;

 public RedisTemplate<String, Object> getRedisTemplate() {
  return redisTemplate;
 }

 public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
  this.redisTemplate = redisTemplate;
 }

 public void setName(String name) {
  this.name = name;
 }

 @Override
 public String getName() {
  return this.name;
 }

 @Override
 public Object getNativeCache() {
  return this.redisTemplate;
 }

 @Override
 public ValueWrapper get(Object key) {
  final String keyf = (String) key;
  Object object = null;
  object = redisTemplate.execute(new RedisCallback<Object>() {
   public Object doInRedis(RedisConnection connection) throws DataAccessException {

    byte[] key = keyf.getBytes();
    byte[] value = connection.get(key);
    if (value == null) {
     return null;
    }
    return toObject(value);
   }
  });
  return (object != null ? new SimpleValueWrapper(object) : null);
 }

 @Override
 public void put(Object key, Object value) {
  final String keyf = (String) key;
  final Object valuef = value;
  final long liveTime = 86400;

  redisTemplate.execute(new RedisCallback<Long>() {
   public Long doInRedis(RedisConnection connection) throws DataAccessException {
    byte[] keyb = keyf.getBytes();
    byte[] valueb = toByteArray(valuef);
    connection.set(keyb, valueb);
    if (liveTime > 0) {
     connection.expire(keyb, liveTime);
    }
    return 1L;
   }
  });
 }

 /**
  * 描述 : <Object轉byte[]>. <br>
  * <p>
  * <使用方法說明>
  * </p>
  *
  * @param obj
  * @return
  */
 private byte[] toByteArray(Object obj) {
  byte[] bytes = null;
  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  try {
   ObjectOutputStream oos = new ObjectOutputStream(bos);
   oos.writeObject(obj);
   oos.flush();
   bytes = bos.toByteArray();
   oos.close();
   bos.close();
  } catch (IOException ex) {
   ex.printStackTrace();
  }
  return bytes;
 }

 /**
  * 描述 : <byte[]轉Object>. <br>
  * <p>
  * <使用方法說明>
  * </p>
  *
  * @param bytes
  * @return
  */
 private Object toObject(byte[] bytes) {
  Object obj = null;
  try {
   ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
   ObjectInputStream ois = new ObjectInputStream(bis);
   obj = ois.readObject();
   ois.close();
   bis.close();
  } catch (IOException ex) {
   ex.printStackTrace();
  } catch (ClassNotFoundException ex) {
   ex.printStackTrace();
  }
  return obj;
 }

 @Override
 public void evict(Object key) {
  final String keyf = (String) key;
  redisTemplate.execute(new RedisCallback<Long>() {
   public Long doInRedis(RedisConnection connection) throws DataAccessException {
    return connection.del(keyf.getBytes());
   }
  });
 }

 @Override
 public void clear() {
  redisTemplate.execute(new RedisCallback<String>() {
   public String doInRedis(RedisConnection connection) throws DataAccessException {
    connection.flushDb();
    return "ok";
   }
  });
 }

 @SuppressWarnings("unchecked")
 @Override
 public <T> T get(Object key, Class<T> type) {
  final String keyf = (String) key;
  Object object = null;
  object = redisTemplate.execute(new RedisCallback<Object>() {
   public Object doInRedis(RedisConnection connection) throws DataAccessException {

    byte[] key = keyf.getBytes();
    byte[] value = connection.get(key);
    if (value == null) {
     return null;
    }
    return toObject(value);
   }
  });
  return (T) object;
 }

 @Override
 public ValueWrapper putIfAbsent(Object key, Object value) {
  put(key, value);
  return new SimpleValueWrapper(value);
 }
}
spring設定:


<?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:cache="http://www.springframework.org/schema/cache"
 xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">

 <!-- 啟用快取註解功能,這個是必須的,否則註解不會生效,另外,該註解一定要宣告在spring主組態檔中才會生效 -->
 <cache:annotation-driven cache-manager="cacheManager"/>

 <bean id="userService" class="org.springframework.cache.demo.UserService" />
 
    <!-- spring自己的換管理器,這裡定義了兩個快取位置名稱 ,既注解中的value --> 
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> 
        <property name="caches"> 
            <set> 
                <bean class="org.springframework.cache.demo.redis.RedisCache"> 
                    <property name="redisTemplate" ref="redisTemplate" /> 
                    <property name="name" value="userCache"/> 
                </bean> 
            </set> 
        </property> 
    </bean>
   
    <!-- redis 相關設定 --> 
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> 
        <property name="maxIdle" value="300" />       
        <property name="maxWaitMillis" value="3000" /> 
        <property name="testOnBorrow" value="true" /> 
    </bean> 
    <bean id="connectionFactory" 
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" 
        p:host-name="192.168.1.90" p:port="6379" p:pool-config-ref="poolConfig" 
        p:database="0" />
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> 
        <property name="connectionFactory" ref="connectionFactory" /> 
    </bean> 
</beans>
除了以上方式,在spring-data專案中增加了對redis的支援spring-data-redis,單獨引入依賴:


<dependency>
   <groupId>org.springframework.data</groupId>
   <artifactId>spring-data-redis</artifactId>
   <version>1.4.2.RELEASE</version>
  </dependency>使用spring-data-redis提供的RedisTemplate對redis操作,spring設定如下:


<?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'
 xmlns:c='http://www.springframework.org/schema/c'
 xmlns:p='http://www.springframework.org/schema/p'
 xmlns:cache='http://www.springframework.org/schema/cache'
 xsi:schemaLocation='
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
        '>

 <!-- 啟用快取註解功能,這個是必須的,否則註解不會生效,另外,該註解一定要宣告在spring主組態檔中才會生效 -->
 <cache:annotation-driven cache-manager="cacheManager" />

 <bean id="userService" class="org.springframework.cache.demo.UserService" />

 <!-- 宣告cacheManager -->
 <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"
  c:template-ref="redisTemplate" />

 <!-- redis 相關設定 -->
 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
  <property name="maxIdle" value="300" />
  <property name="maxWaitMillis" value="3000" />
  <property name="testOnBorrow" value="true" />
 </bean>
 <bean id="jedisConnectionFactory"
  class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
  p:host-name="192.168.1.90" p:port="6379" p:pool-config-ref="jedisPoolConfig"
  p:database="0" p:use-pool="true" />

 <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
  p:connection-factory-ref="jedisConnectionFactory" />
</beans>

下面關於Redis的文章您也可能喜歡,不妨參考下:


IT145.com E-mail:sddin#qq.com