环境变量和@Value 无法在 Spring 启动时协同工作

Environment variables and @Value can't work together on Spring Boot

我有一个 Spring 启动应用程序,它连接到用作缓存的 Redis 实例。当我在开发环境中时,我有以下内容:

---

spring:
  profiles: default
redis: 
  host: localhost
  port: 6379

而我的缓存配置class是这样的:

@Configuration
@EnableCaching
public class CacheConfiguration {

   @Value("${redis.host}") 
   String redisHost;

   @Value("${redis.port}") 
   int redisPort;

在生产中,此应用已 Docker 化,我有以下 docker-compose.yml 文件:

redis: 
  image: tutum/redis
  ports:
    - "6379:6379"
  volumes:
    - /data
app: 
  build: .
  ports:
    - "8080:8080"
  links:
    - redis

application.yml 是:

---

spring:
  profiles: docker
redis: 
  host: redis
  port: 6379

要在 Docker 上启动应用程序,我 运行 使用 -Dspring.profiles.active=docker,但是当应用程序启动时,出现以下错误:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private int com.inkdrop.config.cache.CacheConfiguration.redisPort; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type [java.lang.String] to required type [int]; nested exception is java.lang.NumberFormatException: For input string: "tcp://172.17.0.3:6379"

出于某种原因,Spring 引导将 redis.port 读取为 tcp://172.17.0.3:6379。因此,对于测试建议,我从 CacheConfiguration class 中删除了 @Value 注释,并手动将其设置为 redis 作为主机和 6379 作为端口并且它起作用了。好像在使用环境变量和 @Value、Spring 时迷路了。有人有想法吗?

基于Docker documentation

Compose uses Docker links to expose services containers to one another. Each linked container injects a set of environment variables, each of which begins with the uppercase name of the container.

Docker Compose 将使用 [= 创建一个环境变量,表示容器的 Full URL 43=] 格式,例如REDIS_PORT=tcp://172.17.0.5:6379.

并根据您的 docker-compose.yml 文件:

redis: 
  image: tutum/redis
  ports:
    - "6379:6379"
  volumes:
    - /data

您将有一个名为 REDIS_PORT 的环境变量,其值等于 tcp://172.17.0.3:6379。由于 OS 环境变量在特定于配置文件的应用程序属性方面具有更高的优先级,Spring Boot 会选择 REDIS_PORT 超过 redis.port 的值,因此出现错误:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private int com.inkdrop.config.cache.CacheConfiguration.redisPort; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type [java.lang.String] to required type [int]; nested exception is java.lang.NumberFormatException: For input string: "tcp://172.17.0.3:6379"

作为此问题的解决方法,您应该使用您的端口值覆盖 REDIS_PORT 环境变量,或者将您的配置名称从 redis.name 重命名为任何争议较小的名称。

有点离题但只是引用 tutum-docker-redis Github repository:

This image will be deprecated soon. Please use the docker official image: https://hub.docker.com/_/redis/