복붙노트

[SPRING] PropertyPlaceholderConfigurer와 함께 사용할 환경 별 특성을로드 하시겠습니까?

SPRING

PropertyPlaceholderConfigurer와 함께 사용할 환경 별 특성을로드 하시겠습니까?

이것은 꽤 일반적인 문제처럼 보입니다. 그러나 나는 최선의 방법에 대한 어떤 합의도 찾지 못했기 때문에 여기서 질문을 제기하고 있습니다.

Spring Batch와 Spring을 사용하는 커맨드 라인 자바 애플리케이션을 연구 중이다. PropertyPlaceholderConfigurer와 함께 속성 파일을 사용하고 있지만 여러 환경 (dev, test 등)에 대한 속성 파일을 처리하는 가장 좋은 방법에 대해서는 확신이 없습니다. My Googling은 프로그래밍 방식으로 (즉, Java 코드 자체에서) 속성을로드하는 방식을 선보일뿐입니다. 이는 내가하는 일에 적합하지 않습니다.

필자가 고려한 한 가지 접근법은 각 환경의 속성 파일을 서버에 배치하고 명령 줄 인수를 통해 파일 경로를 클래스 경로에 추가하는 것입니다. 그러나이 방법을 사용하여 파일을로드하는 데 문제가 있습니다.

필자가 고려중인 다른 방법은 jar에 모든 특성 파일을 포함시키고 런타임시 특성 파일의 이름을 채우기 위해 시스템 특성 또는 명령 행 인수를 사용하는 것입니다.

<bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:job.properties.${env}</value>
        </list>
    </property>
</bean>

나는 후자의 해결책에 의지하지만, 내가 바라 보는 더 좋은 방법이 있는지보기 위해 또한 찾고있다.

또한 빌드 대신 런타임에 대체해야한다고 언급해야합니다. 내가 사용할 제약이있는 프로세스는 환경을 통해 프로덕션으로 승격되는 단일 빌드가 필요하므로 대체 Maven 또는 Ant 대체를 사용할 수 없습니다.

