环境变量和@Value 在 Spring Boot 上不能一起工作

Posted

技术标签:

【中文标题】环境变量和@Value 在 Spring Boot 上不能一起工作【英文标题】:Environment variables and @Value can't work together on Spring Boot 【发布时间】:2016-09-03 07:00:00 【问题描述】:

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

---

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

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

@Configuration
@EnableCaching
public class CacheConfiguration 

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

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

在生产中,这个应用程序是 Dockerized,我有以下 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 Boot 将redis.port 读取为tcp://172.17.0.3:6379。因此,对于测试建议,我从CacheConfiguration 类中删除了@Value 注释,并手动将其设置为redis 作为主机和6379 作为端口并且它工作。好像在使用环境变量和@Value 时,Spring 迷路了。有人有想法吗?

【问题讨论】:

您使用的是哪个 Spring Boot 版本?另外我会尝试在 docker compose 文件本身中设置环境变量:environment: redis.port=6379,看看会发生什么。 现在使用 1.3.4。我试试看 【参考方案1】:

基于Docker documentation:

Compose 使用 Docker 链接将服务容器暴露给一个容器 其他。每个链接的容器注入一组环境变量, 每个都以容器的大写名称开头

Docker Compose 将使用 name_PORT 格式创建一个环境变量,表示容器的 完整 URL,例如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 环境变量在特定于 Profile 的应用程序属性方面具有更高的优先级,因此 Spring Boot 将选择 REDIS_PORT 值而不是 @ 987654330@,因此错误:

引起:org.springframework.beans.factory.BeanCreationException: 无法自动装配字段:私有 int com.inkdrop.config.cache.CacheConfiguration.redisPort;嵌套的 异常是 org.springframework.beans.TypeMismatchException: 失败 将类型 [java.lang.String] 的值转换为所需类型 [int]; 嵌套异常是 java.lang.NumberFormatException: 对于输入字符串: "tcp://172.17.0.3:6379"

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

有点离题,但只是引用tutum-docker-redisGithub repository:

此图片将很快被弃用。请使用docker官方 图片:https://hub.docker.com/_/redis/

【讨论】:

我现在不在开发计算机上,我稍后再试试。现在,我认为这正是发生的事情。我现在会接受这个答案:D

以上是关于环境变量和@Value 在 Spring Boot 上不能一起工作的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot- Spring Boot特性2

Spring Boot的特性:外部化配置和配置随机值

Spring Boot 环境变量读取 和 属性对象的绑定

Spring Boot 环境变量读取 和 属性对象的绑定

十Spring Boot 环境变量读取 和 属性对象的绑定

Spring Boot 外部化配置简介