作用: 保证数据时效性的前提下, 提高查询效率; 减少查询数据库的次数, 减轻数据库压力;
原理: 基于Proxy/AspectJ动态代理技术的AOP思想(面向切面编程), 在不改变目标方法的前提下在其切面进行缓存的增删改查(在服务方法执行前查询缓存, 在服务方法执行后添加缓存, 或者清除缓存);
用法:
1. spring cache实现有基于XML/注解实现AOP;
2. CacheManager负责对缓存的增删改查, CacheManager的缓存的介质可配置, 如: ConcurrentMap/EhCache/Redis等;
org.springframework.data
spring-data-redis
1.6.2.RELEASE
redis.clients
jedis
2.9.0
com.fasterxml.jackson.core
jackson-core
2.9.2
com.fasterxml.jackson.core
jackson-databind
2.9.2
com.fasterxml.jackson.core
jackson-annotations
2.9.2
commons-logging
commons-logging
1.2
log4j
log4j
1.2.17
package com.csdn.learn.springcache;
import com.csdn.learn.annocache.Account;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
/**
* 使用@Cacheable, @CachePut, @CacheEvict, @CacheConfig spring通过AOP对方法进行缓存管理
* @author liudong
* @date 2018-04-27
*/
public class AccountService {
/**
* 使用了一个缓存名叫 accountCache
* key condition ,前面的 # 号代表这是一个 SpEL 表达式
* @param userName
* @return
*/
@Cacheable(value = "accountCache", key = "#userName", condition = "#userName.length() <= 4")
public Account getAccountByName(String userName) {
// 方法内部实现不考虑缓存逻辑,直接实现业务
System.out.println("real querying db..." + acctName + "+" + password);
return new Account(acctName);
}
/**
* 更新 accountCache 缓存
* @param account dd
*/
@CachePut(value = "accountCache", key = "#account.getName()")
public void updateAccount(Account account) {
System.out.println("real update db..." + account.getName());
}
/**
* reload 清空 accountCache 缓存
*/
@CacheEvict(value = "accountCache", allEntries = true)
public void reload() {
}
}
package com.csdn.learn.annocache;
import java.io.Serializable;
/**
* 首先定义一个实体类:账号类,具备基本的 id 和 name 属性,且具备 getter 和 setter 方法
* @author liudong
* @date 2018-04-27
*/
public class Account implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private String password;
public Account() {
super();
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Account(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
package com.csdn.learn.rediscacheanno;
import com.csdn.learn.annocache.Account;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
public class Main {
public static void main(String[] args) {
// 加载 spring 配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("spring-cache.xml");
AccountService s = (AccountService) context.getBean("accountServiceBean");
// 第一次查询,应该走数据库
System.out.print("first query...");
s.getAccountByName("somebody");
// 第二次查询,应该不查数据库,直接返回缓存的值
System.out.print("second query...");
s.getAccountByName("somebody");
System.out.println();
// TODO 自行测试@CachePut及@CacheEvict
// 测试redisTemplate
RedisTemplate redisTemplate = (RedisTemplate) context.getBean("redisTemplate");
// redis中存取字符串
redisTemplate.opsForValue().set("redis2", "ceshiRedis222");
System.out.println(redisTemplate.opsForValue().get("redis2"));
// redis中存取实体类
redisTemplate.opsForValue().set("account", new Account("ceshi 123"));
System.out.println(redisTemplate.opsForValue().get("account"));
}
}
#============================#
#==== Redis settings ====#
#============================#
#redis 服务器 IP
redis.host=127.0.0.1
#redis 服务器端口
redis.port=6379
#redis 密码
redis.pass=
#redis 支持16个数据库(相当于不同用户)可以使不同的应用程序数据彼此分开同时又存储在相同的实例上
redis.dbIndex=1
#redis 缓存数据过期时间单位秒
redis.expiration=3000
#控制一个 pool 最多有多少个状态为 idle 的jedis实例
redis.maxIdle=300
#控制一个 pool 可分配多少个jedis实例
redis.maxActive=600
#当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
redis.maxWait=1000
#在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的;
redis.testOnBorrow=true
package com.csdn.learn.rediscacheanno;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
// cacheManager.setDefaultExpiration(3600);//默认缓存一小时
return cacheManager;
}
/**
* redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate
最后, SpringBoot整合Redis做缓存Cache技术配置非常简单, 可以试着玩一玩