해결법

  1. ==============================

    1.동의합니다. 정확한 컨텍스트에 똑같은 페이로드를 배포하려는 경우 빌드 시간 구성이되어서는 안됩니다.

    동의합니다. 정확한 컨텍스트에 똑같은 페이로드를 배포하려는 경우 빌드 시간 구성이되어서는 안됩니다.

    PropertyPlaceHolderConfigurer의 Locations 속성은 다양한 유형의 리소스를 사용할 수 있습니다. 파일 시스템 리소스 또는 URL 일 수 있습니까? 따라서 config 파일의 위치를 ​​로컬 서버의 파일로 설정할 수 있으며 실행될 때마다 해당 서버의 config 파일에 지정된 모드로 실행됩니다. 특정 모드를 실행하는 특정 서버가 있으면 정상적으로 작동합니다.

    동일한 서버에서 서로 다른 모드로 동일한 응용 프로그램을 실행하려는 경우에도이 줄을 읽는 것입니다. 이 경우 내가 제안하는 것은 명령 행 매개 변수를 통해 config 파일의 위치를 ​​전달하는 것입니다. 이 값을 PropertyPlaceHolderConfigurer에 전달하는 것은 약간 까다 롭지 만 불가능하지는 않습니다.

  2. ==============================

    2.본질적으로 완료된 JAR 파일을 다른 환경에 놓기를 원할 경우, 런타임에 적절한 특성을 선택하면 어떤 수정도 필요 없습니다. 이것이 맞다면 다음 접근법이 유효합니다 :

    본질적으로 완료된 JAR 파일을 다른 환경에 놓기를 원할 경우, 런타임에 적절한 특성을 선택하면 어떤 수정도 필요 없습니다. 이것이 맞다면 다음 접근법이 유효합니다 :

    1) 사용자 홈 디렉토리에 특성 파일이 있는지 확인하십시오.

    다음과 같이 JAR 외부의 특성 파일을 참조하도록 PropertyPlaceholderConfigurer를 구성하십시오.

    <bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreUnresolvablePlaceholders" value="false"/>
        <property name="order" value="1"/>
        <property name="locations">
          <list>
            <!-- User home holds secured information -->
            <value>file:${user.home}/MyApp/application.properties</value>
          </list>
        </property>
      </bean>
    

    운영 체제는 적절한 사용자 만 액세스 할 수 있도록 application.properties 파일의 내용을 보호합니다. 이 파일은 응용 프로그램을 처음 실행할 때 존재하지 않으므로 시작할 때 중요한 값 (예 : 사용자 이름, 암호, 최대 절전 모드 등)을 묻는 간단한 스크립트를 만듭니다. 명령 줄 인터페이스에 대한 광범위한 도움말과 유용한 기본 값을 제공하십시오.

    2) 응용 프로그램이 데이터베이스를 볼 수 있도록 제어 된 환경에있는 경우 문제는 위의 기술 1)을 사용하여 기본 자격 증명을 만드는 중 하나로 줄일 수 있습니다. 컨텍스트를 시작하는 동안 데이터베이스에 연결 한 다음 읽은 값을 사용하여 대체를 수행합니다 JDBC를 통해. 응용 프로그램 시작에 대한 2 단계 접근이 필요합니다. 1 단계는 JdbcTemplate 및 관련 DataSource를 채우는 application.properties 파일과 함께 상위 컨텍스트를 호출합니다. 단계 2는 JdbcTemplate이 JdbcPropertyPlaceholderConfigurer에서 구성된대로 사용될 수 있도록 부모를 참조하는 기본 컨텍스트를 호출합니다.

    이런 종류의 코드의 예는 다음과 같습니다.

    public class JdbcPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
    
      private Logger log = Logger.getLogger(JdbcPropertyPlaceholderConfigurer.class);
      private JdbcTemplate jdbcTemplate;
      private String nameColumn;
      private String valueColumn;
      private String propertiesTable;
    
      /**
       * Provide a different prefix
       */
      public JdbcPropertyPlaceholderConfigurer() {
        super();
        setPlaceholderPrefix("#{");
      }
    
      @Override
      protected void loadProperties(final Properties props) throws IOException {
        if (null == props) {
          throw new IOException("No properties passed by Spring framework - cannot proceed");
        }
        String sql = String.format("select %s, %s from %s", nameColumn, valueColumn, propertiesTable);
        log.info("Reading configuration properties from database");
        try {
          jdbcTemplate.query(sql, new RowCallbackHandler() {
    
            public void processRow(ResultSet rs) throws SQLException {
              String name = rs.getString(nameColumn);
              String value = rs.getString(valueColumn);
              if (null == name || null == value) {
                throw new SQLException("Configuration database contains empty data. Name='" + name + "' Value='" + value + "'");
              }
              props.setProperty(name, value);
            }
    
          });
        } catch (Exception e) {
          log.fatal("There is an error in either 'application.properties' or the configuration database.");
          throw new IOException(e);
        }
        if (props.size() == 0) {
          log.fatal("The configuration database could not be reached or does not contain any properties in '" + propertiesTable + "'");
        }
      }
    
      public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
      }
    
      public void setNameColumn(String nameColumn) {
        this.nameColumn = nameColumn;
      }
    
      public void setValueColumn(String valueColumn) {
        this.valueColumn = valueColumn;
      }
    
      public void setPropertiesTable(String propertiesTable) {
        this.propertiesTable = propertiesTable;
      }
    
    }
    

    위의 코드는 Spring에서 이와 같이 설정 될 것입니다 (order 속성은 $ 접두사가 붙은 자리 표시 자 뒤에옵니다).

      <!-- Enable configuration through the JDBC configuration with fall-through to framework.properties -->
      <bean id="jdbcProperties" class="org.example.JdbcPropertyPlaceholderConfigurer">
        <property name="ignoreUnresolvablePlaceholders" value="false"/>
        <property name="order" value="2"/>
        <property name="nameColumn" value="name"/>
        <property name="valueColumn" value="value"/>
        <property name="propertiesTable" value="my_properties_table"/>
        <property name="jdbcTemplate" ref="configurationJdbcTemplate"/> <!-- Supplied in a parent context -->
      </bean>
    

    이렇게하면 Spring 설정에서 follow가 발생할 수있다.

    <!-- Read from application.properties -->
    <property name="username">${username}</property>  
    ...
    <!-- Read in from JDBC as part of second pass after all $'s have been fulfilled -->
    <property name="central-thing">#{name.key.in.db}</property> 
    

    3) 물론 웹 애플리케이션 컨테이너에 있다면 JNDI 만 사용하십시오. 그러나 당신은 그렇게 할 수 없습니다.

    희망이 도움이!

  3. ==============================

    3.를 사용할 수 있습니다. 당신의 Spring XML에서 $ {target_env}를 명령 행 인자 (-Dtarget_env = test.)를 사용하여 설정하십시오.

    를 사용할 수 있습니다. 당신의 Spring XML에서 $ {target_env}를 명령 행 인자 (-Dtarget_env = test.)를 사용하여 설정하십시오.

    Spring 3.1부터는 를 사용하여 기본값을 지정할 수 있으므로 명령 행에서 값을 설정할 필요가 없습니다 .

    Maven 옵션 인 경우 플러그인 실행 중에 Spring 변수를 설정할 수 있습니다. 테스트 또는 통합 테스트 실행 중.

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.12</version>
        <configuration>
            <systemPropertyVariables>
                <target_env>test.</target_env>
            </systemPropertyVariables>
        </configuration>
    </plugin>
    

    다른 Maven 프로파일도 사용할 수 있다고 가정합니다.

  4. ==============================

    4.Spring 속성 자리 표시 자 구성자 - 몇 가지 확실하지 않은 옵션

    Spring 속성 자리 표시 자 구성자 - 몇 가지 확실하지 않은 옵션

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:db.properties"></property>
    </bean>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="${db.url.${mode}}" />
        <property name="username" value="${db.username.${mode}}" />
        <property name="password" value="${db.password.${mode}}" />
    </bean>
    

    $ {db.username. $ {mode}} : "모드"는 프로젝트 모드 (환경)를 정의합니다. - dev / prod 속성 파일은 다음과 같습니다.

    #Database properties
    #mode dev/prod
    mode=dev
    
    #dev db properties
    db.url.dev=jdbc:mysql://localhost:3306/dbname
    db.username.dev=root
    db.password.dev=root
    
    #prod db properties
    db.url.prod=jdbc:mysql://localhost:3306/dbname
    db.username.prod=root
    db.password.prod=root
    
  5. ==============================

    5.필자가 과거에 일반적으로해온 방법은 패키지 / 배포시에 환경 (dev / test / prod)을 대체하는 것입니다.

    필자가 과거에 일반적으로해온 방법은 패키지 / 배포시에 환경 (dev / test / prod)을 대체하는 것입니다.

    올바른 구성 파일을 서버의 올바른 위치에 복사하거나 배포 패키지에 올바른 구성 파일을 번들링 할 수 있습니다. Ant / Maven을 사용한다면 이것은 매우 간단해야합니다. 어떤 빌드 도구를 사용하고 있습니까? Ant / Maven. 값을 대체 할 수있는 능력을 제공해야합니다.

    PropertyPlaceholderConfigurer를 사용하는 또 다른 방법은 SYSTEM_PROPERTIES_MODE_OVERRIDE 속성을 사용하는 것입니다. 이 속성을 사용하여 시스템 속성을 통해로드 할 속성 파일의 위치를 ​​설정할 수 있습니다.

    http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.html#SYSTEM_PROPERTIES_MODE_OVERRIDE

    희망이 도움이됩니다.

  6. ==============================

    6.이 블로그 게시물에는 속성 파일을 전환하기위한 좋은 아이디어가 있습니다. 더블 PropertyPlaceholderConfigurer를 사용하여 시스템 속성을 사용하여 구성 파일을 지정했습니다.

    이 블로그 게시물에는 속성 파일을 전환하기위한 좋은 아이디어가 있습니다. 더블 PropertyPlaceholderConfigurer를 사용하여 시스템 속성을 사용하여 구성 파일을 지정했습니다.

  7. ==============================

    7.빌드 시간을 대체하기 위해 Maven을 사용하여 변수를 대체 할 속성을 만듭니다. Maven settings.xml 파일에서로드 할 속성을 결정할 수 있으며 파일은 환경에 한정 될 수 있습니다. PPC를 사용하는 프로덕션 속성의 경우이 블로그를 참조하십시오.

    빌드 시간을 대체하기 위해 Maven을 사용하여 변수를 대체 할 속성을 만듭니다. Maven settings.xml 파일에서로드 할 속성을 결정할 수 있으며 파일은 환경에 한정 될 수 있습니다. PPC를 사용하는 프로덕션 속성의 경우이 블로그를 참조하십시오.

  8. ==============================

    8.안녕하세요, Spring in Action을 읽고 Spring에서 제공하는 솔루션을 찾았습니다. 프로필 또는 조건부 : 여러 프로필을 만들 수 있습니다. 테스트, dev에, prod 등

    안녕하세요, Spring in Action을 읽고 Spring에서 제공하는 솔루션을 찾았습니다. 프로필 또는 조건부 : 여러 프로필을 만들 수 있습니다. 테스트, dev에, prod 등

    Spring은 어떤 프로파일이 활성화되어 있는지를 결정할 때 두 개의 분리 된 속성을 사용합니다 : spring.profiles.active 및 spring.profiles.default. spring.profiles.active 인 경우 이 설정되면, 그 값에 따라 활성 프로파일이 결정됩니다. 그러나 봄이라면 .profiles.active가 설정되어 있지 않으면 Spring은 spring.profiles.default를 찾습니다. 두 경우 모두 spring.profiles.active 또는 spring.profiles.default가 설정되면 아무 것도 없습니다. 활성 프로파일 및 프로파일에있는 것으로 정의되지 않은 Bean 만 작성됩니다.

    이러한 속성을 설정하는 방법에는 여러 가지가 있습니다. 1 DispatcherServlet의 초기화 매개 변수로 사용 2 웹 응용 프로그램의 컨텍스트 매개 변수로 3 JNDI 항목으로 4 환경 변수로 5 JVM 시스템 특성으로 6 통합 테스트 클래스에서 @ActiveProfiles 주석 사용

  9. ==============================

    9.classpath 옵션을 사용하고 Jetty에서 환경별로 classpath를 조정한다. jetty-maven-plugin에서 testclasses를위한 디렉토리를 설정하고 testresources를 찾을 수 있습니다.

    classpath 옵션을 사용하고 Jetty에서 환경별로 classpath를 조정한다. jetty-maven-plugin에서 testclasses를위한 디렉토리를 설정하고 testresources를 찾을 수 있습니다.

    비 로컬 환경 (테스트 / 프로덕션)의 경우, 환경 플래그를 사용하여 적절한 파일을 $ JETTY_HOME / resources 폴더 (Jetty의 클래스 경로에 빌드 됨)

  10. from https://stackoverflow.com/questions/2204917/load-environment-specific-properties-for-use-with-propertyplaceholderconfigurer by cc-by-sa and MIT license