在春季启动时启用Redis缓存

问题描述 投票:7回答:3

我在Spring Boot项目中具有以下配置。

@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;
    }
}

而且我对pom也有以下的maven依赖。

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

我在定义的端口上的本地计算机上运行单独的Redis服务器。同样在我的服务类中,我有@ Cacheable,@ CachePut之类的注释来支持缓存。

我可以启动Spring Boot应用程序而不会出错,CRUD操作也可以。但是似乎它没有使用定义的redis缓存。我使用了“ redi桌面管理器”浏览工具,找不到有关redis的任何数据。我也尝试通过redis cli命令'monitor'来监视Redis服务器,但在监视器上看不到任何更改。

因此,我认为Redis缓存在Spring Boot应用程序上仍然无法正常工作。有人可以帮我解决这个问题吗?

我正在使用Spring Boot 1.4.2.RELEASE

谢谢!

spring-boot redis spring-data-redis spring-cache
3个回答
11
投票

鉴于您使用的是Spring Boot,不需要进行很多Redis配置,因为Spring Boot为Redis提供了[auto-configuration”支持,既是data source也是一个caching provider

您也不确定使用什么版本的[[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 caching以及您的@Configuration“ Application”类,如上所示。并且,因为您可以消除大部分显式配置,并且还使用

Spring Boot's

"auto-configuration" support for Redis作为数据源,所以我在测试类中添加了"AutoRedisConfiguration" @Configuration类。即您可以使用它来配置Redis,而不是我的其他@Configuration类("CustomRedisConfiguration"),它使用您的配置+ fix。这里是完整的测试示例...

/* * 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; } } }

希望这会有所帮助!

干杯,约翰


1
投票
我正在使用Spring Boot 2.0,使用Redis非常简单,以实现简单的缓存目的。

    用@EnableCaching注释Spring引导应用程序>
  1. 在您的application.properties中具有这些属性
  2. spring.cache.type = redisredis.host.url =redis.host.port =

  3. 用@Cacheable注释方法。
  4. 就是这样!

如果使用的是AWS Elasticache,并且已经检查了传输中的加密,那么您需要添加一个RedisConfiguration文件以将ssl设置为true。

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()); }


0
投票
您可以使用redis-cli中的命令检查redis中密钥的存在:

keys *

© www.soinside.com 2019 - 2024. All rights reserved.