springboot2.xまとめ——Redisと注釈開発の統合

36655 ワード

一、Redisの統合
1.依存関係の追加

<dependency>
	<groupId>org.springframework.bootgroupId>
	<artifactId>spring-boot-starter-data-redisartifactId>
dependency>

<dependency>
	<groupId>org.apache.commonsgroupId>
	<artifactId>commons-pool2artifactId>
dependency>

2.考え方と原理
考え方:
  • RedisConfig構成クラスを作成する---構成クラスの中でredisTemplateとcacheManagerを再構築する;このクラスでkeyの生成ポリシーなどを設定することもできます...
  • は、オブジェクトのキャッシュを実装し、独自のシーケンス化および逆シーケンス化器を定義する.

  • 原理解析:redisのstarter依存を導入すると、
    org.springframework.boot.autoconfigure.cache.RedisCacheConfigurationが機能し、RedisCacheManagerを作成し、RedisCacheManagerからRedisCacheを作成します.
    デフォルトorg.springframework.boot.autoconfigure.cache.SimpleCacheConfigurationはCacheManagerが既に存在していることが判明しても有効になりません.デフォルトのConcurrentMapCacheManagerも作成されず、ConcurrentMapCacheも作成されません.
    これによりキャッシュはデフォルトのConcurrentMapCacheからRedisCacheに切り替わる.
    そこで,@Cacheable,@CacheEveit,@CachePutを使用すると,redisにデータが緩和される.
    しかし、直接キャッシュすると、データがredisに格納されるのはJSON形式ではありません.デフォルトのredisTemplateはJDKシーケンス化メカニズムを使用しているため、バイナリで保存されたデータであり、グラフィック化展示には不利です.
    したがって、redisのカスタムシーケンス化設定も行います.
    package com.haocheng.study.util.redis;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.cache.CacheManager;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.cache.RedisCacheConfiguration;
    import org.springframework.data.redis.cache.RedisCacheManager;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.RedisSerializationContext;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    import java.time.Duration;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * Redis   
     * @Author: haocheng
     * @Date: 2019-10-17 16:44
     */
    @Configuration
    //    
    @EnableCaching
    public class RedisConfig{
        /**
         *    redisTemplate
         * @param factory
         * @return
         */
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    
            //  Fastjson2JsonRedisSerializer         
            FastJson2JsonRedisSerializer fastJson2JsonRedisSerializer = new FastJson2JsonRedisSerializer(Object.class);
    
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(factory);
            //        redis key 
            template.setKeySerializer(new StringRedisSerializer());
            template.setHashKeySerializer(new StringRedisSerializer());
            //        redis value 
            template.setValueSerializer(fastJson2JsonRedisSerializer);
            template.setHashValueSerializer(fastJson2JsonRedisSerializer);
            template.afterPropertiesSet();
            return template;
        }
    
        /**
         *      jackson  json   
         * @return
         */
    //    @Bean
    //    public RedisSerializer jackson2JsonRedisSerializer() {
    //        //  Jackson2JsonRedisSerializer         redis value 
    //        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
    //
    //        ObjectMapper mapper = new ObjectMapper();
    //        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    //        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    //        serializer.setObjectMapper(mapper);
    //        return serializer;
    //    }
    
    
        /**
         *         
         * @param redisConnectionFactory
         * @return
         */
        @Bean
        public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    
            //  Fastjson2JsonRedisSerializer         redis value 
            FastJson2JsonRedisSerializer fastJson2JsonRedisSerializer = new FastJson2JsonRedisSerializer(Object.class);
    
            //         ,  config              
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
            //            ,    Duration  
            config = config.entryTtl(Duration.ofMinutes(1))
                    //    key string   
                    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                    //   value json   
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJson2JsonRedisSerializer))
                    //      
                    .disableCachingNullValues();
    
            //             set  
            Set<String> cacheNames = new HashSet<>();
            cacheNames.add("cache1");
            cacheNames.add("cache2");
    
            //               
            Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
            configMap.put("cache1", config);
            configMap.put("cache2", config.entryTtl(Duration.ofSeconds(120)));
    
            //                cacheManager
            RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
                    //                   ,         
                    .initialCacheNames(cacheNames)
                    .withInitialCacheConfigurations(configMap)
                    .build();
            return cacheManager;
        }
    
    }
    
    

    注意:fastjsonによるシーケンス化
    package com.haocheng.study.util.redis;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.parser.ParserConfig;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.SerializationException;
    
    import java.nio.charset.Charset;
    
    /**
     *   FastJson        
     *
     * @Author: haocheng
     * @Date: 2019-10-18 14:36
     */
    public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
    
        private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
        private Class<T> clazz;
        public FastJson2JsonRedisSerializer(Class<T> clazz) {
            super();
            this.clazz = clazz;
        }
    
        static {
    //          fastjson   :     class    ,      ,
    //        fastjson        autoType   ,          ,
    //                      autoType ,
    //              com.alibaba.fastjson.JSONException: autoType is not support   
    //        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
            ParserConfig.getGlobalInstance().addAccept("com.haocheng.study.model.");
        }
    
        @Override
        public byte[] serialize(T t) throws SerializationException {
            if (null == t) {
                return new byte[0];
            }
            return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
        }
    
        @Override
        public T deserialize(byte[] bytes) throws SerializationException {
            if (null == bytes || bytes.length <= 0) {
                return null;
            }
            String str = new String(bytes, DEFAULT_CHARSET);
            return (T) JSON.parseObject(str, clazz);
        }
    }
    
    

    二、注釈式開発
    サービスで直接使えばいいです
    //@Cacheable  key name      cache2 
    @Cacheable(value = "cache2", key = "'#param'", unless="#result == null")
    public void getDept(String name){
        System.out.println("        " + name + ",     ");
    }
    
    // @CacheEvict   cache2   key name   
    @CacheEvict(value = "cache2", key = "#param")
    public void removeDept(String name) {
       System.out.println("    " + name + ",         ");
    }
    

    共通キャッシュ注記の説明
    1.@Cacheable:主にメソッドに対して構成され、メソッドの要求パラメータに基づいて結果をキャッシュできる
    主なパラメータの説明:
  • value:キャッシュの名前springプロファイルで定義するには、少なくとも1つの
  • を指定する必要があります.
    eg:@Cacheable(value="cache")または@Cacheable(value={"cache 1","cache 2"}です.
  • key:キャッシュされたkey、空の
  • SpEL式で記述するように指定した場合、指定しない場合、デフォルトではメソッドのすべてのパラメータを組み合わせます.たとえば、@Cacheable(value="testcache",key="#userName").
  • condition:キャッシュの条件は、空であってもよい、
  • 例:
    @Cacheable(value = "my-redis-cache1" ,key = "'book'+#book_id" ,condition = "#book_id>8")
    public Book selectByPrimaryKey(Long book_id) {
        return bookMapper.selectByPrimaryKey(book_id);
    }
    

    2.@CachePut:メソッドの要求パラメータに基づいて結果をキャッシュできるメソッド構成を主に目的としています.@Cacheableとは異なり、毎回実際のクエリがトリガーされます.
    メソッドの呼び出し
    主なパラメータの説明:
    パラメータ構成は@Cacheableと同じです.
    @CachePut(value = "my-redis-cache2")  //    
    public Book selectByPrimaryKey(Long book_id) {
        return bookMapper.selectByPrimaryKey(book_id);
    }
    

    3.@CacheEveict:主にメソッド構成で、一定の条件に従ってキャッシュをクリアできる
    主なパラメータの説明:
  • value,keyおよびconditionパラメータ構成は@Cacheableと同じです.
  • allEntries:すべてのキャッシュ・コンテンツを空にするかどうか、デフォルトはfalse、
  • trueとして指定すると、メソッド呼び出し後すぐにすべてのキャッシュが空になります.
    eg:@CachEvict(value=”testcache”,allEntries=true).
    @CacheEvict(value = "my-redis-cache2" ,allEntries = true)
    public void clean(){
        System.out.println("  my-redis-cache2  ..........");
    }
    
  • beforeInvocation:メソッドの実行前にクリアするかどうか、デフォルトはfalse、trueと指定すると、メソッドがまだ実行されていないときにキャッシュがクリアされます.デフォルトでは、メソッドが例外を放出するとキャッシュはクリアされません.
  • eg: @CachEvict(value=”testcache”,beforeInvocation=true).