springboot框架学习积累—SpringBoot缓存管理之相关组件

1.SpringBoot支持的缓存组件有哪些

  1. SpringBoot中,数据的缓存管理存储依赖于Spring框架中cache相关的org.springframework.cache.Cacheorg.springframework.cache.CacheManager缓存管理器接口
  2. 如果当前程序没有定义类型为CacheManagerBean组件或者是名为cacheResolver缓存解析器,SpringBoot将尝试选择并启用以下缓存组件(按照指定顺序)
  1. Generic
  2. JCache (JSR-107) (EhCache3 、Hazelcast、 Infinispan等)
  3. EhCache 2.x
  4. Hazelcast
  5. Infinispan
  6. Couchbase
  7. Redis
  8. Caffeine
  9. Simple

springboot 整合各组件 springboot相关组件_redis


springboot 整合各组件 springboot相关组件_springboot 整合各组件_02

2.SpringBoot基于注解的Redis缓存实现

  1. 添加redis的依赖启动器:由于引入了Redis的依赖启动器,所以会将默认的SimpleCacheConfiguration缓存配置类变成RedisCacheConfiguration这个缓存配置类,容器中使用的缓存管理器也从ConcurrentMapCacheManager变成了RedisCacheManager,这时候缓存管理器创建的CacheRedisCache,进而操作Redis进行数据的缓存
<dependency> 
		<groupId>org.springframework.boot</groupId> 
		<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 对Redis服务进行配置
#Redis服务地址
spring.redis.host=127.0.0.1
#Redis服务端口号
spring.redis.port=6379
#Redis服务密码
spring.redis.password=
#对基于注解的Redis缓存数据统一设置有效期为1分钟,单位毫秒
spring.cache.redis.time-to-live=60000
  1. 编写业务层,实现Redis缓存逻辑
controller
/**
 * @author yy
 */
@RestController
public class CommentController {

    @Autowired
    private CommentService commentService;

    /**
     * 查询
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/findCommentById")
    public Comment findCommentById(Integer id){
        Comment comment = commentService.findCommentById(id);
        return comment;
    }

    /**
     * 修改
     *
     * @param comment
     * @return
     */
    @RequestMapping("/updateComment")
    public Comment updateComment(Comment comment){
        Comment commentById = commentService.findCommentById(comment.getId());
        commentById.setAuthor(comment.getAuthor());
        Comment comment1 = commentService.updateComment(commentById);
        return comment1;
    }


    /**
     * 删除
     *
     * @param id
     */
    @RequestMapping("/deleteComment")
    public void deleteComment(Integer id){
        commentService.deleteComment(id);
    }
service
/**
 * @author yh
 */
@Service
public class CommentService {

    @Autowired
    private CommentRepository commentRepository;

    /**
     * @Cacheable:  将该方法查询结果comment存放在springboot默认Simple缓存中(前提是没有引入其他缓存组件)
     * cacheNames: 起一个缓存命名空间  对应缓存唯一标识
     * unless:当满足等号后面的条件时,结果不进入缓存
     */
    @Cacheable(cacheNames = "comment",unless = "#result == null ")
    public Comment findCommentById(Integer id){
        Optional<Comment> byId = commentRepository.findById(id);
        if (byId.isPresent()){
            //获取comment对象
            Comment comment = byId.get();
            return comment;
        }
        return null;
    }

    /**
     * 更新
     */
    @CachePut(cacheNames = "comment",key = "#result.id")
    public Comment updateComment(Comment comment){
        commentRepository.updateComment(comment.getAuthor(),comment.getId());
        return comment;
    }

    /**
     * 删除
     */
    @CacheEvict(cacheNames = "comment")
    public void deleteComment(Integer id){
        commentRepository.deleteById(id);
    }

}

3.SpringBoot基于API的Redis缓存实现

springboot 整合各组件 springboot相关组件_redis_03

/**
 * @author yh
 */
@Service
public class ApiCommentService {

    @Autowired
    private CommentRepository commentRepository;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 查询方法,使用API方式进行缓存。
     * 先去缓存中查找,缓存中有直接返回,没有,查询数据库
     *
     * @param id
     * @return
     */
    public Comment findCommentById(Integer id){
        //通过key找Object对象,get括号中的是key
        Object o = redisTemplate.opsForValue().get("comment_" + id);
        if (o!=null){
            //查询到了数据直接返回
            return (Comment) o;
        }else {
            //缓存中没有,去数据库中找
            Optional<Comment> byId = commentRepository.findById(id);
            if (byId.isPresent()){
                //获取comment对象
                Comment comment = byId.get();
                //将查询结果放到缓存中,并且设置有效期
                redisTemplate.opsForValue().set("comment_" + id,comment,1, TimeUnit.DAYS);
                return comment;
            }
        }
        return null;
    }

    /**
     * 修改
     *
     * @param comment
     * @return
     */
    public Comment updateComment(Comment comment){
        commentRepository.updateComment(comment.getAuthor(),comment.getId());
        //将数据在数据库中修改完成,再存到redis库里面,将更新数据
        redisTemplate.opsForValue().set("comment_" + comment.getId(),comment);
        return comment;
    }

