我的弹簧启动项目配置如下.
@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
我也跟随maven对pom的依赖.
org.springframework.boot spring-boot-starter-data-redis
我在定义端口上的本地计算机上运行了一个单独的redis服务器.另外在我的服务类中,我有@Cacheable,@ CachePut等注释来支持缓存.
我可以毫无错误地启动Spring启动应用程序,并且CRUD操作也可以.但似乎它没有使用定义的redis缓存.我使用'redi desktop manger'浏览工具,但在redis上找不到任何数据.我也尝试通过redis cli命令'monitor'监控redis服务器,我在监视器上看不到任何变化.
所以我认为redis缓存仍然不能用于我的spring启动应用程序.有人可以帮我弄清楚这个问题吗?
我使用的是春季启动版1.4.2.RELEASE
谢谢!
鉴于您使用的是Spring Boot,因此大部分Redis配置都是不必要的,因为Spring Boot为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 对Redis缓存的" 自动配置 "支持以及@Configuration
上面显示的"应用程序"类.
而且,因为您可以消除大部分显式配置并使用Spring Boot 对Redis 的"自动配置"支持作为数据源,所以我"AutoRedisConfiguration"
@Configuration
在我的测试类中添加了一个类.即你可以使用它来配置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 RedisTemplateredisTemplate; @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 redisTemplate() { RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(jedisConnectionFactory()); return redisTemplate; } @Bean CacheManager cacheManager() { RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate()); cacheManager.setUsePrefix(true); // THIS IS NEEDED! return cacheManager; } } }
希望这可以帮助!
干杯,约翰