版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38362455/article/details/81287489
一.spring cache和cache+redis的区别
1. 缓存级别不同
Spring cache是代码级的缓存,他一般是使用一个ConcurrentMap。也就是说实际上还是是使用JVM的内存来缓存对象的,那么肯定会造成大量的内存消耗。但是使用方便。
Redis 作为一个缓存服务器,是内存级的缓存。它是使用单纯的内存来进行缓存。
2. sprirng cache+redis的好处
那么Spring cache +redis的好处显而易见了。既可以很方便的缓存对象,同时用来缓存的内存的是使用redis的内存,不会消耗JVM的内存,提升了性能。当然这里Redis不是必须的,换成其他的缓存服务器一样可以,只要实现Spring的Cache类,并配置到XML里面就行了。
下面开始整合cache+redis
1.在spring-mvc.xml中加入配置
<!--开启缓存注解-->
<cache:annotation-driven cache-manager="cacheManager"/>
<!-- 定义缓存管理 -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<!--name对应的名称要在类或方法的注解中使用-->
<bean class="com.gcol.qy.core.annotation.RedisCache">
<property name="redisTemplate" ref="redisTemplate" />
<property name="name" value="myCache"/>
</bean>
</set>
</property>
</bean>
几点说明:
1.com.gcol.qy.core.annotation.RedisCache 这个类是我们自己写的类 他实现了cache接口用于操作redis 如下:
2.redisTemplate 配置在spring-redis.xml 中配置好的bean 这里不作展示,不会配置redisTemplate的小伙伴去自行百度
3.<property name="name" value="myCache"/>
myCache 后面使用@Cacheable会用到
package com.gcol.qy.core.annotation;
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;
/**
* @Author: Xuhao
* @Date: Created in 14:29 2018/7/30
*/
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() {
// TODO Auto-generated method stub
return this.name;
}
@Override
public Object getNativeCache() {
// TODO Auto-generated method stub
return this.redisTemplate;
}
@Override
public ValueWrapper get(Object key) {
// TODO Auto-generated method stub
System.out.println("get key");
final String keyf = key.toString();
Object object = null;
object = redisTemplate.execute(new RedisCallback<Object>() {
@Override
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 <T> T get(Object key, Class<T> type) {
return null;
}
@Override
public void put(Object key, Object value) {
// TODO Auto-generated method stub
System.out.println("put key");
final String keyf = key.toString();
final Object valuef = value;
final long liveTime = 86400;
redisTemplate.execute(new RedisCallback<Long>() {
@Override
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) {
// TODO Auto-generated method stub
System.out.println("del key");
final String keyf = key.toString();
redisTemplate.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection)
throws DataAccessException {
return connection.del(keyf.getBytes());
}
});
}
@Override
public void clear() {
// TODO Auto-generated method stub
System.out.println("clear key");
redisTemplate.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection)
throws DataAccessException {
connection.flushDb();
return "ok";
}
});
}
}
测试Dao
@Override
@Cacheable(value = "myCache",key = "#openid")
public List<Object> findListCDKeyByOpenid(String openid) {
Session session = super.getSession();
String sql ="SELECT " +
"pri.cd_key as cdKey, " +
"war.award_name as awardName," +
"war.award_content as awardContent " +
" FROM wechat_test_prizes pri " +
" JOIN " +
" wechat_test_awards war on(pri.award_id=war.id)" +
" WHERE " +
"pri.id in (" +
" SELECT prize_id FROM wechat_user_lottery_record" +
" WHERE openid =:openid and Activity_code = 'CHILDFQ_QUIZ'" +
");";
SQLQuery sqlQuery = session.createSQLQuery(sql);
sqlQuery.setParameter("openid",openid);
sqlQuery.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return sqlQuery.list();
}
第一次调用如下:
第二次如下:没执行sql 直接从redis里获取的