    /**
     * 删除
     *
     * @param id
     */
    public void deleteComment(Integer id){
        commentRepository.deleteById(id);
        redisTemplate.delete("comment_" + id);
    }
}

4.SpringBoot之Redis缓存默认序列化机制

springboot 整合各组件 springboot相关组件_redis_04

  1. 查看源码,可以将源码分成两部分 1.声明了key,value各种序列化的初始值,初始值为空 2.进行默认序列化设置方式,默认设置是JDK序列化方式
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, 
		BeanClassLoaderAware {
	// 声明了key,value各种序列化的初始值,初始值为空
	@Nullable
	private RedisSerializer keySerializer = null;
	@Nullable
	private RedisSerializer valueSerializer = null;
	@Nullable
	private RedisSerializer hashKeySerializer = null;
	@Nullable
	private RedisSerializer hashValueSerializer = null;
	...
	
	// 进行默认序列化设置方式,默认设置是JDK序列化方式
	public void afterPropertiesSet() {
		super.afterPropertiesSet();
		boolean defaultUsed = false;
		if(this.defaultSerializer == null) {
			this.defaultSerializer = new JdkSerializationRedisSerializer(
			this.classLoader != null?
			this.classLoader:this.getClass().getClassLoader());
	 		}
			...
	 	}
		...
	}

springboot 整合各组件 springboot相关组件_springboot 整合各组件_05


2. 根据上述源码分析可以得出以下两个重要结论

springboot 整合各组件 springboot相关组件_Redis_06


springboot 整合各组件 springboot相关组件_redis_07


springboot 整合各组件 springboot相关组件_redis_08

5.SpringBoot之Redis缓存自定义序列化机制

  1. 引入Redis的依赖后,SpringBoot提供的RedisAutoConfiguration自动配置会生效,RedisAutoConfiguration这个类有关于RedisTemplate的定义方式
public class RedisAutoConfiguration {
	//将方法的返回值注入到ioc容器中,key是方法名
	@Bean
	//当redisTemplate这个bean不存在时生效,如果自定义了一个redisTemplate的bean,那么这个方法的返回值就失效了
	@ConditionalOnMissingBean(name = "redisTemplate")
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
			throws UnknownHostException {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}
	...
}

springboot 整合各组件 springboot相关组件_缓存_09


springboot 整合各组件 springboot相关组件_springboot 整合各组件_10


springboot 整合各组件 springboot相关组件_Redis_11

6.SpringBoot缓存管理之自定义RedisCacheManager

springboot 整合各组件 springboot相关组件_缓存_12

Redis注解默认序列化机制:RedisCacheConfiguration

springboot 整合各组件 springboot相关组件_redis_13

@Configuration
    class RedisCacheConfiguration {
        @Bean
        public RedisCacheManager cacheManager(RedisConnectionFactory
                                                      redisConnectionFactory, ResourceLoader
                                                      resourceLoader) {
            RedisCacheManagerBuilder builder =
                    RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(this.determineConfiguration(resourceLoader.getClassLoader()));
            List<String> cacheNames = this.cacheProperties.getCacheNames();
            if (!cacheNames.isEmpty()) {
                builder.initialCacheNames(new LinkedHashSet(cacheNames));
            }
            return
                    (RedisCacheManager) this.customizerInvoker.customize(builder.build());
        }

        private org.springframework.data.redis.cache.RedisCacheConfiguration
        determineConfiguration(ClassLoader classLoader) {
            if (this.redisCacheConfiguration != null) {
                return this.redisCacheConfiguration;
            } else {
                Redis redisProperties = this.cacheProperties.getRedis();
                org.springframework.data.redis.cache.RedisCacheConfiguration
                        config =
                        org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConf
                ig();
                config =
                        config.serializeValuesWith(SerializationPair.fromSerializer(
                                new
                                        JdkSerializationRedisSerializer(classLoader)));
...
                return config;
            }
        }
    }

springboot 整合各组件 springboot相关组件_缓存_14


springboot 整合各组件 springboot相关组件_springboot 整合各组件_15


制,需要自定义RedisCacheManager

自定义RedisCacheManager

springboot 整合各组件 springboot相关组件_Redis_16

@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    // 分别创建String和JSON格式序列化对象,对缓存数据key和value进行转换
    RedisSerializer<String> strSerializer = new StringRedisSerializer();
    Jackson2JsonRedisSerializer jacksonSeial =
            new Jackson2JsonRedisSerializer(Object.class);

    // 解决查询缓存转换异常的问题
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jacksonSeial.setObjectMapper(om);

    // 定制缓存数据序列化方式及时效
    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofDays(1))
            .serializeKeysWith(RedisSerializationContext.SerializationPair
                    .fromSerializer(strSerializer))
            .serializeValuesWith(RedisSerializationContext.SerializationPair
                    .fromSerializer(jacksonSeial))
            .disableCachingNullValues();
    RedisCacheManager cacheManager = RedisCacheManager
            .builder(redisConnectionFactory).cacheDefaults(config).build();
    return cacheManager;
}

springboot 整合各组件 springboot相关组件_Redis_17