zoukankan      html  css  js  c++  java
  • springboot集成redis(缓存篇)

    一 前言

    公众号:知识追寻者

    知识追寻者(Inheriting the spirit of open source, Spreading technology knowledge;)

    pring为我们提供的缓存注解Spring Cache。Spring支持多种缓存技术:RedisCacheManager,EhCacheCacheManager、GuavaCacheManager等,今天的内容是集成RedisCacheManager实现缓存技术;

    二 Spring Cache

    spring cache 常用注解如下

    2.1@Cacheable

    作用:查询数据加入缓存

    参数如下:

    • cacheNames 缓存名称
    • key 缓存的key, SPEL表达式写法
    • condition 缓存执行的条件,返回true时候执行

    2.2@CachePut

    作用:修改了数据库的数据,同时更新缓存。

    参数如下:

    • cacheNames 缓存名称
    • key 缓存的key, SPEL表达式写法
    • condition 缓存执行的条件,返回true时候执行

    2.3@CacheEvict

    作用:删除数据,删除缓存

    参数如下:

    • allEntries boolean类型,表示是否需要清除缓存中的所有元素
    • key 需要删除的缓存的key

    三 集成配置

    3.1 依赖

    springboot 2.1.1

    	<dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.18</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.postgresql</groupId>
                <artifactId>postgresql</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.0</version>
            </dependency>
        </dependencies>
    

    3.2 application.yml

    主要是 redis 和 数据库 链接配置;如果使用mysql 自行更好 数据库链接驱动和依赖;

    server:
      port: 9000
    
    spring:
      redis:
        # Redis服务器地址
        host: localhost
        #Redis服务器连接端口
        port: 6379
        #password:
        # Redis数据库索引(默认为0)
        database: 2
        # 连接超时时间(毫秒)
        timeout: 5000
        jedis:
          pool:
            #连接池最大连接数(使用负值表示没有限制)
            max-active: 100
            # 连接池中的最小空闲连接
            max-idle: 10
            # 连接池最大阻塞等待时间(使用负值表示没有限制)
            max-wait: 100000
      #数据库配置
      datasource:
        driverClassName: org.postgresql.Driver
        url: jdbc:postgresql://127.0.0.1:5432/springboot
        username: postgres
        password: 123456
    
    logging:
      level:
        com.zszxz.cach.mapper : debug
    

    3.3 redis配置

    主要是设置 CacheManagerredisTemplate; 并且支持默认key 过期时间,和乱码问题解决;

    /**
     * @Author lsc
     * <p> redis配置 </p>
     */
    @Configuration
    @EnableCaching
    public class RedisConfig  extends CachingConfigurerSupport {
    
    
    
        /* *
         * @Author lsc
         * <p>自定义生成key的规则 </p>
         * @Param []
         * @Return KeyGenerator
         */
        @Override
        @Bean
        public KeyGenerator keyGenerator() {
            return new KeyGenerator() {
                @Override
                public Object generate(Object o, Method method, Object... objects) {
                    //格式化缓存key字符串
                    StringBuilder sb = new StringBuilder();
                    //追加类名
                    sb.append(o.getClass().getName());
                    //追加方法名
                    sb.append(method.getName());
                    //遍历参数并且追加
                    for (Object obj : objects) {
                        sb.append(obj.toString());
                    }
                    return sb.toString();
                }
            };
        }
    
        @Bean
        public CacheManager cacheManager(RedisConnectionFactory factory) {
            RedisSerializer<String> redisSerializer = new StringRedisSerializer();
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    
            //解决查询缓存转换异常的问题
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
    
            // 配置序列化(解决乱码的问题),过期时间120秒
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofSeconds(120))
                    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                    .disableCachingNullValues();
    
            RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                    .cacheDefaults(config)
                    .build();
            return cacheManager;
        }
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
            // 创建redisTemplate
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(connectionFactory);
    
            // 使用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);
    
            //set value serializer
            redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
            // key采用String的序列化方式
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            // value序列化方式采用jackson
            redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
            // hash的key也采用String的序列化方式
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            // hash的value序列化方式采用jackson
            redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
            redisTemplate.afterPropertiesSet();
            return redisTemplate;
        }
    
    }
    

    3.3 使用注解集成redis缓存

    /* *
         * @Author lsc
         * <p>先从缓存中读取,如果没有再从DB获取数据,然后把数据添加到缓存中
         * unless 表示条件表达式成立的话不放入缓存
         * 如果 设置 ,keyGenerator = "keyGenerator" 就不能设置 key
         *  </p>
         * @Param [user_id]
         * @Return com.zszxz.cach.entity.UserEntity
         */
        @Override
        @Cacheable(cacheNames = "UserEntity", key = "#user_id")
        public UserEntity getUser(Long user_id) {
            return userMapper.getUser(user_id);
        }
    
    
        /* *
         * @Author lsc
         * <p>修改了数据库的数据,同时更新缓存。先调用目标方法,然后缓存方法结果 </p>
         * @Param [userEntity]
         * @Return int
         */
        @Override
        @CachePut(cacheNames = "UserEntity", key = "#result.user_id")
        public UserEntity updateUser(UserEntity userEntity) {
            userMapper.updateUser(userEntity);
            // 注意,会将缓存更新未参数userEntity里面的值
            return userEntity;
        }
    
        /* *
         * @Author lsc
         * <p>allEntries 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存
         * 指定删除一条缓存
         * </p>
         * @Param [user_id]
         * @Return int
         */
        @Override
        @CacheEvict(cacheNames = "UserEntity", key = "#user_id")
        public int delUser(Long user_id) {
            return userMapper.delUser(user_id);
        }
    

    四 测试

    4.1 查询测试

    测试代码

        @Test
        public void testGet(){
            UserEntity user = userService.getUser(1L);
            System.out.println(user);
        }
    

    第一次查询控制台会打印SQL,第二次查询不会打印SQL,直接从redis获取

    4.2 修改缓存测试

    修改缓存的结果是方法的返回值,由于这边式参数直接作为返回值,故参数用户实体的属性必须是全属性,否则查询缓存时会出现多个参数是null,而数据库中有值;比如这边的user_telephone字段;

        @Test
        public void testPUT(){
            UserEntity userEntity = new UserEntity();
            userEntity.setUser_id(1L);
            userEntity.setUser_name("知识追寻者");
            userEntity.setUser_gender("female");
            userService.updateUser(userEntity);
        }
    

    4.3 删除缓存测试

    删除缓存后直接删除指定key的一条缓存;

        @Test
        public void testDel(){
            userService.delUser(1L);
        }
    

    有关sping cahe 学习参照如下链接

    https://blog.csdn.net/u012240455/article/details/80844361

  • 相关阅读:
    高格-远程支持中的奇怪问题【15】
    关于er图的几个工具
    如何解决win10明明是管理员还要权限的问题
    判断日期天数
    谈一谈在公司两次压测我总结的思路
    vue学习之-----v-model数据双向绑定,自定义组件父子传参
    Js各种小技巧总结
    openlayers学习之-----核心类
    openlayers学习之-----把坐标点改为WKT格式的数据
    新书介绍 -- 《Redis核心原理与实践》
  • 原文地址:https://www.cnblogs.com/zszxz/p/12880190.html
Copyright © 2011-2022 走看看