programing

Spring Boot의 application.properties에서 env 변수 사용

goodcopy 2022. 7. 24. 23:09
반응형

Spring Boot의 application.properties에서 env 변수 사용

Spring Boot 웹 어플리케이션에서 작업하고 있으며 사용하고 있는 데이터베이스는 MySQL입니다.

  • 셋업은 처음에 로컬로 테스트하는 것입니다(즉, MySQL을 PC에 설치해야 합니다).

  • 그리고 비트버킷으로 간다.

  • Jenkins는 Bitbucket에 대한 새로운 푸시를 자동으로 감지하고 Bitbucket을 기반으로 구축합니다(Jenkins mvn 빌드를 통과하려면 Jenkins를 실행하는 가상 머신에도 MySQL을 설치해야 합니다).

  • Jenkins 빌드가 통과하면 OpenShift의 어플리케이션에 코드를 푸시합니다(Jenkins의 Openstime 배포 플러그인 사용).

우리가 안고 있는 문제는, 여러분이 이미 알고 계시겠지만, 다음과 같습니다.

  • application.propertiesMySQL 정보를 하드코드로 만들 수 없습니다.우리의 프로젝트는 3개의 다른 장소(로컬, 젠킨스, OpenShift)에서 실행되기 때문에 데이터 소스 필드를 동적으로 만들어야 합니다.application.properties(여러 가지 방법이 있다는 것을 알지만, 현재 이 솔루션에 임하고 있습니다.

      spring.datasource.url = 
      spring.datasource.username = 
      spring.datasource.password = 
    

우리가 생각해낸 솔루션은 시스템 환경 변수를 로컬 및 Jenkins VM에 생성하고(OpenShift와 동일한 방식으로 명명), 각각 올바른 값을 할당하는 것입니다.

export OPENSHIFT_MYSQL_DB_HOST="jdbc:mysql://localhost"
export OPENSHIFT_MYSQL_DB_PORT="3306"
export OPENSHIFT_MYSQL_DB_USERNAME="root"
export OPENSHIFT_MYSQL_DB_PASSWORD="123asd"

우리는 이것을 했고 효과가 있다.했는데,Map<String, String> env = System.getenv();다음과 같이 환경 변수를 Java 변수로 만들 수 있습니다.

String password = env.get("OPENSHIFT_MYSQL_DB_PASSWORD");   
String userName = env.get("OPENSHIFT_MYSQL_DB_USERNAME");   
String sqlURL = env.get("OPENSHIFT_MYSQL_DB_HOST"); 
String sqlPort = env.get("OPENSHIFT_MYSQL_DB_PORT");

Java 를 Java에서 .application.properties그리고 그것이 우리가 어려움을 겪고 있는 것입니다.

?password,userName,sqlURL , , , , 입니다.sqlPort를 지정합니다.application.properties을 볼 수 하기 , 그리고 을 「이것들」의 「이것들」의 「이것들」의 「이것들」의 「이것들」에 시킬 수 있을까요?application.properties

우리는 그 중 하나로서 많은 것을 시도했다.

spring.datasource.url = ${sqlURL}:${sqlPort}/"nameofDB"
spring.datasource.username = ${userName}
spring.datasource.password = ${password}

아직까지는 운이 없다.를 올바른 하고 있을 수 .application.properties.

Java ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」하려면 , 을 시스템에 추가합니다.application.properties 삭제:

spring.datasource.url = ${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/"nameofDB"
spring.datasource.username = ${OPENSHIFT_MYSQL_DB_USERNAME}
spring.datasource.password = ${OPENSHIFT_MYSQL_DB_PASSWORD}

단, @Stefan Isele이 제안하는 방법이 더 바람직합니다.이 경우 env 변수를 1개만 선언하면 되기 때문입니다.spring.profiles.activeapplication-{profile-name}.properties플릿입입니니다

환경에 따라 구성을 달리하는 가장 쉬운 방법은 스프링 프로파일을 사용하는 것입니다.외부 설정을 참조해 주세요.

이것은 당신에게 많은 유연성을 줍니다.나는 그것을 내 프로젝트에 사용하고 있고 그것은 매우 도움이 된다.이 경우 'local', 'jenkins' 및 'openshift'의 3가지 프로파일이 있습니다.

고유의 파일3」)을 갖게 됩니다.application-local.properties,application-jenkins.properties , , , , 입니다.application-openshift.properties

여기서 관련 환경의 속성을 설정할 수 있습니다.할 때 해야 활성화 됩니다.-Dspring.profiles.active=jenkins

편집

변수를 할 수 .SPRING_PROFILES_ACTIVE프로파일을 활성화하고 파라미터로 전달할 필요가 없습니다.

실행 시 웹 앱에 대한 활성 프로파일 옵션을 전달할 수 있는 방법이 있습니까?

아니요. 스프링은 애플리케이션 컨텍스트를 구축할 때 첫 번째 단계 중 하나로 활성 프로파일을 결정합니다.그런 다음 활성 프로파일을 사용하여 읽을 속성 파일과 인스턴스화할 콩을 결정합니다.애플리케이션이 기동하면, 변경할 수 없습니다.

Flyway는 application.properties(Spring-Boot V2.1)에 대한 직접 환경변수를 인식하지 않습니다.예:

spring.datasource.url=jdbc:mysql://${DB_HOSTNAME}:${DB_PORT}/${DB_DATABASE}
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASS}

