天天看點

Spring 整合 Redis

pom建構:

<dependency>  
        <groupId>org.springframework.data</groupId>  
        <artifactId>spring-data-redis</artifactId>  
        <version>1.6.0.RELEASE</version>  
    </dependency>  
    <dependency>  
        <groupId>org.springframework</groupId>  
        <artifactId>spring-test</artifactId>  
        <version>3.1.2.RELEASE</version>  
        <scope>test</scope>  
    </dependency>  
      
    <dependency>  
        <groupId>redis.clients</groupId>  
        <artifactId>jedis</artifactId>  
        <version>2.9.0</version>  
    </dependency>  
      
     <dependency>  
        <groupId>junit</groupId>  
        <artifactId>junit</artifactId>  
        <version>4.8.2</version>  
        <scope>test</scope>  
    </dependency>             

spring配置檔案(applicationContext.xml):

<context:property-placeholder location="classpath:redis.properties" />  
	<!-- redis config start -->
	<!-- 啟用緩存注解功能,這個是必須的,否則注解不會生效,另外,該注解一定要聲明在spring主配置檔案中才會生效 -->
	<cache:annotation-driven cache-manager="cacheManager" />


	<!-- 配置JedisPoolConfig執行個體 -->
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="${redis.maxTotal}" />
		<property name="maxIdle" value="${redis.maxIdle}" />
		<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
		<property name="testOnBorrow" value="${redis.testOnBorrow}" />
		<property name="testOnReturn" value="${redis.testOnReturn}" />
		<!-- <property name="testWhileIdle" value="true"/> -->
	</bean>


	<!-- 配置JedisConnectionFactory -->
	<bean id="JedisConnectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
		p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"
		p:pool-config-ref="jedisPoolConfig" p:timeout="${redis.timeout}" />


	<!-- 配置RedisTemplate -->
	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="JedisConnectionFactory" />
	</bean>

	<!-- spring自己的緩存管理器,這裡定義了緩存位置名稱 ,即注解中的value -->
	<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
		<property name="caches">
			<set>
				<!-- 這裡可以配置多個redis -->
				<!-- <bean class="com.cn.util.RedisCache"> <property name="redisTemplate" 
					ref="redisTemplate" /> <property name="name" value="default"/> </bean> -->
				<bean class="com.github.util.RedisCache">
					<property name="redisTemplate" ref="redisTemplate" />
					<property name="name" value="common" />
					<!-- common名稱要在類或方法的注解中使用 -->
				</bean>
			</set>
		</property>
	</bean>
	<!-- redis config end -->           

開啟Spring采用CGLIB代理

<!-- 配置使Spring采用CGLIB代理 -->

<aop:aspectj-autoproxy proxy-target-class="true" />

redis.properties:

# Redis settings
redis.host=192.168.1.39
redis.port=6379
redis.pass=jay
redis.timeout=0

redis.maxIdle=300
redis.maxTotal=50
redis.maxWaitMillis=1000
redis.testOnBorrow=true
redis.testOnReturn=true           

Java代碼:

自己實作的緩存類 RedisCache

package com.github.util;

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) {
		System.out.println("get key");
		final String keyf = key.toString();
		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) {
		System.out.println("put key");
		final String keyf = key.toString();
		final Object valuef = value;
		final long liveTime = 10 * 6;		//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;
			}
		});
	}

	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;
	}

	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) {
		System.out.println("del key");
		final String keyf = key.toString();
		redisTemplate.execute(new RedisCallback<Long>() {
			public Long doInRedis(RedisConnection connection)
					throws DataAccessException {
				return connection.del(keyf.getBytes());
			}
		});
	}

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

	@Override
	public <T> T get(Object key, Class<T> type) {
		return null;
	}

	@Override
	public ValueWrapper putIfAbsent(Object key, Object value) {
		return null;
	}

}           

注意:

spring配置檔案中的

<bean class="com.github.util.RedisCache">

<property name="redisTemplate" ref="redisTemplate" />

<property name="name" value="common" />

<!-- common名稱要在類或方法的注解中使用 -->

</bean>

name 的value 可以自定義 。後面方法注解的value要和這個對應

對Redis不懂的看這篇文章.

這裡配置就完成了。可以直接在service方法上面開啟注解:

有4個注解@Cacheable,@CachePut , @CacheEvict,@CacheConfig

@Cacheable、@CachePut、@CacheEvict 注釋介紹

@Cacheable 作用和配置方法

@Cacheable 的作用 主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存

@Cacheable 主要的參數

value 緩存的名稱,在 spring 配置檔案中定義,必須指定至少一個例如:這裡和上面的name 的value對應,樓主這裡寫的是common

@Cacheable(value=”mycache”) 或者

@Cacheable(value={”cache1”,”cache2”}

key 緩存的 key,可以為空,如果指定要按照 SpEL 表達式編寫,如果不指定,則預設按照方法的所有參數進行組合例如:

@Cacheable(value=”testcache”,key=”#userName”)

condition 緩存的條件,可以為空,使用 SpEL 編寫,傳回 true 或者 false,隻有為 true 才進行緩存例如:

@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

------------------------------------------------------------

--

@CachePut 作用和配置方法

@CachePut 的作用 主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存,和 @Cacheable 不同的是,它每次都會觸發真實方法的調用

@CachePut 主要的參數

value 緩存的名稱,在 spring 配置檔案中定義,必須指定至少一個例如:

@CachePut 不同的是不管有沒有緩存,都會調用方法.使用于 資料庫的插入

//

@CacheEvict 作用和配置方法

@CachEvict 的作用 主要針對方法配置,能夠根據一定的條件對緩存進行清空

@CacheEvict 主要的參數

@CachEvict(value=”mycache”) 或者

@CachEvict(value={”cache1”,”cache2”}

@CachEvict(value=”testcache”,key=”#userName”)

condition 緩存的條件,可以為空,使用 SpEL 編寫,傳回 true 或者 false,隻有為 true 才清空緩存例如:

@CachEvict(value=”testcache”,

condition=”#userName.length()>2”)

allEntries 是否清空所有緩存内容,預設為 false,如果指定為 true,則方法調用後将立即清空所有緩存例如:

@CachEvict(value=”testcache”,allEntries=true)

beforeInvocation 是否在方法執行前就清空,預設為 false,如果指定為 true,則在方法還沒有執行的時候就清空緩存,預設情況下,如果方法執行抛出異常,則不會清空緩存例如:

@CachEvict(value=”testcache”,beforeInvocation=true)

知道你們注意到一個問題沒有,就是所有的@Cacheable()裡面都有一個

value=“xxx”的屬性,這顯然如果方法多了,寫起來也是挺累的,如果可以一次性聲明完 那就省事了,

是以,有了@CacheConfig這個配置,

@CacheConfig

is a class-level annotation that allows to share the cache names,不過不用擔心,如果你在你的方法寫别的名字,那麼依然以方法的名字為準。

注釋在類上面

@CacheConfig(cacheNames = "common")

樓主自己打包一份給大家參考下吧!!!