在这里就不做spring框架详细描述,只对用的作解释,有什么问题欢迎来信。
1.pom添加
这里增加spring-data-redis
和jedis
必须要jar包。
org.springframework.data
spring-data-redis
1.3.4.RELEASE
redis.clients
jedis
2.5.2
2.spring 配置
在spring的配置文件applicationContext.xml里加入下面的redis的配置信息。
这里配置redis的一些信息,当然也可以用配置文件来配置
redis.host=192.168.31.4
redis.port=6379
redis.pass=
redis.maxIdle=50
redis.maxActive=50
redis.maxWait=50
redis.testOnBorrow=true
redis.timeout=1000
接下来在配置文件中配置要缓存的对象值,如下:
这里面配置的orderServiceImpl.selectInterests 和 orderServiceImpl.selectInterestsList 分别是redis缓存的名称,下面代码会说到
3.redis缓存配置类
这里增加配置文件中实现的SystemRedisCache ,这里主要对redis的业务的操作方法。
import com.hejia.alauda.utils.SerializableUtil;
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;
import org.springframework.util.StringUtils;
/**
* info:redis缓存配置类
* Created by shang on 2016/11/9.
*/
public class SystemRedisCache implements Cache {
/**
* Redis
*/
private RedisTemplate redisTemplate;
/**
* 缓存名称
*/
private String name;
/**
* 超时时间
*/
private long timeout;
/*
* (non-Javadoc)
* @see org.springframework.cache.Cache#getName()
*/
@Override
public String getName() {
return this.name;
}
/*
* (non-Javadoc)
* @see org.springframework.cache.Cache#getNativeCache()
*/
@Override
public Object getNativeCache() {
// TODO Auto-generated method stub
return this.redisTemplate;
}
/*
* (non-Javadoc)
* @see org.springframework.cache.Cache#get(java.lang.Object)
*/
@Override
public ValueWrapper get(Object key) {
if (StringUtils.isEmpty(key)) {
return null;
} else {
final String finalKey;
if (key instanceof String) {
finalKey = (String) key;
} else {
finalKey = key.toString();
}
Object object = null;
object = redisTemplate.execute(new RedisCallback
这里附带一个工具类的代码,主要对开发中object和list对象的序列化和反序列化。
因为redis不知object和泛型,所有在将对象存入redis时,需要将缓存的数据序列化。
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* info:序列化工具类
* Created by shang on 2016/11/9.
*/
public class SerializableUtil {
/**
* 序列化
*
* @param object
* @return
*/
public static byte[] serialize(Object object) {
if (object == null) {
return null;
}
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
byte[] bytes = null;
try {
// 序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
bytes = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(oos);
close(baos);
}
return bytes;
}
/**
* 反序列化
*
* @param bytes
* @return
*/
public static Object unserialize(byte[] bytes) {
if (bytes == null) {
return null;
}
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(bais);
close(ois);
}
return null;
}
/**
* 序列化 list 集合
*
* @param list
* @return
*/
public static byte[] serializeList(List> list) {
if (list==null||list.size()==0) {
return null;
}
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
byte[] bytes = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
for (Object obj : list) {
oos.writeObject(obj);
}
bytes = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(oos);
close(baos);
}
return bytes;
}
/**
* 反序列化 list 集合
*/
public static List> unserializeList(byte[] bytes) {
if (bytes == null) {
return null;
}
List list = new ArrayList();
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
while (bais.available() > 0) {
Object obj = (Object) ois.readObject();
if (obj == null) {
break;
}
list.add(obj);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close(bais);
close(ois);
}
return list;
}
/**
* 关闭io流对象
*
* @param closeable
*/
public static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
4.缓存service方法
对指定的service方法做缓存,使用方法如下:
@Cacheable(value = "orderServiceImpl.selectInterests",key = "'selectInterests_'+#params.get('user_id')+'_'+#params.get('type')+'_'+#pager.pageNumber")//增加redis缓存
@Override
public Pager selectInterests(Map params, Pager pager) {
System.out.println("select selectInterests class ....");
pager.setList(interestMapper.findInterestListV3(params, pager));
pager.setTotalCount(interestMapper.findCountInterestListV3(params));
return pager;
}
@Cacheable(value = "orderServiceImpl.selectInterestsList",key = "'selectInterestsList_'+#params.get('user_id')+'_'+#params.get('type')+'_'+#params.get('valueDate')")//增加redis缓存
@Override
public List
这上面的两个方法就是spring配置文件里配置的两个缓存,我这里主要是对查询的分页做缓存。
上面的方法只是添加缓存,并10分钟后过期。这里的key是在redis所对应的标识,如果要查询出来可以使用key值来查询。
如果你需要对缓存进行修改和删除,这需要使用@CachePut
和 @CacheEvict
。使用方法如下
Cache注解详解
- @CacheConfig:主要用于配置该类中会用到的一些共用的缓存配置。在这里@CacheConfig(cacheNames = "users"):配置了该数据访问对象中返回的内容将存储于名为users的缓存对象中,我们也可以不使用该注解,直接通过@Cacheable自己配置缓存集的名字来定义。
- @Cacheable:配置了findByName函数的返回值将被加入缓存。同时在查询时,会先从缓存中获取,若不存在才再发起对数据库的访问。该注解主要有下面几个参数:
- value、cacheNames:两个等同的参数(cacheNames为Spring 4新增,作为value的别名),用于指定缓存存储的集合名。由于Spring 4中新增了@CacheConfig,因此在Spring 3中原本必须有的value属性,也成为非必需项了
- key:缓存对象存储在Map集合中的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key = "#p0"):使用函数第一个参数作为缓存的key值,更多关于SpEL表达式的详细内容可参考官方文档
- condition:缓存对象的条件,非必需,也需使用SpEL表达式,只有满足表达式条件的内容才会被缓存,比如:@Cacheable(key = "#p0", condition = "#p0.length() < 3"),表示只有当第一个参数的长度小于3的时候才会被缓存,若做此配置上面的AAA用户就不会被缓存,读者可自行实验尝试。
- unless:另外一个缓存条件参数,非必需,需使用SpEL表达式。它不同于condition参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对result进行判断。
- keyGenerator:用于指定key生成器,非必需。若需要指定一个自定义的key生成器,我们需要去实现org.springframework.cache.interceptor.KeyGenerator接口,并使用该参数来指定。需要注意的是:该参数与key是互斥的
- cacheManager:用于指定使用哪个缓存管理器,非必需。只有当有多个时才需要使用
- cacheResolver:用于指定使用那个缓存解析器,非必需。需通过org.springframework.cache.interceptor.CacheResolver接口来实现自己的缓存解析器,并用该参数指定。
除了这里用到的两个注解之外,还有下面几个核心注解:
- @CachePut:配置于函数上,能够根据参数定义条件来进行缓存,它与@Cacheable不同的是,它每次都会真是调用函数,所以主要用于数据新增和修改操作上。它的参数与@Cacheable类似,具体功能可参考上面对@Cacheable参数的解析
- @CacheEvict:配置于函数上,通常用在删除方法上,用来从缓存中移除相应数据。除了同@Cacheable一样的参数之外,它还有下面两个参数:
- allEntries:非必需,默认为false。当为true时,会移除所有数据
- beforeInvocation:非必需,默认为false,会在调用方法之后移除数据。当为true时,会在调用方法之前移除数据。
5.结束
上面这些就是使用spring cache对redis做缓存的用法。如果在你的项目里需要可以试试一番,这里没有使用Ecache缓存是因为项目使用分布式部署,如果是本地缓存就不行了,所以使用redis做缓存,统一存取。
有什么问题欢迎给我来信或留言!