web-dev-qa-db-ja.com

Spring BootでRedisキャッシュを有効にする

私の春のブートプロジェクトで次の構成があります。

@SpringBootApplication
@EnableTransactionManagement
@EnableCaching
@EnableScheduling
@EnableAsync
public class Application {

    String redisHost = "localhost";
    int redisPort = 6379;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(redisHost);
        factory.setPort(redisPort);
        factory.setUsePool(true);
        return factory;
    }
    @Bean
    RedisTemplate<Object, Object> redisTemplate() {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object, Object>();
        redisTemplate.setConnectionFactory(jedisConnectionFactory());
        return redisTemplate;
    }
    @Bean
    public CacheManager cacheManager() {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate());
        return cacheManager;
    }
}

また、私は以下のmavenがpomに依存している。

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

ローカルマシンの定義されたポートで別のredisサーバーを実行しています。また、サービスクラスには、キャッシュをサポートするための@ Cacheable、@ CachePutなどの注釈があります。

エラーなしでスプリングブートアプリケーションを起動でき、CRUD操作も機能します。しかし、定義されたredisキャッシュを使用していないようです。 「rediデスクトップマネージャー」ブラウジングツールを使用しましたが、redisでデータを見つけることができませんでした。また、redis cliコマンド 'monitor'を使用してredisサーバーを監視しようとしましたが、モニターで変更を確認できません。

だから私はまだ私の春のブートアプリケーションでredisキャッシュが機能していないと思います。誰かが問題を解決するのを手伝ってくれる?

スプリングブートバージョン1.4.2を使用しています。リリース

ありがとう!

8
lsc

Spring Bootを使用している場合、Spring Bootは "を提供するため、Redis構成の多くは不要です。 データソース および キャッシングプロバイダー の両方としてのRedisの自動構成 "サポート。

また、アプリケーションの実行に使用しているSpring Bootのバージョン(例:_1.5.0.RC1_)、または_application.properties_がオンになっているかどうかについても明確ではありませんでしたアプリケーションのクラスパス。明示的に_spring.cache.type_を指定した場合は、違いが生じる可能性があります(たとえば、「redis」以外に設定します)。

