• 5.Spring-Boot缓存数据之Redis


    1.启用对缓存的支持

    spring对缓存的支持有两种方式:

       a.注解驱动的缓存

       b.XML声明的缓存

      本文主要介绍纯Java配置的缓存,那么必须在配置类上添加@EnableCaching,这样的话就能启动注解驱动的缓存。

    2.使用Redis缓存

    缓存的条目不过是一个键值对(Key-Value),其中key描述了产生value的操作和参数,因此会很自然的想到Redis。

    Redis可以用来为srping缓存抽象机制缓存条目,Spring-Data-Redis提供了RedisCacheManager,这是CacheManager的一个实现。RedisCacheManager会与Redis服务器协作,通过RedisTemplate将缓存条目储存到Redis中。

    为了使用RedisCacheManager,我们需要RedisTmeplate Bean配置以及RedisConnectionFactory实现类(JedisConnectionFactory Bean配置)。

    3.配置将缓存条目存储在Redis服务器的缓存管理器。

       前提需要在pom.xml引入

                   <!--redis  -->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    
    </dependency>  

    在application.properties中配置redis连接相关参数

    #配置redis
    #在RedisProperties.class有redis的默认配置,默认host为localhost,默认端口为6379
    spring.redis.host=127.0.0.1
    spring.redis.port=6379

     配置缓存管理器

    package com.niugang;
    import java.lang.reflect.Method;
    import org.springframework.cache.CacheManager;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.cache.interceptor.KeyGenerator;
    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.jedis.JedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    
    
    @Configuration
    //没有@EnableCaching这个注解的话,代码不会报错,就是内容不会放入redis中
    
    @EnableCaching 
    
    public class RedisConfig {
    /**
    * 緩存管理器,不管用什么的缓存,都必须有缓存管理器
    */
    @Bean
    public CacheManager cacheManager() {
    RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate());
    /*
    * 设置缓存保留的时间,默认是永久保存
    */
    redisCacheManager.setDefaultExpiration(60);
    return redisCacheManager;
    }
    
    
    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
    JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
    jedisConnectionFactory.afterPropertiesSet();
    return jedisConnectionFactory;
    
    }
    
          /**
    * redis默认对象序列化是通过jdk来序列化的,这里面不用默认序列化方式,用JackJson进行序列化
    * 
    * 设置key的类型为String类型
    * 
    * @return
    */
    @Bean
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public RedisTemplate<String, String> redisTemplate() {
    RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
    
    redisTemplate.setConnectionFactory(jedisConnectionFactory());
    
              // 使用Jackson2JsonRedisSerialize 替换默认序列化
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
    // 设置value的序列化规则和 key的序列化规则
    redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.afterPropertiesSet();
    return redisTemplate;
    
    }
    
     /**
         * 生产key的策略
         * @return
         */
    @Bean  
        public KeyGenerator wiselyKeyGenerator(){  
            return new KeyGenerator() {  
                @Override  
                public Object generate(Object target, Method method, Object... params) {  
                    StringBuilder sb = new StringBuilder();  
                    sb.append(target.getClass().getName());  
                    sb.append(method.getName());  
                    for (Object obj : params) {  
                        sb.append(obj.toString());  
                    }  
                   
                    return sb.toString();  
                }  
            };
    
    
    }
    
    }

    4.为方法添加注解以支持缓存

    spring的缓存抽象在很大程度上是围绕切面构建的,在sprng中启用缓存时,会创建一个切面,它触发

    一个或更多的spring的缓存注解。

                                               spring提供了四个注解来声明缓存规则

                        

                        

    5.填充缓存

          @Cacheable和CachePut都可以填充缓存,他们之间还是确有差异的。

          

                                             @Cacheable和CachePut共同的属性

                       

    6.自定义key

    @Cacheable和CachePut都有一个名为key的属性,这个属性能够替代默认的key,t它是通过SpEl(Spring El表达式)表达式计算得到的。具体到我们的业务场景 save(User user),我们需要将key设置保存为User对象中的id,我们通过mysql数据库自动生成id,此时参数中的User对象还没有id.幸好有SpEl。

    7.在UserService中添加如下方法。

            /**
    * 查询全部
    * 
    * @Cacheable,先在缓存中找,有则直接返回,不去调用方法,没有则调用方法,将结果放入缓存中
    * 
    * 
    * 默认的key是基于方法参数来确定的,queryList()这个方法没有参数,所以需要生成key的策略
    */
    //@Cacheable(value="findAll",keyGenerator="wiselyKeyGenerator")
    public List<User> queryList() {
    return userDao.findAll();
    }
    
          /**
    * @Cachable会条件性的出发对方法的调用,这个取决于缓存中是不是已经有所需要的值。对于
    * 所注解的方法,@CachePut采用一种更为直接的流程。带有@CachePut注解的方法始终都会调用,
    * 而的返回值也会放入到缓存中。
    * @CachePut先将对象保存到db中,返回的对象User中的id作为缓存中的key
    * result能够得到返回的User
    * @param user
    */
    @CachePut(value="save",key="#result.id.toString()")
    @Transactional
    public User save(User user) {
    log.info("添加对象");
    return userDao.save(user);
    
    }
    
        /**
    * 函数功能:根据id查询
    * 
    * 当get被调用时,缓存切面会拦截调用并在缓存中查找之前以名findOne存储的返回值。缓存的key是
    * 传递到get()方法的id参数,这个参数还必须是String类型。如果按照这个key能
    * 够找到值得话就返回找到的值,方法不会在被调用。如果没有找到值的话,那就会调用这个方法
    * 并将返回值放到缓存之中。
    * 
    * 默认是以参数id的值作为缓存中的key的
    * 
    * 没有添加key="#id.toString()" 可能为报java.lang.Integer cannot be cast to java.lang.String
    * 因为key的类型为String类型
    */
    @Cacheable(value="findOne",key="#id.toString()")
    public User get(Integer id) {
    log.info("从数据查询id为:{}的对象",id);
    return userDao.findOne(id);
    
    }
    
         /**
    * 删除 
    * @CacheEvict移除条目,可以用在返回值为void的方法上,但是@Cacheable,@CachePut不能用在返回值为void的方法上
    * 
    * @param id
    */
    @CacheEvict(value="save",key="#id.toString()")
    @Transactional
    public void delete(int id) {
    log.info("从数据删除id为:{}的对象",id);
    userDao.delete(id);
    }

    微信公众号

                              
  • 相关阅读:
    蓝绿发布、灰度发布和滚动发布
    linux redis 设置密码:
    redis配置文件讲解
    17 个方面,综合对比 Kafka、RabbitMQ、RocketMQ、ActiveMQ 四个分布式消息队列
    CentOS 7下安装Redis
    压力测试工具介绍
    【k8s部署kong一】kong k8s 安装 以及可视化管理界面
    Jmeter连接ORACLE数据库
    Jenkins安装插件提示实例似乎已离线问题解决办法
    Fiddler增加显示请求响应时间列
  • 原文地址:https://www.cnblogs.com/niugang0920/p/12197014.html
Copyright © 2020-2023  润新知