缓存其实就是一个临时的存储器。
客户端第一次请求的时候是从库里拿出我们需要的数据,但如果每次查询都从库里拿,就会很耗时耗能。那么使用缓存以后,我们只需要第一次从库里拿完存到缓存中,只要不清除缓存,我们以后的请求都直接在缓存中拿数据,就会快很多很多。
缓存主要是为了提高数据的读取速度。 因为服务器和应用客户端之间存在着流量的瓶颈,所以读取大容量数据时,使用缓存来直接为客户端服务,可以减少客户端与服务器端的数据交互,从而大大提高程序的性能。
SpringBoot支持很多种缓存方式:redis、guava、ehcahe、jcache等等。
主要用于配置该类中会用到的一些共用的缓存配置。 在这里@CacheConfig(cacheNames = “users”):配置了该数据访问对象中返回的内容将存储于名为users的缓存对象中,我们也可以不使用该注解,直接通过@Cacheable自己配置缓存集的名字来定义。
配置了findByName函数的返回值将被加入缓存。同时在查询时,会先从缓存中获取,若不存在才再发起对数据库的访问。
注解参数:
配置于函数上,能够根据参数定义条件来进行缓存,它与@Cacheable不同的是,它每次都会真是调用函数,所以主要用于数据新增和修改操作上。 它的参数与@Cacheable类似,具体功能可参考上面对@Cacheable参数的解析
配置于函数上,通常用在删除方法上,用来从缓存中移除相应数据。也就是清除缓存除了同@Cacheable一样的参数之外,它还有下面两个参数:
用于定义复杂的缓存规则,可以集成@Cacheable和 @CachePut
// @Caching 定义复杂的缓存规则
@Caching(
cacheable = {
@Cacheable(/*value={"emp"},*/key = "#lastName")
},
put = {
@CachePut(/*value={"emp"},*/key = "#result.id"),
@CachePut(/*value={"emp"},*/key = "#result.email")
}
)
public Employee getEmpByLastName(String lastName){
return employeeMapper.getEmpByLastName(lastName);
}
Java缓存框架 EhCache EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。
主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。
1、修改 pom 文件
引入Ehcache jar包
<dependency>
<groupId>net.sf.ehcachegroupId>
<artifactId>ehcacheartifactId>
dependency>
2、创建 Ehcache 的配置文件
文件名:ehcache.xml
位置:src/main/resources/ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="java.io.tmpdir" />
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120"
maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap" />
defaultCache>
<cache name="users" maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120"
maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap" />
cache>
ehcache>
3、修改 application.properties 文件
主要添加 ehcache 的配置xml文件的位置
spring.cache.ehcache.cofnig=ehcache.xml
4、修改启动类
启动类上在增加 @EnableCaching
,作用就是启动 SpringCache 功能,使缓存生效 。
5、在service业务层用注解来使用缓存
也可以在dao层使用注解,使用方式一样。注意:这里就算不调用查询数据库的方法,service层的方法返回值也会被缓存,也就是该缓存注解缓存的是方法的返回值,与方法里的执行逻辑无关。
@Service
public class UsersServiceImpl implements UsersService {
@Autowired
private UsersRepository usersRepository;
@Override
// @Cacheable:对当前查询的对象做缓存处理
@Cacheable(value = "users")
public Users findUserById(Integer id) {
return this.usersRepository.findOne(id);
}
1、引入依赖 pom.xml
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
2、修改application.yml,配置redis
#数据库连接
spring:
datasource:
url: jdbc:mysql://localhost:3306/mytest_springboot_cache?useUnicode=true
driver-class-name: com.mysql.jdbc.Driver
username: root
password: lzh
## Redis 配置
redis:
## Redis数据库索引(默认为0)
database: 0
## Redis服务器地址
host: 192.168.126.129
## Redis服务器连接端口
port: 6379
## Redis服务器连接密码(默认为空)
password:
jedis:
pool:
## 连接池最大连接数(使用负值表示没有限制)
#spring.redis.pool.max-active=8
max-active: 8
## 连接池最大阻塞等待时间(使用负值表示没有限制)
#spring.redis.pool.max-wait=-1
max-wait: -1
## 连接池中的最大空闲连接
#spring.redis.pool.max-idle=8
max-idle: 8
## 连接池中的最小空闲连接
#spring.redis.pool.min-idle=0
min-idle: 0
## 连接超时时间(毫秒)
timeout: 1200
3、编写java配置类
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
/**
* 选择redis作为默认缓存工具
* @param redisConnectionFactory
* @return
*/
/*@Bean
//springboot 1.xx
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
return rcm;
}*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}
/**
* retemplate相关配置
* @param factory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(factory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSeial.setObjectMapper(om);
// 值采用json序列化
template.setValueSerializer(jacksonSeial);
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
// 设置hash key 和value序列化模式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jacksonSeial);
template.afterPropertiesSet();
return template;
}
/**
* 对hash类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
/**
* 对redis字符串类型数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
/**
* 对链表类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
/**
* 对无序集合类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
/**
* 对有序集合类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}
这里主要是使用RedisTemplate来对远程redis操作,每次访问controller暴露的接口,首先判断redis缓存中是否存在该数据,若不存在就从数据库中读取数据,然后保存到redis缓存中,当下次访问的时候,就直接从缓存中取出来。这样就不用每次都执行sql语句,能够提高访问速度。 但是在保存数据到缓存中,通过设置键和值和超时删除,注意设置超时删除缓存时间不要太长,否则会给服务器带来压力。
也可以使用注解的形式,使用方式和Ehcache的使用方式一致。
这里不介绍redis集群,详细见redis类型的博客。
yml配置文件:
spring:
redis:
cluster:
nodes:
- 192.168.1.236:7001
- 192.168.1.236:7002
- 192.168.1.236:7003
- 192.168.1.244:7004
- 192.168.1.244:7005
- 192.168.1.244:7006
max-redirects: 3 # 获取失败 最大重定向次数
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
min-idle: 5 # 连接池中的最小空闲连接
timeout: 6000 # 连接超时时长(毫秒)
这种方式 redisTemplate 可直接使用默认,在使用的地方直接注入即可
@Autowired
private RedisTemplate<String, Object> redisTemplate;
yml配置文件:
spring:
redis:
password: # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
cluster:
nodes:
- 192.168.1.236:7001
- 192.168.1.236:7002
- 192.168.1.236:7003
- 192.168.1.244:7004
- 192.168.1.244:7005
- 192.168.1.244:7006
jedis:
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
连接池注入配置信息
@Configuration
public class RedisConfig {
@Autowired
private RedisConnectionFactory factory;
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
}
在使用的地方直接注入即可
@Autowired
private RedisTemplate<String, Object> redisTemplate;
yml配置文件:
spring:
redis:
timeout: 6000ms
password:
cluster:
max-redirects: 3 # 获取失败 最大重定向次数
nodes:
- 192.168.1.236:7001
- 192.168.1.236:7002
- 192.168.1.236:7003
- 192.168.1.244:7004
- 192.168.1.244:7005
- 192.168.1.244:7006
lettuce:
pool:
max-active: 1000 #连接池最大连接数(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
连接池注入配置信息
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
在使用的地方直接注入即可
@Autowired
private RedisTemplate<String, Object> redisTemplate;