七.Redis极简入门-SpringCache操作缓存

x33g5p2x  于2021-12-19 转载在 其他  
字(5.1k)|赞(0)|评价(0)|浏览(460)

学习使用,老鸟飞过,欢迎交流

前言

java操作Redis有很多中方案,Jedis,SpringBootDataRedis,Redisson等,本篇文章的目的是使用SpringBootDataRedis整合SpringCache基于Redis实现缓存操作

一.SpringBoot整合Redis实现缓存

SpringBoot提供了整合Redis的方案,我们使用spring-boot-starter-data-redis包就可以很方便的操作Redis了。

1.第一步:导入redis的基础依赖
<!--整合Redis , 底层可以用jedis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

spring-boot-starter-data-redis 默认使用的是lettuce操作Redis,这个技术在高并发下会有内存溢出的风险,这里我排除掉lettuce,使用jedis操作redis

2.第二步:配置redis
spring:
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password: 123456
    jedis:
      pool: #连接池
        max-wait: 2000ms #等待超时
        min-idle: 2 #最小空闲数
        max-idle: 8 #最大空闲数
3.第三步:配置RedisTemplate序列化方式

主要配置对象存储到Redis使用JSON格式序列化,这种格式比较通用

@Configuration
public class CacheConfig extends CachingConfigurerSupport {

    @Resource
    private RedisConnectionFactory factory;

    //使用JSON进行序列化
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        //JSON格式序列化
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();        
        //value的序列化 
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
        //hash结构value的虚拟化
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        return redisTemplate;
    }

    @Bean
    @Override
    public CacheResolver cacheResolver() {
        return new SimpleCacheResolver(cacheManager());
    }

    @Bean
    @Override
    public CacheErrorHandler errorHandler() {
        // 用于捕获从Cache中进行CRUD时的异常的回调处理器。
        return new SimpleCacheErrorHandler();
    }
    //缓存管理器
    @Bean
    @Override
    public CacheManager cacheManager() {
        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                        .disableCachingNullValues() //不允许空值
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));//值使用JSON虚拟化
        return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();
    }
}
4.第三步:缓存流程

通过注入:RedisTemplate操作缓存,如果使用String的话也可以直接使用 StringRedisTemplate

@Autowired
 private RedisTemplate<String,Object> redisTemplate;

 //@Autowired
 //private StringRedisTemplate stringRedisTemplate;

缓存逻辑伪代码,先从缓存查询,如果缓存有直接返回结果,如果缓存没有就走数据库查询,然后同步到缓存再返回结果:

public User selectUserById(Long id){
	//从缓存查询
	String userKey = "user:"+id;
	User userFromCache = redisTemplate.opsForValue().get(userKey );
	if(null == userFromCache ){
		//缓存为空,从数据库查询
		User userFromDB = userDao.selectUserById(id);
		//把user存储到缓存
		redisTemplate.opsForValue().set(userKey ,userFromDB  );
		//返回User
		return userFromDB ;
	}
	return userFromCache ;
}

上面代码并不完整,在数据库中的数据发送事务操作的时候,还需要把缓存中的数据剔除来保证数据一致性

public void deleteUserById(Long id){
	userDao.deleteUserById(id);
	String userKey = "user:"+id;
	redisTemplate.delete(userKey )
}

二.使用SpringCahe注解实现缓存

1.注解介绍

对于缓存声明,Spring的缓存提供了一组java注解:

  • @Cacheable :写入缓存
  • @CacheEvict:清除缓存
  • @CachePut:更新缓存
  • @Caching:组合多个缓存操作
  • @CacheConfig:设置类级别上共享的一些常见缓存设置
2.开启SpringCache

在启动类贴上 @EnableCaching 注解

@SpringBootApplication
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(CourseApplication.class );
    }
}
3.写入缓存

@Cacheable :写入缓存,打在有返回值的方法上,自动把返回值加入缓存,并且在执行方法之前会检查缓存时候有数据,如果有就直接返回缓存中的数据,不再执行方法

//@Cacheable(cacheNames = "user",key = "'id1'")
 @Cacheable(cacheNames = "user",key = "#id")
 public User selectUserById(Long id) {
 	return userDao.selectUserById(id);
 }

一个注解就实现了上面代码 1.4 中的缓存案例 ,非常方便,这里的

  • cacheNames = “user” :指的是缓存的名字为“user”
  • key = “#id” :是值把参数id的值作为是缓存的key,“#id”是表达式写法,在Redis中会 cacheNames 和 key 联合起来作为 键 ,效果如:“user::1” ,

常见的用法:

  • @Cacheable(cacheNames = “user”,key = “‘id1’”) :固定一个key 效果如:“user:id1”
  • @Cacheable(cacheNames = “user”,key = “#obj.id”) :取参数obj对象的id的值作为key ,效果如:“user::1”
  • @Cacheable(cacheNames = “user”,key = “#id”,condition="#id > 10") : 需要满足id大于10才做缓存
4.删除缓存

在数据库做了事务操作(增删改),需要把缓存中的数据删除,等待下一次查询重新同步缓存数据,在SpringCache中可以使用 @CacheEvict 注解完成,他会主动匹配key完成缓存的剔除工作

@CacheEvict(cacheNames = "user",key = "#id")
public void deleteUserById(Long id){
	userDao.deleteUserById(id);
}

如果要对缓存批量删除可以使用 @CacheEvict(cacheNames="user", allEntries=true)

5.更新缓存

更新缓存使用@CachePut注解,和@Cacheable用法相同,他会把方法的返回值自动更新到缓存,以注解的key做自动匹配

@CachePut(cacheNames = "user",key = "#user.id")
public User updateUserById(User user){
	userDao.updateUserById(user);
	return user;
}

注意:建议不要把@CachePut和@Cacheable作用于同一个方法,可能会有功能上的冲突

6.组合操作

@Caching注解可以组合多个缓存操作,比如删除多个缓存

//删除多个缓存,user和其账户一起删除
@Caching(evict = { @CacheEvict(cacheNames="user", key = "#user.id"), @CacheEvict(cacheNames="account", key = "#user.id") })
public void updateUserById(User user){
	userDao.updateUserById(user);
	return user;
}
7.公共配置

@CacheConfig注解可以配置一些共享的属性,比如把cacheNames抽取出来

@CacheConfig(cacheName="user") 
public class CacheService{

	@CacheEvict(key = "#id")
	public void deleteUserById(Long id){
		userDao.deleteUserById(id);
	}
	
	@CachePut(key = "#user.id")
	public User updateUserById(User user){
		userDao.updateUserById(user);
		return user;
	}
}

文章结束,希望对你有所帮助

相关文章