SpringBoot中集成Redis

2020-05-16  本文已影响0人  花醉霜寒

\color{green}{添加pom依赖}
此处需要更新jackson的版本,否则会报错

NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.11.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.11.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

\color{green}{配置文件配置}

spring:
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # Redis服务器地址
    host: localhost
    # Redis服务器连接端口
    port: 6379

    lettuce:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0

JedisPool的主要可选参数及参数含义如下所示:

public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneable {

    //当资源池连接用尽后,调用者的最大等待时间(ms),默认值为-1,表示永不超时
    private long maxWaitMillis = DEFAULT_MAX_WAIT_MILLIS;

    //资源池中资源的最小空闲时间(ms),达到此值后空闲资源将被移除,默认值为1000L * 60L * 30L(30min)
    private long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;

    //连接空闲时间大于softMinEvictableIdleTimeMillis并且当前连接池的空闲连接数大于最小空闲连接数minIdle,默认值为-1,表示永不超时
    private long softMinEvictableIdleTimeMillis = DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;

    //空闲资源检测时,每次检测资源的个数。默认值为3,设置为-1表示对所有资源进行检测
    private int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;

    //是否开启空闲资源检测,默认值为false,建议设置为true
    private boolean testWhileIdle = DEFAULT_TEST_WHILE_IDLE;

    //空闲资源的检测周期(单位为毫秒),默认值为-1,表示不检测,建议开启检测,建议设置为30s左右
    private long timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;

    //当资源池用尽后,调用者是否要等待。只有当值为true时,下面的maxWaitMillis才会生效
    private boolean blockWhenExhausted = DEFAULT_BLOCK_WHEN_EXHAUSTED;

    //是否开启JMX监控
    private boolean jmxEnabled = DEFAULT_JMX_ENABLE;
}


public class GenericObjectPoolConfig extends BaseObjectPoolConfig {

    //资源池中的最大连接数,默认值为8
    private int maxTotal = DEFAULT_MAX_TOTAL;

    //资源池允许的最大空闲连接数,默认值为8
    private int maxIdle = DEFAULT_MAX_IDLE;

    //资源池确保的最少空闲连接数,默认值为0
    private int minIdle = DEFAULT_MIN_IDLE;
}

\color{green}{配置类}
1)spring-boot-starter-data-redis 1.x 传统写法

@Configuration
@EnableCaching
public class MyRedisConfig extends CachingConfigurerSupport {
    @Value("${spring.redis.host}")
    private String redisHost;
    @Value("${spring.redis.port}")
    private Integer redisPort;
    @Value("${spring.redis.pool.max-active}")
    private int maxActive;
    @Value("${spring.redis.pool.min-idle}")
    private int minIdle;
    @Value("${spring.redis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.pool.max-wait}")
    private int maxWait;

    @Bean("queryManager")
    @Primary
    public CacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        cacheManager.setDefaultExpiration(1800L);
        return cacheManager;
    }

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        JedisPoolConfig pooConfig = new JedisPoolConfig();
        // 最大空闲连接数, 默认8个
        pooConfig.setMaxIdle(maxIdle);
        // 最大连接数, 默认8个
        pooConfig.setMaxTotal(maxActive);
        // 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,
        // 默认-1
        pooConfig.setMaxWaitMillis(maxWait);
        // 最小空闲连接数, 默认0
        pooConfig.setMinIdle(minIdle);
        JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
        redisConnectionFactory.setHostName(redisHost);
        redisConnectionFactory.setPort(redisPort);
        redisConnectionFactory.setPoolConfig(pooConfig);
        redisConnectionFactory.setPassword(password);
        redisConnectionFactory.setDatabase(database);
        return redisConnectionFactory;
    }
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        JedisConnectionFactory jedisConnectionFactory = (JedisConnectionFactory) redisConnectionFactory;
        redisTemplate.setConnectionFactory(jedisConnectionFactory);
        redisTemplate.setEnableTransactionSupport(false);
        RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(stringRedisSerializer);
        return redisTemplate;
    }
   
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append("wiki-");
                sb.append(target.getClass().getName());
                sb.append(".");
                sb.append(method.getName());
                sb.append("(");
                return sb.append(StringUtils.join(params, ",")).append(")").toString();
            }
        };
    }
}

但是JedisConnectionFactory中很多方法都被废弃了,不推荐使用,需要使用新版本使用全新的实现方式。


2)spring-boot-starter-data-redis 2.x版本写法

@Configuration
@ConfigurationProperties(prefix = "spring.redis")
@ConditionalOnProperty(name = {"spring.redis.host"})
@Data
public class StandaloneRedisConfig {

    private String host;

    private int port;
}
@Configuration
@ConfigurationProperties(prefix = "spring.redis.lettuce.pool")
@Data
public class JedisPoolConfig {

    private int maxActive;