しかし、一般的に、私はあなたのRedisまたはSpring Cache_@Configuration_クラスで実際に多くの誤りを見つけることはできません。ただし、cacheManager.setUsePrefix(true)を明示的に設定しないと問題になるようです。このRedisCacheManagerプロパティ( 'usePrefix`)を設定すると、すべてが期待どおりに機能しました。

私は(Spring Data)Redisのエキスパートではないので、なぜこれが必要なのか正確にはわかりません。ただし、テスト構成はSpring Boot's"auto-configuration" support for Redis cache に基づいています上記の_@Configuration_ "Application"クラスも同様です。

また、明示的な構成のほとんどを排除して、Spring Boot's "auto-configuration"サポートを使用できるため、 Redis もデータソースとして、テストクラスに_"AutoRedisConfiguration"_ _@Configuration_クラスを追加しました。つまりこれを使用して、構成を使用する他の_@Configuration_クラス(_"CustomRedisConfiguration"_)+fixの代わりにRedisを構成できます。

これが完全なテスト例です...

_/*
 * Copyright 2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.Apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.spring.cache;

import static org.assertj.core.api.Assertions.assertThat;

import Java.util.Arrays;
import Java.util.Properties;
import Java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.PostConstruct;

import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.spring.cache.CachingWithRedisIntegrationTest.CachingWithRedisConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Assert;

/**
 * Integration tests testing Spring's Cache Abstraction using Spring Data Redis auto-configured with Spring Boot.
 *
 * To run this test, first start a Redis Server on localhost listening on the default port, 6379.
 *
 * @author John Blum
 * @see org.junit.Test
 * @since 1.0.0
 */
@RunWith(SpringRunner.class)
@ActiveProfiles("auto")
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@ContextConfiguration(classes = CachingWithRedisConfiguration.class)
@SuppressWarnings("unused")
public class CachingWithRedisIntegrationTest {

  protected static final int REDIS_PORT = 6379;
  protected static final String REDIS_Host = "localhost";

  private AtomicBoolean setup = new AtomicBoolean(false);

  @Autowired
  private MathService mathService;

  @Autowired(required = false)
  private RedisTemplate<Object, Object> redisTemplate;

  @Before
  public void setup() {
    if (redisTemplate != null && !setup.getAndSet(true)) {
      redisTemplate.delete(Arrays.asList(0L, 1L, 2L, 4L, 8L));
    }
  }

  @Test
  public void firstCacheMisses() {
    assertThat(mathService.factorial(0L)).isEqualTo(1L);
    assertThat(mathService.wasCacheMiss()).isTrue();
    assertThat(mathService.factorial(1L)).isEqualTo(1L);
    assertThat(mathService.wasCacheMiss()).isTrue();
    assertThat(mathService.factorial(2L)).isEqualTo(2L);
    assertThat(mathService.wasCacheMiss()).isTrue();
    assertThat(mathService.factorial(4L)).isEqualTo(24L);
    assertThat(mathService.wasCacheMiss()).isTrue();
    assertThat(mathService.factorial(8L)).isEqualTo(40320L);
    assertThat(mathService.wasCacheMiss()).isTrue();
  }

  @Test
  public void thenCacheHits() {
    assertThat(mathService.factorial(0L)).isEqualTo(1L);
    assertThat(mathService.wasCacheMiss()).isFalse();
    assertThat(mathService.factorial(1L)).isEqualTo(1L);
    assertThat(mathService.wasCacheMiss()).isFalse();
    assertThat(mathService.factorial(2L)).isEqualTo(2L);
    assertThat(mathService.wasCacheMiss()).isFalse();
    assertThat(mathService.factorial(4L)).isEqualTo(24L);
    assertThat(mathService.wasCacheMiss()).isFalse();
    assertThat(mathService.factorial(8L)).isEqualTo(40320L);
    assertThat(mathService.wasCacheMiss()).isFalse();
  }

  interface MathService {
    boolean wasCacheMiss();
    long factorial(long number);
  }

  @EnableCaching
  @SpringBootConfiguration
  @Import({ AutoRedisConfiguration.class, CustomRedisConfiguration.class })
  static class CachingWithRedisConfiguration {

    @Bean
    MathService mathService() {
      return new MathService() {
        private final AtomicBoolean cacheMiss = new AtomicBoolean(false);

        @Override
        public boolean wasCacheMiss() {
          return cacheMiss.getAndSet(false);
        }

        @Override
        @Cacheable(cacheNames = "Factorials")
        public long factorial(long number) {
          cacheMiss.set(true);

          Assert.isTrue(number >= 0L, String.format("Number [%d] must be greater than equal to 0", number));

          if (number <= 2L) {
            return (number < 2L ? 1L : 2L);
          }

          long result = number;

          while (--number > 1) {
            result *= number;
          }

          return result;
        }
      };
    }

    @Bean
    @Profile("none")
    CacheManager cacheManager() {
      return new ConcurrentMapCacheManager();
    }
  }

  @Profile("auto")
  @EnableAutoConfiguration
  @SpringBootConfiguration
  static class AutoRedisConfiguration {

    @PostConstruct
    public void afterPropertiesSet() {
      System.out.println("AUTO");
    }

    @Bean
    static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
      PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer =
        new PropertySourcesPlaceholderConfigurer();
      propertySourcesPlaceholderConfigurer.setProperties(redisProperties());
      return propertySourcesPlaceholderConfigurer;
    }

    static Properties redisProperties() {
      Properties redisProperties = new Properties();

      redisProperties.setProperty("spring.cache.type", "redis");
      redisProperties.setProperty("spring.redis.Host", REDIS_Host);
      redisProperties.setProperty("spring.redis.port", String.valueOf(REDIS_PORT));

      return redisProperties;
    }
  }

  @Profile("custom")
  @SpringBootConfiguration
  static class CustomRedisConfiguration {

    @PostConstruct
    public void afterPropertiesSet() {
      System.out.println("CUSTOM");
    }

    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
      JedisConnectionFactory factory = new JedisConnectionFactory();
      factory.setHostName(REDIS_Host);
      factory.setPort(REDIS_PORT);
      factory.setUsePool(true);
      return factory;
    }

    @Bean
    RedisTemplate<Object, Object> redisTemplate() {
      RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
      redisTemplate.setConnectionFactory(jedisConnectionFactory());
      return redisTemplate;
    }

    @Bean
    CacheManager cacheManager() {
      RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate());
      cacheManager.setUsePrefix(true); // THIS IS NEEDED!
      return cacheManager;
    }
  }
}
_

お役に立てれば!

乾杯、ジョン

11
John Blum

私はSpring Boot 2.0を使用していますが、単純なキャッシュの目的でRedisを使用するのは非常に簡単です。

  1. @EnableCachingを使用してSpringブートアプリケーションに注釈を付ける
  2. あなたのapplication.propertiesにこれらのプロパティがあります

    spring.cache.type = redis redis.Host.url = redis.Host.port =

  3. @Cacheableでメソッドに注釈を付けます。

それでおしまい!!

AWS Elasticacheを使用していて、転送中の暗号化をチェックしている場合は、sdisをtrueに設定するRedisConfigurationファイルを追加する必要があります。

Spring Boot 2.0がLettuceConnectionFactoryを使用するようになりました。

上記を行うには、クラスを追加し、@ Configurationアノテーションを付けて、次のBeanを追加するだけです。

@Bean
  public LettuceConnectionFactory redisConnectionFactory() {
    RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
    configuration.setHostName(redisHost);
    configuration.setPort(redisPort);
    return new LettuceConnectionFactory(configuration,            LettuceClientConfiguration.builder().useSsl().disablePeerVerification().build());
  }
1
Sukalpo

Redis-cliのコマンドを使用して、redisにキーの存在を確認できます:keys *

あなたの鍵があれば、すべてがOKです:)

0
S.Dayneko