이 문제를 해결하기 위해 이 환경변수를 실행했습니다.보통 .env 파일을 만듭니다.

SPRING_DATASOURCE_URL=jdbc:mysql://127.0.0.1:3306/place
SPRING_DATASOURCE_USERNAME=root
SPRING_DATASOURCE_PASSWORD=root

변수를 내 환경으로 내보냅니다.

export $(cat .env | xargs)

마지막으로 명령어를 실행하면

mvn spring-boot:run

또는 jar 파일을 실행합니다.

java -jar target/your-file.jar

또 다른 접근법이 있습니다.https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/maven-plugin/examples/run-env-variables.html

직접 코멘트를 할 만큼 평판이 높지 않기 때문에 많은 코멘트에 대한 대응입니다.

응용 프로그램콘텍스트가 아직 로드되지 않은 한 실행 시 프로파일을 지정할 수 있습니다.

// Previous answers incorrectly used "spring.active.profiles" instead of
// "spring.profiles.active" (as noted in the comments).
// Use AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME to avoid this mistake.

System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, environment);
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext.xml");

다음은 다양한 환경에 맞게 로드되는 환경 속성 파일의 체인을 통한 코드 조각입니다.

응용 프로그램 리소스 아래의 속성 파일( src/main/resources ):-

 1. application.properties
 2. application-dev.properties
 3. application-uat.properties
 4. application-prod.properties

application.properties에는 모든 환경에 액세스할 수 있는 모든 공통 속성이 포함되며 지정된 환경에서만 작동하는 환경 관련 속성이 포함됩니다.따라서 이러한 속성 파일을 로드하는 순서는 다음과 같습니다.

 application.properties -> application.{spring.profiles.active}.properties.

코드 스니펫은 다음과 같습니다:-

    import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;

    public class PropertiesUtils {

        public static final String SPRING_PROFILES_ACTIVE = "spring.profiles.active";

        public static void initProperties() {
            String activeProfile = System.getProperty(SPRING_PROFILES_ACTIVE);
            if (activeProfile == null) {
                activeProfile = "dev";
            }
            PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer
                    = new PropertySourcesPlaceholderConfigurer();
            Resource[] resources = new ClassPathResource[]
                    {new ClassPathResource("application.properties"),
                            new ClassPathResource("application-" + activeProfile + ".properties")};
            propertySourcesPlaceholderConfigurer.setLocations(resources);

        }
    }

나는 질문의 작성자와 같은 문제에 직면했다. 팀원 반드시 해야 에 답변이하지 않았습니다..gitignoredb 연결 문자열과 자격 증명이 다른 파일을 사용하므로 사람들이 실수로 공통 파일을 커밋하거나 다른 사람의 db 연결을 끊는 일이 없습니다.

게다가 이하의 순서에 따라서는, 다른 환경에 도입하는 것도 간단해, 한층 더 보너스로 버전 관리에 기밀 정보가 필요 없게 되었습니다.

PHP Symfony 3 프레임워크에서 아이디어를 얻으려면parameters.yml(.무시) 및 aparameters.yml.dist(이것은 첫 번째 것을 만드는 샘플입니다.composer install),

아래 답변에서 얻은 지식을 조합하여 https://stackoverflow.com/a/35534970/986160과 https://stackoverflow.com/a/35535138/986160을 실시했습니다.

기본적으로는 스프링 설정의 상속을 사용할 수 있으며, 다음과 같이 상위 설정 및 기타 기밀 credential을 사용하여 액티브프로파일을 선택할 수 있습니다.

application.yml.dist (sample)

    spring:
      profiles:
        active: local/dev/prod
      datasource:
        username:
        password:
        url: jdbc:mysql://localhost:3306/db?useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8

application.yml(.dev 서버의 경우)

