在项目中,我们经常需要将一些常用的数据使用缓存起来,避免频繁的查询数据库造成效率低下。spring 为我们提供了一套基于注解的缓存实现,方便我们实际的开发。我们可以扩展spring的cache接口以达到使用redis来做缓存的效果。
步骤:
1.编写一个类用于实现 org.springframework.cache.Cache 这个接口
2.编写一个类实现 org.springframework.cache.CacheManager 这个接口或继承 org.springframework.cache.support.AbstractCacheManager这个类
3.在配置文件中进行配置。
代码:
1.使用redis实现spring的cache接口 -- 数据以hash的方式存入到redis中
package com.huan.redis.springcache; import org.springframework.cache.Cache; import org.springframework.cache.support.SimpleValueWrapper; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; /** * 自定义redis缓存 * * @描述 * @作者 huan * @时间 2016年6月26日 - 下午2:14:26 */ public class RedisCache implements Cache { private JedisPool jedisPool; /** 缓存的过期时间,单位是秒 */ private int timeouts; public void setJedisPool(JedisPool jedisPool) { this.jedisPool = jedisPool; } public int getTimeouts() { return timeouts; } public void setTimeouts(int timeouts) { this.timeouts = timeouts; } private String name; public void setName(String name) { this.name = name; } @Override public String getName() { return name; } @Override public Object getNativeCache() { return jedisPool; } @Override public ValueWrapper get(Object key) { ValueWrapper result = null; Jedis jedis = null; try { jedis = jedisPool.getResource(); String value = jedis.hget(getName(), (String) key); if (value != null) { result = new SimpleValueWrapper(value); } } catch (Exception e) { e.printStackTrace(); } finally { if (null != jedis) { jedis.close(); } } return result; } @Override public void put(Object key, Object value) { String cacheKey = (String) key; String cacheValue = (String) value; Jedis jedis = null; try { jedis = jedisPool.getResource(); jedis.hset(getName(), cacheKey, cacheValue); jedis.expire(getName(), getTimeouts()); } catch (Exception e) { e.printStackTrace(); } finally { if (null != jedis) { jedis.close(); } } } @Override public void evict(Object key) { if (null != key) { Jedis jedis = null; try { jedis = jedisPool.getResource(); jedis.hdel(getName(), (String) key); } catch (Exception e) { e.printStackTrace(); } finally { if (null != jedis) { jedis.close(); } } } } @Override public void clear() { Jedis jedis = null; try { jedis = jedisPool.getResource(); jedis.hdel(getName()); } catch (Exception e) { e.printStackTrace(); } finally { if (null != jedis) { jedis.close(); } } } }
2.实现自己的缓存管理器
package com.huan.redis.springcache; import java.util.Collection; import org.springframework.cache.Cache; import org.springframework.cache.support.AbstractCacheManager; /** * 继承spring的抽象缓存管理器,用于实现我们自己的缓存管理 * @描述 * @作者 huan * @时间 2016年6月26日 - 下午2:17:15 */ public class RedisCacheManager extends AbstractCacheManager{ private Collection<? extends RedisCache> caches; public void setCaches(Collection<? extends RedisCache> caches) { this.caches = caches; } @Override protected Collection<? extends Cache> loadCaches() { return this.caches; } }
3.配置文件中进行配置
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> <context:annotation-config /> <context:component-scan base-package="com.huan.redis" /> <cache:annotation-driven cache-manager="cacheManager"/> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="testWhileIdle" value="true" /> <property name="minEvictableIdleTimeMillis" value="60000" /> <property name="timeBetweenEvictionRunsMillis" value="30000" /> <property name="numTestsPerEvictionRun" value="-1" /> <property name="maxTotal" value="8" /> <property name="maxIdle" value="8" /> <property name="minIdle" value="0" /> </bean> <bean id="jedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg ref="jedisPoolConfig" /> <constructor-arg value="192.168.1.5" /> </bean> <bean id="cacheManager" class="com.huan.redis.springcache.RedisCacheManager"> <property name="caches"> <set> <bean class="com.huan.redis.springcache.RedisCache"> <property name="jedisPool" ref="jedisPool" /> <property name="name" value="usersCache" /> <property name="timeouts" value="3600" /> </bean> <bean class="com.huan.redis.springcache.RedisCache"> <property name="jedisPool" ref="jedisPool" /> <property name="name" value="booksCache" /> <property name="timeouts" value="3600" /> </bean> </set> </property> </bean> </beans>
注意:1. <cache:annotation-driven cache-manager="cacheManager"/>这一句用于开启spring的缓存注解
2.redis.clients.jedis.JedisPool 用于配置redis的地址和端口,默认端口是6379,如果自己的redis不是这个端口,可以选择JedisPool中适当的构造方法进行配置
4.编写业务方法 -- UserService类中比较简单,就是UserServiceImpl中方法的申明。
package com.huan.redis.service; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; /** * 测试业务员方法 * @描述 * @作者 huan * @时间 2016年6月26日 - 下午3:20:58 */ @Service public class UserServiceImpl implements UserService { /** 将数据放入到usersCache这个缓存中,缓存的key使用spirng的spel表达式获取值 */ @Override @Cacheable(value = "usersCache", key = "#loginName") public String getUser(String loginName) { System.out.println("no user cache:" + loginName); return loginName; } @Override public String getUserNoCache(String loginName) { return getUser(loginName); } @Override @Cacheable(value = "booksCache", key = "#bookId") public String addBook(String bookId) { System.out.println("no book cache:" + bookId); return bookId; } /** 使usersCache中的缓存key为#loginName这个值的缓存失效 */ @Override @CacheEvict(value = "usersCache", key = "#loginName") public void evictUser(String loginName) { System.out.println("evict cache loginName:" + loginName); } }
5.进行测试