All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.rustknife.jknife.cache.config.AppCacheConfig Maven / Gradle / Ivy

The newest version!
package com.rustknife.jknife.cache.config;

import com.rustknife.jknife.cache.*;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.lang.Nullable;

import javax.annotation.Resource;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;

/**
 * 缓存配置,支持 ehcache + redis 混合部署
 * 注: 1、cache name 以 "redis" 打头自动使用 redis
 *      2、ehcache 可以不用任何配置,未配置的将会自动创建并使用默认配置,默认缓存永不过期,但是建议配置一下 diskStore path
 *      3、ehcache 可以在 ehcache.xml 中配置需要自定义配置的 cache,默认缓存无需配置,配置项不会生效
 *      4、未做 redis 连接失败处理,确保未配置 redis 的服务不访问 redis 相关接口
 *      5、非注解常用操作使用 CacheKit 工具(如 remove 等,CacheKit 同样将自动识别是否为 redis 操作),
 *         复杂操作可以根据缓存类型分别 使用 CacheEhCacheKit 和 CacheRedisKit 工具
 * yoke 2018-05-18
 */
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
@Configuration
@EnableCaching
public class AppCacheConfig extends CachingConfigurerSupport
{
    @Resource
    private RedisProperties redisProperties;
    
    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(".");
            sb.append(method.getName());
            sb.append("(");
            boolean first = true;
            for (Object obj : params) {
                if(!first) sb.append(",");
                else first = false;
                sb.append(obj.toString());
            }
            sb.append(")");
            return sb.toString();
        };
    }

    @Bean
    //@ConditionalOnClass(value=org.springframework.data.redis.cache.RedisCache.class)
    public RedisCacheManager redisCacheManager(@Qualifier("redisTemplate") RedisTemplate redisTemplate) {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .computePrefixWith(new DefaultRedisCachePrefix())
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getKeySerializer()))        //key序列化方式
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()))    //value序列化方式
                .disableCachingNullValues()                 //不缓存null值
                .entryTtl(Duration.ofSeconds(60 * 60));     //默认缓存过期时间

        //CacheRedisKit.setUsePrefix(true);

        return RedisCacheManager.builder(redisTemplate.getConnectionFactory())
                .cacheDefaults(redisCacheConfiguration)
                .transactionAware()
                .build();
    }

    @Bean("redisTemplate")
    @Primary
    public RedisTemplate redisTemplate(
            LettuceConnectionFactory redisConnectionFactory){
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        RedisSerializer stringSerializer = new StringRedisSerializer();
        template.setDefaultSerializer(stringSerializer);
        template.setKeySerializer(stringSerializer);
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashKeySerializer(stringSerializer);
        template.setHashValueSerializer(stringSerializer);
        return template;
    }

    /**
     * 工具类专用
     * @param redisConnectionFactory redisConnectionFactory
     * @return RedisTemplate
     * @throws UnknownHostException UnknownHostException
     */
    @Bean("redisTemplateRawKey")
    public RedisTemplate redisTemplateRawKey(
            LettuceConnectionFactory redisConnectionFactory){
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        RedisSerializer stringSerializer = new StringRedisSerializer();
        template.setEnableDefaultSerializer(false);
        template.setKeySerializer(null);
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashKeySerializer(stringSerializer);
        template.setHashValueSerializer(stringSerializer);
        return template;
    }

    /**
     * session 专用
     * @return RedisTemplate
     * @throws UnknownHostException UnknownHostException
     */
    @Bean("redisTemplateSession")
    public RedisTemplate redisTemplateSession(){
        LettuceConnectionFactory redisConnectionFactory = this.createSessionLettuceConnectionFactory();

        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        RedisSerializer stringSerializer = new StringRedisSerializer();
        template.setEnableDefaultSerializer(false);
        template.setKeySerializer(null);
        template.setValueSerializer(new ObjectRedisSerializer());
        template.setHashKeySerializer(stringSerializer);
        template.setHashValueSerializer(stringSerializer);
        return template;
    }

    public static class String2JsonRedisSerializer extends StringRedisSerializer {
        @Override
        public String deserialize(@Nullable byte[] bytes) {
            String ret = (bytes == null ? null : new String(bytes, StandardCharsets.UTF_8));
            if(ret != null && ret.length() >= 2) {
                if(ret.charAt(0) == '\"' && ret.charAt(ret.length() - 1) == '\"')
                    ret = ret.substring(1, ret.length() - 1);
            }
            return ret;
        }
        @Override
        public byte[] serialize(@Nullable String string) {
            return (string == null ? null : (("\"" + string + "\"").getBytes(StandardCharsets.UTF_8)));
        }
    }
    /**
     * Token 专用
     * @return RedisTemplate
     * @throws UnknownHostException UnknownHostException
     */
    @Bean("redisTemplateToken")
    public StringRedisTemplate redisTemplateToken(){
        LettuceConnectionFactory redisConnectionFactory = this.createTokenLettuceConnectionFactory();

        /*
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        template.setValueSerializer(new String2JsonRedisSerializer());
        template.setHashValueSerializer(new String2JsonRedisSerializer());
        template.setEnableDefaultSerializer(false);
        template.setStringSerializer(new String2JsonRedisSerializer());
        template.setDefaultSerializer(new String2JsonRedisSerializer());
        return template;
        */
        // String2JsonRedisSerializer 与 weixin-mp-java库冲突, 其 unlock 时脚本执行将异常,全部用 StringRedisSerializer
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(RedisSerializer.string());
        template.setValueSerializer(RedisSerializer.string());
        template.setHashValueSerializer(RedisSerializer.string());
        template.setEnableDefaultSerializer(false);
        template.setStringSerializer(RedisSerializer.string());
        template.setDefaultSerializer(RedisSerializer.string());
        return template;
    }

    @Bean
    public AppEhCacheCacheManager ehCacheCacheManager(net.sf.ehcache.CacheManager cacheManager) {
        return new AppEhCacheCacheManager(cacheManager);
    }

    @Bean
    public AppEhCacheManagerFactoryBean ehcache() {
        AppEhCacheManagerFactoryBean ehCacheManagerFactoryBean = new AppEhCacheManagerFactoryBean();
        ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
        return ehCacheManagerFactoryBean;
    }
    
    @Bean
    @Override
    public CacheManager cacheManager() {
        return new AppCacheManager();
    }

    @Override
    public CacheErrorHandler errorHandler() {
        return null;
    }

    private LettuceConnectionFactory createSessionLettuceConnectionFactory() {
        return createCustomLettuceConnectionFactory(
                2,
                redisProperties.getHost(),
                redisProperties.getPort(),
                redisProperties.getPassword(),
                4,
                0,
                8,
                1000 * 10L,
                1000 * 10L,
                1000 * 4L
        );
    }

    private LettuceConnectionFactory createTokenLettuceConnectionFactory() {
        return createCustomLettuceConnectionFactory(
                3,
                redisProperties.getHost(),
                redisProperties.getPort(),
                redisProperties.getPassword(),
                4,
                0,
                8,
                1000 * 10L,
                1000 * 10L,
                1000 * 4L
        );
    }

    public static  LettuceConnectionFactory createCustomLettuceConnectionFactory(
            int dbIndex,
            String hostName,
            int port,
            String password,
            int maxIdle,
            int minIdle,
            int maxActive,
            Long maxWait,
            Long timeOut,
            Long shutdownTimeOut){

        RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration(hostName, port);
        redisConfiguration.setDatabase(dbIndex);
        redisConfiguration.setPassword(password);

        GenericObjectPoolConfig genericObjectPoolConfig =
                new GenericObjectPoolConfig();
        genericObjectPoolConfig.setMaxIdle(maxIdle);
        genericObjectPoolConfig.setMinIdle(minIdle);
        genericObjectPoolConfig.setMaxTotal(maxActive);
        genericObjectPoolConfig.setMaxWaitMillis(maxWait);

        LettuceClientConfiguration lettuceClientConfiguration = LettucePoolingClientConfiguration
                .builder()
                .commandTimeout(Duration.ofMillis(timeOut))
                .shutdownTimeout(Duration.ofMillis(shutdownTimeOut))
                .poolConfig(genericObjectPoolConfig)
                .build();

        LettuceConnectionFactory lettuceConnectionFactory = new
                LettuceConnectionFactory(redisConfiguration,lettuceClientConfiguration);
        lettuceConnectionFactory .afterPropertiesSet();

        return lettuceConnectionFactory;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy