• SpringCache学习实践


    1. SpringCache学习实践

    1.1. 引用

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    

    1.2. 启用方式

    1.2.1. 添加一种cacheManager的bean

    1. 若注解了@EnableCaching,则spring可自动发现并配置cacheManager,只要有一种可用于缓存提供的即可,详情见文献[1]。常用的有Ehcache、redis等实现
    @Configuration
        @EnableCaching
        public class CacheConfiguration {
            @Bean
    	    public CacheManager cacheManager() {
    	        SimpleCacheManager cacheManager = new SimpleCacheManager();
    	        cacheManager.setCaches(Collections.singletonList(new ConcurrentMapCache("models")));
    	        return cacheManager;
    	    }
        }
    
    

    1.3. 使用方式

    1. 三个主要的注解 Cacheable (最常用的注解,用于标注需要缓存方法)、CacheEvict(用于仅清除缓存)、CachePut(用于仅存放缓存)
    2. 先定义一个测试POJO: TestModel。 含有name和address两个字符串变量。
    class TestModel {
           String name;
           String address;
           // 省略getter和setter
       }
    

    1.3.1. Cacheable

    @Cacheable(value = "models", key = "#testModel.name", condition = "#testModel.address !=  '' ")
    public TestModel getFromMem(TestModel testModel) throws InterruptedException {
        TimeUnit.SECONDS.sleep(1);
        testModel.setName(testModel.getName().toUpperCase());
        return testModel;
    }
    
    1. 例子里的注解@Cacheable中存在有以下几个元素
      • value (也可使用 cacheNames) : 可看做命名空间,表示存到哪个缓存里了。
      • key : 表示命名空间下缓存唯一key,使用Spring Expression Language(简称SpEL,详见参考文献[5])生成。
      • condition : 表示在哪种情况下才缓存结果(对应的还有unless,哪种情况不缓存),同样使用SpEL
    2. 当第一次使用
    {name: 'XiaoMing', address: 'ChengDu'}
    

    调用getFromMem时,会等待一秒钟,然后返回

    {name: 'XIAOMING', address: 'ChengDu'}
    

    再次使用name为’XiaoMing’的对象作为参数调用getFromMem时,会立即返回上一个结果,无论参数中的address是什么。
    但是如果第一次调用时,address为空字符串,第二次调用仍然需要等待一秒钟,这就是condition的作用。

    1.3.2. CacheEvict

    @CacheEvict(value = "models", allEntries = true)
    @Scheduled(fixedDelay = 10000)
    public void deleteFromRedis() {
    }
    
    @CacheEvict(value = "models", key = "#name")
    public void deleteFromRedis(String name) {
    }
    
    1. 例子里的注解 @CacheEvict 中存在有以下几个元素

      • value (也可使用 cacheNames) : 同Cacheable注解,可看做命名空间。表示删除哪个命名空间中的缓存
      • allEntries: 标记是否删除命名空间下所有缓存,默认为false
      • key: 同Cacheable注解,代表需要删除的命名空间下唯一的缓存key
    2. 例子中第一段,与 @Scheduled 注解同时使用,每十秒删除命名空间name下所有的缓存

    3. 第二段,调用此方法后删除命名空间models下, key == 参数 的缓存
      同样含有unless与condition

    1.3.3. CachePut

    @CachePut(value = "models", key = "#name")
    public TestModel saveModel(String name, String address) {
        return new TestModel(name, address);
    }
    
    1. 例子里的注解 @CachePut 中存在有以下几个元素
      • value: 同上
      • key: 同上
      • condition(unless): 同上
    2. 比如可用于后台保存配置时及时刷新缓存。

    1.4. Redis作为缓存配置

    1.4.1. 引用

    1. 再加依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
     </dependency>
    
    1. 然后在配置中添加RedisConnectionFactory用于获取redis链接
     @Value("${spring.redis.host}")
        private String redisHost;
    
        @Value("${spring.redis.port}")
        private int redisPort;
    
        @Value("${spring.redis.timeout}")
        private int redisTimeout;
    
        @Value("${spring.redis.password}")
        private String redisAuth;
    
        @Value("${spring.redis.database}")
        private int redisDb;
    
        @Value("${spring.redis.pool.max-active}")
        private int maxActive;
    
        @Value("${spring.redis.pool.max-wait}")
        private int maxWait;
    
        @Value("${spring.redis.pool.max-idle}")
        private int maxIdle;
    
        @Value("${spring.redis.pool.min-idle}")
        private int minIdle;
    
        @Bean
        public RedisConnectionFactory redisConnectionFactory() {
            JedisPoolConfig poolConfig = new JedisPoolConfig();
            poolConfig.setMaxTotal(maxActive);
            poolConfig.setMaxIdle(maxIdle);
            poolConfig.setMaxWaitMillis(maxWait);
            poolConfig.setMinIdle(minIdle);
            poolConfig.setTestOnBorrow(true);
            poolConfig.setTestOnReturn(false);
            poolConfig.setTestWhileIdle(true);
            JedisClientConfiguration clientConfig = JedisClientConfiguration.builder()
                    .usePooling().poolConfig(poolConfig).and().readTimeout(Duration.ofMillis(redisTimeout)).build();
    
            // 单点redis
            RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
            // 哨兵redis
            // RedisSentinelConfiguration redisConfig = new RedisSentinelConfiguration();
            // 集群redis
            // RedisClusterConfiguration redisConfig = new RedisClusterConfiguration();
            redisConfig.setHostName(redisHost);
            redisConfig.setPassword(RedisPassword.of(redisAuth));
            redisConfig.setPort(redisPort);
            redisConfig.setDatabase(redisDb);
    
            return new JedisConnectionFactory(redisConfig,clientConfig);
        }
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate() {
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            Jackson2JsonRedisSerializer<Object> serializer = jackson2JsonRedisSerializer();
            redisTemplate.setConnectionFactory(redisConnectionFactory());
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(serializer);
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashValueSerializer(serializer);
            return redisTemplate;
        }
    
        @Bean
        public Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
            final Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
            final ObjectMapper objectMapper = Jackson2ObjectMapperBuilder
                    .json().build();
            objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
            return jackson2JsonRedisSerializer;
        }
    
  • 相关阅读:
    算法导论
    深度探索C++对象模型
    git 介绍及其使用总结
    前端跨域常见的几种方式
    前端面试angular 常问问题总结
    低版本浏览器支持HTML5标签的方法
    理解 angular 的路由功能
    Angular 新手容易碰到的坑
    Angular 新手容易碰到的坑
    一 Unicode和UTF-8的异同
  • 原文地址:https://www.cnblogs.com/sky-chen/p/10256157.html
Copyright © 2020-2023  润新知