我需要更改Redis代码,以便它可以与新的SpringBoot 2.0.3一起使用,当前在启动Tomcat 9.0.12时(未以Jar形式启动SpringBoot-业务需求),我得到以下错误:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method vehicleHistoryCacheManager in somePath.config.UfCacheConfig
required a bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' that could not be found.
- Bean method 'redisConnectionFactory' in 'JedisConnectionConfiguration' not loaded because @ConditionalOnMissingBean
(types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all)
beans of type 'org.springframework.data.redis.connection.RedisConnectionFactory' redisConnectionFactory
- Bean method 'redisConnectionFactory' in 'LettuceConnectionConfiguration' not loaded because @ConditionalOnMissingBean
(types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all)
found beans of type 'org.springframework.data.redis.connection.RedisConnectionFactory' redisConnectionFactory
Action:
Consider revisiting the conditions above or defining a bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' in your configuration.
19-Oct-2018 13:43:22.142 SEVERE [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/motoPolicy]]
(...)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'technicalController'
defined in file [somePath\TecController.class]:
Unsatisfied dependency expressed through constructor parameter 0;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'ufCacheServiceImpl'
defined in URL [jar:file:/someName.jar!/somePath/UfCacheServiceImpl.class]:
Unsatisfied dependency expressed through constructor parameter 0;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'vehicleHistoryCacheManager' defined in class path resource
[somePath/config/UfCacheConfig.class]:
Unsatisfied dependency expressed through method 'vehicleHistoryCacheManager' parameter 0;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=vehicleTemplate)}
(...)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ufgCacheServiceImpl'
defined in URL [jar:file:/uf.jar!/somePath/UfgCacheServiceImpl.class]:
Unsatisfied dependency expressed through constructor parameter 0;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'vehicleHistoryCacheManager' defined in class path resource
[somePath/config/UfCacheConfig.class]:
Unsatisfied dependency expressed through method 'vehicleHistoryCacheManager' parameter 0;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=vehicleTemplate)}
(...)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'vehicleHistoryCacheManager' defined in class path resource
[somePath/config/UfCacheConfig.class]:
Unsatisfied dependency expressed through method 'vehicleHistoryCacheManager' parameter 0;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=vehicleTemplate)}
(...)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=vehicleTemplate)}
(...)
19-Oct-2018 13:43:22.162 SEVERE [RMI TCP Connection(3)-127.0.0.1] org.apache.tomcat.util.modeler.BaseModelMBean.invoke Exception invoking method manageApp
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException:
Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/motoPolicy]]
(...)
[2018-10-19 01:43:22,176] Artifact motoPolicy-web:war exploded: Error during artifact deployment. See server log for details.
(...)
19-Oct-2018 13:43:22.162 SEVERE [RMI TCP Connection(3)-127.0.0.1] org.apache.tomcat.util.modeler.BaseModelMBean.invoke Exception invoking method createStandardContext
javax.management.RuntimeOperationsException: Exception invoking method manageApp
(...)
Caused by: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException:
Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/motoPolicy]]
(...)
我对pom中Redis的依赖是:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>5.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.0</version>
</dependency>
这里是redis配置:
@Configuration
class RedisConfig {
@Value("${ufg.redis.host}") // 127.0.0.1
private String hostName;
@Value("${ufg.redis.port}") // 6379
private int port;
@Bean
LettuceConnectionFactory redisConnectionFactory() {
LettuceConnectionFactory redisConnectionFactory = new LettuceConnectionFactory();
redisConnectionFactory.setHostName(hostName);
redisConnectionFactory.setPort(port);
return redisConnectionFactory;
}
@Bean
ObjectMapper redisObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.registerModule(new Jdk8Module());
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+1:00"));
objectMapper.setDateFormat(new ISO8601DateFormat());
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
return objectMapper;
}
}
这是配置类:
@Slf4j
@Configuration
@EnableCaching
public class UfCacheConfig {
public static final String VEHICLE_HISTORY_CACHE_MANAGER = "vehicleHistoryCacheManager";
public static final String VEHICLE_HISTORY_CACHE = "vehicleHistoryCache";
public static final String VEHICLE_GENERATOR_NAME = "vehicleKeyGenerator";
public static final String PERSON_HISTORY_CACHE_MANAGER = "personHistoryCacheManager";
public static final String PERSON_HISTORY_CACHE = "personHistoryCache";
public static final String PERSON_GENERATOR_NAME = "personKeyGenerator";
@Value("${ufg.cache.expiration.validity.minutes}")
private int expirationValidityMinutes;
@Bean(value ="vehicleTemplate")
public RedisTemplate<String, GetVehicleInsuranceHistoryResponse> vehicleTemplate(RedisConnectionFactory redisConnectionFactory,
@Qualifier("redisObjectMapper") ObjectMapper objectMapper) {
RedisTemplate<String, GetVehicleInsuranceHistoryResponse> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
@Primary
@Bean(name = VEHICLE_HISTORY_CACHE_MANAGER)
public CacheManager vehicleHistoryCacheManager(@Qualifier("vehicleTemplate") RedisConnectionFactory redisConnectionFactory) {
Duration expiration = Duration.ofSeconds(expirationValidityMinutes * 60);
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig().entryTtl(expiration)).build();
}
@Bean(value ="personTemplate")
public RedisTemplate<String, GetPersonInsuranceHistoryResponse> redisTemplate(RedisConnectionFactory redisConnectionFactory,
@Qualifier("redisObjectMapper") ObjectMapper objectMapper) {
RedisTemplate<String, GetPersonInsuranceHistoryResponse> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
@Bean(name = PERSON_HISTORY_CACHE_MANAGER)
public CacheManager personHistoryCacheManager(@Qualifier("personTemplate") RedisConnectionFactory redisConnectionFactory) {
Duration expiration = Duration.ofSeconds(expirationValidityMinutes * 60);
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig().entryTtl(expiration)).build();
}
@Bean(name = VEHICLE_GENERATOR_NAME)
public KeyGenerator vehicleKeyGenerator() {
return (o, method, objects) -> new VehicleKeyGenerator((GetVehicleInsuranceHistoryRequest) objects[0]).generate();
}
@Bean(name = PERSON_GENERATOR_NAME)
public KeyGenerator personKeyGenerator() {
return (o, method, objects) -> new PersonKeyGenerator((GetPersonInsuranceHistoryRequest) objects[0]).generate();
}
private static <T> RedisTemplate<String, T> createTemplate(Class<T> clazz, RedisConnectionFactory redisConnectionFactory, ObjectMapper objectMapper) {
RedisTemplate<String, T> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
Jackson2JsonRedisSerializer<T> serializer = new Jackson2JsonRedisSerializer<>(clazz);
serializer.setObjectMapper(objectMapper);
redisTemplate.setValueSerializer(serializer);
return redisTemplate;
}
}
这里是堆栈跟踪中提到的服务类:
@Slf4j
@Service
public class UfCacheServiceImpl implements UfCacheService {
private CacheManager vehicleCacheManager;
private CacheManager personCacheManager;
@Autowired
public UfCacheServiceImpl(@Qualifier(VEHICLE_HISTORY_CACHE_MANAGER) CacheManager vehicleCacheManager,
@Qualifier(PERSON_HISTORY_CACHE_MANAGER) CacheManager personCacheManager) {
this.vehicleCacheManager = vehicleCacheManager;
this.personCacheManager = personCacheManager;
}
@Override
public void clear() {
log.info("Clearing ufg cache");
vehicleCacheManager.getCache(VEHICLE_HISTORY_CACHE).clear();
personCacheManager.getCache(PERSON_HISTORY_CACHE).clear();
}
}
如您所见,我使用了类似的东西,但是redis无法正常工作:
@Bean(value ="vehicleTemplate")
@Qualifier("vehicleTemplate")
编辑:
关于Boris
答案:
在整个项目中,我只能找到jedis
或Jedis
这样的短语,这是pom依赖项。当我删除它们时,输出更改为:
Parameter 0 of method vehicleHistoryCacheManager in somePackages.config.UfCacheConfig required a bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' that could not be found.
- Bean method 'redisConnectionFactory' not loaded because @ConditionalOnClass did not find required class 'redis.clients.jedis.Jedis'
- Bean method 'redisConnectionFactory' in 'LettuceConnectionConfiguration' not loaded because @ConditionalOnMissingBean (types: org.springframework.data.redis.connection.RedisConnectionFactory;
SearchStrategy: all) found beans of type 'org.springframework.data.redis.connection.RedisConnectionFactory' redisConnectionFactory
我找不到像JedisConnectionConfiguration
这样的东西来删除它。
注释了pom中的依赖项后,我在外部库中找不到短语jedis
。
我看到在spring-boot-starter-parent
中带有External Libraries
(在主父pom中)的版本中,我只有spring-data-redis
2.0.8。
答案 0 :(得分:3)
您放置了@ConditionalOnMissingBean注释,该注释仅在BeanFactory中不包含RedisConnectionFactory
类的bean时才匹配。查看日志,我们可以看到您正在尝试同时配置Lettuce和Jedis客户端库:
- Bean method 'redisConnectionFactory' in 'JedisConnectionConfiguration' not loaded because @ConditionalOnMissingBean
- Bean method 'redisConnectionFactory' in 'LettuceConnectionConfiguration' not loaded because @ConditionalOnMissingBean
但是您一次只能使用一个。
如果要使用生菜,请删除JedisConnectionConfiguration
并删除jedis
依赖性。
但是我建议改为使用Redis Starter:
1。。添加spring-boot-starter-data-redis
maven依赖项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2。。删除jedis
和spring-data-redis
maven依赖项
3。。删除@Qualifier批注,因为您无需进一步控制autowiring selection process
设置连接工厂。redisTemplate.setConnectionFactory(connectionFactory);
5。。使用Redis Starter提供的基本自动配置
删除redisConnectionFactory()
方法。
像插入其他任何Spring Bean一样,插入一个自动配置的RedisConnectionFactory
或RedisTemplate
实例,以连接到Redis。
6。。使用Spring Boot Redis属性
Spring Boot使用以下默认Redis属性,您可以在属性文件中覆盖它们:
spring.redis.host=localhost
spring.redis.port=6379
有关更多详细信息,请参见here。