spring:
  profiles:
    active: dev
  datasource:
    username: root
    password: verysecretpassword
    url: jdbc:mysql://localhost:3306/real_db?useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8

application.yml (.로컬머신의 경우)

spring:
  profiles:
    active: dev
  datasource:
    username: root
    password: rootroot
    url: jdbc:mysql://localhost:3306/xampp_db?useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8

application-dev.yml(중요하지 않은 환경 고유의 속성)

spring:
  datasource:
    testWhileIdle: true
    validationQuery: SELECT 1
  jpa:
    show-sql: true
    format-sql: true
    hibernate:
      ddl-auto: create-drop
      naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL57InnoDBDialect

.properties에서도 같은 작업을 수행할 수 있습니다.

너무 늦게 썼는지 속성 읽기 방법을 무시하려고 했을 때도 비슷한 문제가 발생했습니다.

문제는 1) env에서 속성을 읽는다 2) env에서 속성을 읽는다 3) 시스템 속성에서 속성을 읽는다 3) 마지막으로 시스템 속성에서 속성을 읽는다.

그래서 이 문제를 해결하기 위해 나는 나의 콩 구성 클래스로 간다.

@Validated
@Configuration
@ConfigurationProperties(prefix = ApplicationConfiguration.PREFIX)
@PropertySource(value = "${application.properties.path}", factory = PropertySourceFactoryCustom.class)
@Data // lombok
public class ApplicationConfiguration {

    static final String PREFIX = "application";

    @NotBlank
    private String keysPath;

    @NotBlank
    private String publicKeyName;

    @NotNull
    private Long tokenTimeout;

    private Boolean devMode;

    public void setKeysPath(String keysPath) {
        this.keysPath = StringUtils.cleanPath(keysPath);
    }
}

또한 @PropertySource 팩토리를 덮어씁니다.그리고 읽기 속성을 위한 저만의 구현을 만들었습니다.

    public class PropertySourceFactoryCustom implements PropertySourceFactory {

        @Override
        public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
            return name != null ? new PropertySourceCustom(name, resource) : new PropertySourceCustom(resource);
        }


    }

Property Source Custom을 작성했습니다.

public class PropertySourceCustom extends ResourcePropertySource {


    public LifeSourcePropertySource(String name, EncodedResource resource) throws IOException {
        super(name, resource);
    }

    public LifeSourcePropertySource(EncodedResource resource) throws IOException {
        super(resource);
    }

    public LifeSourcePropertySource(String name, Resource resource) throws IOException {
        super(name, resource);
    }

    public LifeSourcePropertySource(Resource resource) throws IOException {
        super(resource);
    }

    public LifeSourcePropertySource(String name, String location, ClassLoader classLoader) throws IOException {
        super(name, location, classLoader);
    }

    public LifeSourcePropertySource(String location, ClassLoader classLoader) throws IOException {
        super(location, classLoader);
    }

    public LifeSourcePropertySource(String name, String location) throws IOException {
        super(name, location);
    }

    public LifeSourcePropertySource(String location) throws IOException {
        super(location);
    }

    @Override
    public Object getProperty(String name) {

        if (StringUtils.isNotBlank(System.getenv(name)))
            return System.getenv(name);

        if (StringUtils.isNotBlank(System.getProperty(name)))
            return System.getProperty(name);

        return super.getProperty(name);
    }
}

그래서 이게 도움이 됐어요.

Spring 컨텍스트 5.0을 사용하여 다음 주석을 통해 시스템 환경에 따라 올바른 속성 파일을 로드하는 데 성공했습니다.

@PropertySources({
    @PropertySource("classpath:application.properties"),
    @PropertySource("classpath:application-${MYENV:test}.properties")})

여기서 MYENV 값은 시스템 환경에서 읽습니다.시스템 환경이 존재하지 않으면 기본 테스트 환경 속성 파일이 로드됩니다.MYENV 값을 잘못 지정하면 응용 프로그램 부팅에 실패합니다.

주의: 유지 보수하는 각 프로파일에 대해 어플리케이션[프로파일]을 작성해야 합니다.속성 파일 및 스프링 부트가 아닌 Spring 컨텍스트 5.0을 사용했지만, 이것은 Spring 4.1에서도 동작할 것이라고 생각합니다.

속성 파일이 환경변수로 외부화되면 다음 실행 Configuration을 IDE에 추가할 수 있습니다.

--spring.config.additional-location={PATH_OF_EXTERNAL_PROP}

언급URL : https://stackoverflow.com/questions/35531661/using-env-variable-in-spring-boots-application-properties

반응형