spring整合redis是同过jedis操作redis的,同时它还提供了对redis缓存的注解支持:
1.核心注解:
@Cacheable:被标注的方法表示,每次执行到该方法会先判断有没有缓存,有直接返回缓存的值,而不直接执行方法体,如果没有,则执行方法体,并缓存返回值
属性:value:指定缓存名
key:指定key,往往设置成方法参数
key生成策略:如若未指定key,则使用默认的key生成策略.可以自定义key生成策略.
condition:条件判断,
@CachePut:更新指定缓存,每次执行到该方法,都会执行方法体,并更新指定的缓存
属性:同上
@CacheEvict:删除缓存,执行完方法体后并删除指定的缓存
属性:同上
allEntries :设置为true时,忽略所有key,删除所有指定缓存名的缓存
注解的属性value+key是redis里缓存的Key是的一部分
注解详解参考:spring的@Cacheable @Cacheput @CacheEvict详解
2.环境配置:
启动redis:
1.pom.xml引入依赖
<!--redis相关 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.8.6.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
2.redis.properties
redis.host=127.0.0.1
redis.port=6379
redis.sentinel.port=26879
#redis.pwd= //如有密码可填写
redis.database=0
redis.timeout=1000
redis.userPool=true
redis.defaultExpiration=3000
redis.transactionAware=true
redis.userPrefix=true
redis.pool.maxIdle=100
redis.pool.minIdle=10
redis.pool.maxTotal=200
redis.pool.maxWaitMillis=10000
redis.pool.minEvictableIdleTimeMillis=300000
redis.pool.numTestsPerEvictionRun=10
redis.pool.timeBetweenEvictionRunsMillis=30000
redis.pool.testOnBorrow=true
redis.pool.testOnReturn=true
redis.pool.testWhileIdle=true
2.配置spring容器:application-redis.xml
可能要更改的位置:
1.注意自己redis.properties的位置更改加载的位置
<?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: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">
<!-- 如果在其他地方定义了该标签,请去定义了的地方配置加载该配置文件,否则会报错,因为此标签不支持配置多个 -->
<context:property-placeholder location="classpath:redis.properties" />
<!-- Redis -->
<!-- 连接池参数 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.pool.maxIdle}" />
<property name="minIdle" value="${redis.pool.minIdle}" />
<property name="maxTotal" value="${redis.pool.maxTotal}" />
<property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}" />
<property name="minEvictableIdleTimeMillis" value="${redis.pool.minEvictableIdleTimeMillis}"></property>
<property name="numTestsPerEvictionRun" value="${redis.pool.numTestsPerEvictionRun}"></property>
<property name="timeBetweenEvictionRunsMillis" value="${redis.pool.timeBetweenEvictionRunsMillis}"></property>
<property name="testOnBorrow" value="${redis.pool.testOnBorrow}" />
<property name="testOnReturn" value="${redis.pool.testOnReturn}" />
<property name="testWhileIdle" value="${redis.pool.testWhileIdle}"></property>
</bean>
<!-- jedis单机版 -->
<bean id="redisClient" class="redis.clients.jedis.JedisPool"> <!--配置连接池 -->
<constructor-arg name="host" value="${redis.host}"></constructor-arg>
<constructor-arg name="port" value="${redis.port}"></constructor-arg>
<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
</bean>
<!-- 配置连接jedis工厂 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="jedisPoolConfig" />
<property name="hostName" value="${redis.host}" />
<property name="port" value="${redis.port}" />
<!-- <property name="password" value="${redis.pwd}" /> 密码-->
<property name="usePool" value="${redis.userPool} " />
<property name="database" value="${redis.database}" />
<property name="timeout" value="${redis.timeout}" />
</bean>
<!-- 配置redis模板 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
<!-- redis事务支持 -->
<property name="enableTransactionSupport" value="false" />
</bean>
<!-- 支持注解操作的redis配置=======================↓↓↓ -->
<!-- cache注解驱动 注意需导入相应的命名空间否则会报错-->
<cache:annotation-driven/>
<!-- 配置cacheManager -->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg ref="redisTemplate"/>
<property name="defaultExpiration" value="${redis.defaultExpiration}"/>
<property name="transactionAware" value="${redis.transactionAware}"/>
<property name="usePrefix" value="${redis.userPrefix}"/>
</bean>
</beans>
使用方法:
为了简化测试,我这里就不定义dao层了,仅定义service层和controller层(就假装service的返回值为调用的dao返回的结果吧)
定义测试 service层:
接口:
public interface IRedisService {
public String cacheable(int key) throws Exception;
public String cacheEvict(int key) throws Exception;
public String cachePut(int key) throws Exception;
}
实现类
@Service
public class RedisServiceImpl implements IRedisService{
@Override
@Cacheable(value="testCache",key="#key") //@表示当前方法的返回值是会被缓存在哪个Cache 上 key为键
public String cacheable(int key) throws Exception {
System.out.println("cacheable方法体执行");
return "Cacheable"+key;
}
@Override
@CachePut(value="testCache",key="#key") //@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
public String cachePut(int key) throws Exception {
key++;
System.out.println("CachePut方法体执行:key++");
return "CachePut更新成功"+key;
}
@Override
@CacheEvict(value="testCache",allEntries=true) // allEntries=true,忽略 key删除缓存cacheable
public String cacheEvict(int key) throws Exception {
System.out.println("cacheEvict执行清楚缓存"+key);
return "CacheEvict清除成功";
}
}
controller层:
@Controller
public class CacheController {
@Autowired
private IRedisService rs;
@RequestMapping("/able") //常应用场景:查询
@ResponseBody
public String testCacheAble() throws Exception {
String cacheable = rs.cacheable(1);
System.out.println(cacheable);
return "testCacheable";
}
@RequestMapping("/put")//常应用场景 更新,修改
@ResponseBody
public String put() throws Exception {
String put = rs.cachePut(1);
System.out.println(put);
return "testCachePut";
}
@RequestMapping("/evict") //常应用场景 更新,修改
@ResponseBody
public String evict() throws Exception {
String evict = rs.cacheEvict(1);
System.out.println("");
return "testCacheAble";
}
}
测试:
启动项目后第一次访问 /able
第一次访问执行了service的方法体,并缓存了结果"Cacheable1" 所以输出:
第二次访问/able
因为第一次访问时根据指定value和key缓存了值,第二次访问的时候参数没变,所以有对应的缓存直接返回缓存的值,而没有执行方法体,所以只输出"Cacheable"
再依次访问/put,/able
执行了更新的方法的方法体,并修改了缓存的值为"CachepUT更新成功2"
缓存的值被更新成了"CachepUT更新成功2"
再依次执行 /evict ,/able 可见结果: