我的 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 desktop manger'浏览工具,在redis上找不到任何数据。我还尝试通过 redis cli 命令“monitor”监视 redis 服务器,但在监视器上看不到任何更改。
所以我假设 redis 缓存在我的 spring boot 应用程序上仍然不起作用。有人可以帮我弄清楚这个问题吗?
我正在使用 spring boot 版本 1.4.2.RELEASE
谢谢!
最佳答案
鉴于您正在使用 Spring Boot,您的大部分 Redis 配置都是不必要的,因为 Spring Boot 为 Redis 提供“自动配置”支持, 都是 data source以及 caching provider .
您也没有具体说明您使用的 Spring Boot 版本(例如 1.5.0.RC1
)来运行您的应用程序,或者您是否有任何 application.properties
在您的应用程序的类路径上,如果您明确指定 spring.cache.type
,这可能会有所不同(例如,设置为“redis”以外的其他内容)。
但是,总的来说,我真的看不出您的 Redis 或 Spring Cache 有什么问题 @Configuration
类(class)。但是,未明确设置 cacheManager.setUsePrefix(true)
似乎确实存在问题.当我设置这个 RedisCacheManager
属性 ('usePrefix`),然后一切都按预期工作。
我不是 (Spring Data) Redis 专家,所以我不确定为什么需要这样做。但是,我的测试配置基于 Spring Boot 的 "auto-configuration" support for Redis caching以及你的@Configuration
“应用程序”类,如上所示。
而且,因为您可以消除大部分显式配置并使用Spring Boot "auto-configuration" support for Redis同样作为数据源,我添加了一个 "AutoRedisConfiguration"
@Configuration
类到我的测试类。 IE。您可以使用它来配置 Redis 而不是我的其他 @Configuration
类 ( "CustomRedisConfiguration"
),它使用您的配置 + 修复。
这是完整的测试示例...
/*
* 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;
}
}
}
希望这对您有所帮助!
干杯, 约翰
关于spring-boot - 在 spring boot 中启用 Redis 缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41647382/