1.spring+redis集成配置
1.1、导入依赖
<properties>
<spring-data-redis.version>1.7.1.RELEASE</spring-data-redis.version>
<jedis.version>2.9.0</jedis.version>
<jackson.version>2.9.3</jackson.version>
...
</properties>
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-pool2</artifactId>
<groupId>org.apache.commons</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>${spring-data-redis.version}</version>
</dependency>
<!-- jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
<exclusions>
<exclusion>
<artifactId>jackson-annotations</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
...
</dependencies>
1.2、在src/main/resources下面创建spring-redis.xml文件
1.3、在相同目录下创建redis.properties文件(文件内容如下:)
#ip地址
redis.hostName=127.0.0.1
#端口号
redis.port=6379
#如果有密码
redis.password=
#客户端超时时间单位是毫秒 默认是2000
redis.timeout=10000
#redis缓存数据过期时间单位秒
redis.expiration=3600
##################### redis连接池配置 ###########################################
#最大空闲数
redis.maxIdle=300
#连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal
#redis.maxActive=600
#控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性
redis.maxTotal=1000
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWaitMillis=1000
#连接的最小空闲时间 默认1800000毫秒(30分钟)
redis.minEvictableIdleTimeMillis=300000
#每次释放连接的最大数目,默认3
redis.numTestsPerEvictionRun=1024
#逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
redis.timeBetweenEvictionRunsMillis=30000
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
redis.testOnBorrow=true
#在空闲时检查有效性, 默认false
redis.testWhileIdle=true
#redis集群配置
#redis.sentinel.host1=172.20.1.230
#redis.sentinel.port1=26379
#redis.sentinel.host2=172.20.1.231
#redis.sentinel.port2=26379
#redis.sentinel.host3=172.20.1.232
#redis.sentinel.port3=26379
1.4、编写相关内容如下(注:文中第一步,不需要配置,需要在spring.xml文件中配置多配置文件.properties文件引入方式: 代码在1.4.1中)
<?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:contet="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">
<!-- 1.导入redis配置文件 -->
<!-- <contet:property-placeholder location="redis.properties"/>-->
<!-- 2.创建redis数据库连接池 -->
<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}"/>
<!--逐出连接的最小空闲时间 默认1800000毫秒(30分钟)-->
<property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"/>
<!--每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3-->
<property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"/>
<!--逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1-->
<property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"/>
<!--是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个-->
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
<!--在空闲时检查有效性, 默认false -->
<property name="testWhileIdle" value="${redis.testWhileIdle}"/>
</bean>
<!-- 3.创建redis连接工厂类 -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
destroy-method="destroy">
<property name="poolConfig" ref="poolConfig"/>
<!--IP地址 -->
<property name="hostName" value="${redis.hostName}"/>
<!--端口号 -->
<property name="port" value="${redis.port}"/>
<!--如果Redis设置有密码 -->
<property name="password" value="${redis.password}"/>
<!--客户端超时时间单位是毫秒 -->
<property name="timeout" value="${redis.timeout}"/>
</bean>
<!-- 4.创建redistemplate模板类 -->
<!-- redis操作模板,使用该对象可以操作redis -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<!--redis是key-value-->
<property name="connectionFactory" ref="connectionFactory"/>
<!--如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!! -->
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
</property>
<!--开启事务 -->
<property name="enableTransactionSupport" value="false"/>
</bean>
<!-- 5.配置Redis缓存管理器 -->
<!-- <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg name="redisOperations" ref="redisTemplate" />
<!--redis缓存数据过期时间单位秒-->
<!-- <property name="defaultExpiration" value="${redis.expiration}" />
<!--是否使用缓存前缀-->
<!-- <property name="usePrefix" value="true"/>
<!--设置缓存前缀-->
<!-- <property name="cachePrefix">
<bean class="org.springframework.data.redis.cache.DefaultRedisCachePrefix">
<constructor-arg index="0" value="-cache-"/>
</bean>
</property>
</bean> -->
<!-- 6.配置自定义Key生成器CacheKeyGenerator -->
<!-- <bean id="cacheKeyGenerator" class="com.zking.ssm.util.CacheKeyGenerator"/> -->
<!--7.启用注解式缓存-->
<!-- <cache:annotation-driven cache-manager="redisCacheManager" key-generator="cacheKeyGenerator"/> -->
</beans>
1.4.1、引入外部多文件方式
<!--1. 引入外部多文件方式 -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:redis.properties</value>
</list>
</property>
</bean>
1.5、前言:在spring-mvc中配置对应json对象转换器
<!--配置JSON对象接收-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<!-- json转换器 -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
1.5、案例操作(注:能直接加入对象的原因是在Spring-mvc.xml文件中配置json转换器,而且操作在测试类中进行)
//导入dao层接口类
@Autowired
private IBookMapper bookMapper;
@Autowired
private RedisTemplate<String,Object> template;
@Test
public void test2(){
//mybati相关操作
Book book = bookMapper.queryBook(1);
//添加到redis缓存中
template.opsForValue().set("book",book); //templae的配置中还有opsForSet、opsForHash、opsForZset、opsForList相关操作
//获取redis中的book
Book book = (Book) template.opsForValue().get("book");
}
2、启用spring注解式声明
2.1、解注1.4中5、6、7步的代码
2.2、在util下创建CacheKeyGenerator类(这是在spring-redis.xml中的第六步引入的全局key生成类)
2.3、编写如下代码
package com.zking.ssm.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.util.ClassUtils;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
@Slf4j
public class CacheKeyGenerator implements KeyGenerator {
// custom cache key
public static final int NO_PARAM_KEY = 0;
public static final int NULL_PARAM_KEY = 53;
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder key = new StringBuilder();
key.append(target.getClass().getSimpleName()).append(".").append(method.getName()).append(":");
if (params.length == 0) {
key.append(NO_PARAM_KEY);
} else {
int count = 0;
for (Object param : params) {
if (0 != count) {//参数之间用,进行分隔
key.append(',');
}
if (param == null) {
key.append(NULL_PARAM_KEY);
} else if (ClassUtils.isPrimitiveArray(param.getClass())) {
int length = Array.getLength(param);
for (int i = 0; i < length; i++) {
key.append(Array.get(param, i));
key.append(',');
}
} else if (ClassUtils.isPrimitiveOrWrapper(param.getClass()) || param instanceof String) {
key.append(param);
} else {//Java一定要重写hashCode和eqauls
key.append(param.hashCode());
}
count++;
}
}
String finalKey = key.toString();
log.debug("using cache key={}", finalKey);
return finalKey;
}
}
3、缓存注解
注:各注解作用区域都又说明,请按照文档要求明确注解位置
3.1.@CacheConfig
@CacheConfig是一个类级别的注解,允许共享缓存的名称、KeyGenerator、CacheManager和CacheResolver。
参数 | 说明 |
---|---|
value | 缓存位置的一段名称,不能为空 |
key | 缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL |
3.2.@Cacheable
@Cacheable配置在方法或类上,作用:本方法执行后,先去缓存看有没有数据,如果没有,从数据库中查找出来,给缓存中存一份,返回结果,本次方法执行,在缓存未过期情况下,先在缓存中查找,有的话直接返回,没有的话从数据库查找。
参数 | 说明 |
---|---|
value | 缓存位置的一段名称,不能为空 |
key | 缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL |
keyGenerator | 指定key的生成策略 |
condition | 触发条件,满足条件就加入缓存,默认为空,表示全部都加入缓存,支持SpEL |
示例:
@Cacheable(value="selectByPrimaryKey",key="'selectOne-'+#bookId",condition="#bookId>90")
@Override
public Book selectByPrimaryKey(Integer bookId) {
Book book = bookMapper.selectByPrimaryKey(bookId);
return book;
}
3.3.@CachePut
@CachePut类似于更新操作,即每次不管缓存中有没有结果,都从数据库查找结果,并将结果更新到缓存,并返回结果。
参数 | 说明 |
---|---|
value | 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 |
key | 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 |
condition | 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 |
示例:
@CachePut(value="selectByPrimaryKey",key="'selectOne-'+#bookId",condition="#bookId>90")
@Override
public Book selectByPrimaryKey(Integer bookId) {
Book book = bookMapper.selectByPrimaryKey(bookId);
return book;
}
3.4.@CacheEvict
@CacheEvict用来清除用在本方法或者类上的缓存数据(用在哪里清除哪里)。
参数 | 说明 |
---|---|
value | 缓存位置的一段名称,不能为空 |
key | 缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL |
condition | 触发条件,满足条件就加入缓存,默认为空,表示全部都加入缓存,支持SpEL |
allEntries | true表示清除value中的全部缓存,默认为false |
示例一:清空指定缓存
@CacheEvict(value="selectByPrimaryKey")
@Override
public void delete(Integer bookId) {
System.out.println("被删除了...");
}
示例二:清空所有缓存
@CacheEvict(value="selectByPrimaryKey",allEntries = true)
@Override
public void delete(Integer bookId) {
System.out.println("被删除了...");
}