    private int maxWait;

    private int maxIdle;

    private int minIdle;
}
@Configuration
@EnableCaching
public class RedisConfig {

    @Autowired
    StandaloneRedisConfig standaloneRedisConfig;

    @Autowired
    JedisPoolConfig jedisPoolConfig;

    @Bean
    @ConditionalOnBean(value = {StandaloneRedisConfig.class})
    public RedisConnectionFactory standaloneRedisConnectionFactory() {
        //此处可以使用默认的JedisPool,new RedisStandaloneConfiguration(standaloneRedisConfig);
        //如果如果想要自己配置JedisPool的参数可以这样使用
        return new JedisConnectionFactory(new RedisStandaloneConfiguration(standaloneRedisConfig.getHost(), standaloneRedisConfig.getPort()), clientConfiguration());
    }

    @Bean
    @ConditionalOnBean(value = {JedisPoolConfig.class})
    public JedisClientConfiguration clientConfiguration() {
        //配置JedisClientConfiguration并指定JedisPool
        JedisClientConfiguration.JedisClientConfigurationBuilder builder = JedisClientConfiguration.builder();
        return builder.usePooling()
                .poolConfig(poolConfig(jedisPoolConfig))
                .build();
    }

    private GenericObjectPoolConfig poolConfig(JedisPoolConfig config) {
        GenericObjectPoolConfig jedisPool = new GenericObjectPoolConfig();
        jedisPool.setMaxIdle(config.getMaxIdle());
        jedisPool.setMinIdle(config.getMinIdle());
        jedisPool.setMaxTotal(config.getMaxActive());
        return jedisPool;
    }

    @Bean("redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate() {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        RedisConnectionFactory connectionFactory = standaloneRedisConnectionFactory();
        redisTemplate.setConnectionFactory(connectionFactory);
        redisTemplate.setEnableTransactionSupport(false);
        RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(stringRedisSerializer);
        return redisTemplate;
    }


/**
     * 配置jedisPool
     * @return JedisPool
     */
    @Bean("jedisPool")
    public JedisPool createJedis() {
        return new JedisPool(poolConfig(jedisPoolConfig), standaloneRedisConfig.getHost(), standaloneRedisConfig.getPort());
    }



    @Bean
    public SpringConfigProvider springConfigProvider() {
        return new SpringConfigProvider();
    }

    /**
     * 配置jetcache
     * @return GlobalCacheConfig
     */
    @Bean("globalCacheConfig")
    @ConditionalOnBean(value = {JedisPool.class, JedisPool.class})
    @SuppressWarnings("unchecked")
    public GlobalCacheConfig config(){
        Map localBuilders = new HashMap(8);
        EmbeddedCacheBuilder localBuilder = LinkedHashMapCacheBuilder
                .createLinkedHashMapCacheBuilder()
                .keyConvertor(FastjsonKeyConvertor.INSTANCE);
        localBuilders.put(CacheConsts.DEFAULT_AREA, localBuilder);

        Map remoteBuilders = new HashMap(8);
        RedisCacheBuilder remoteCacheBuilder = RedisCacheBuilder.createRedisCacheBuilder()
                .keyConvertor(FastjsonKeyConvertor.INSTANCE)
                .valueEncoder(JavaValueEncoder.INSTANCE)
                .valueDecoder(JavaValueDecoder.INSTANCE)
                .jedisPool(createJedis());
        remoteBuilders.put(CacheConsts.DEFAULT_AREA, remoteCacheBuilder);

        GlobalCacheConfig globalCacheConfig = new GlobalCacheConfig();
        globalCacheConfig.setLocalCacheBuilders(localBuilders);
        globalCacheConfig.setRemoteCacheBuilders(remoteBuilders);
        globalCacheConfig.setStatIntervalMinutes(15);
        globalCacheConfig.setAreaInCacheName(false);
        return globalCacheConfig;
    }

}

除了配置了RedisTemplate,还配置了JedisPool和JetCache。
\color{green}{SpringBoot中使用Redis}
编写测试类进行测试

@Component
public class CacheService {


    @Autowired
    RedisTemplate<String, String> redisTemplate;

    @PostConstruct
    public void test() {
        System.out.println("第一次调用");
        this.getCache("aaa");
        System.out.println("第二次调用");
        this.getCache("aaa");
    }

    private String getCache(String key) {
        String value = redisTemplate.opsForValue().get(key);
        if(StringUtil.isNullOrEmpty(value)) {
            System.out.println("第一次调用缓存中不存在");
            redisTemplate.opsForValue().set("aaa", "bbb");
            return "bbb";
        } else {
            System.out.println("第二次调用直接返回");
            return value;
        }

    }
}

输出结果为:

第一次调用
第一次调用缓存中不存在
第二次调用
第二次调用直接返回
上一篇下一篇

猜你喜欢

热点阅读