yml example configurationproperties application java spring config spring-boot

java - example - Spring Boot y múltiples archivos de configuración externa



application yml spring boot (8)

Acabo de tener un problema similar y finalmente descubrí la causa: el archivo application.properties tenía los atributos de propiedad y rwx incorrectos. Entonces, cuando tomcat comenzó, el archivo application.properties estaba en la ubicación correcta, pero era propiedad de otro usuario:

$ chmod 766 application.properties $ chown tomcat application.properties

Tengo varios archivos de propiedades que quiero cargar desde classpath. Hay un conjunto predeterminado en /src/main/resources que es parte de myapp.jar . Mi springcontext espera que los archivos estén en classpath. es decir

<util:properties id="Job1Props" location="classpath:job1.properties"></util:properties> <util:properties id="Job2Props" location="classpath:job2.properties"></util:properties>

También necesito la opción de anular estas propiedades con un conjunto externo. Tengo una carpeta de configuración externa en cwd . Según la carpeta de configuración de doc de inicio de primavera debe estar en classpath. Pero no está claro desde el documento si solo anula las applicaiton.properties de applicaiton.properties desde allí o todas las propiedades en config.

Cuando lo probé, solo application.properties se recogió y el resto de las propiedades todavía se recogen desde /src/main/resources . He intentado suministrarlos como una lista separada por comas a spring.config.location pero el conjunto predeterminado aún no se ha anulado.

¿Cómo puedo hacer que múltiples archivos de configuración externa anulen los predeterminados?

Como solución alternativa, actualmente uso app.config.location (propiedad específica de la aplicación) que proporciono a través de la línea de comandos. es decir

java -jar myapp.jar app.config.location=file:./config

y cambié mi applicationcontext para

<util:properties id="Job2Props" location="{app.config.location}/job2.properties"></util:properties>

Y así es como hago la separación entre file y classpath al cargar la aplicación.
EDICIONES:

//psuedo code if (StringUtils.isBlank(app.config.location)) { System.setProperty(APP_CONFIG_LOCATION, "classpath:"); }

Realmente me gustaría no utilizar la solución anterior y tener el resorte anular todos los archivos de configuración externos en el classpath como lo hace para el archivo application.properties .


Con Spring boot, spring.config.location funciona, solo proporcione archivos de propiedades separados por comas.

mira el código a continuación

@PropertySource(ignoreResourceNotFound=true,value="classpath:jdbc-${spring.profiles.active}.properties") public class DBConfig{ @Value("${jdbc.host}") private String jdbcHostName; } }

uno puede poner la versión predeterminada de jdbc.properties dentro de la aplicación. Las versiones externas se pueden establecer mentira esto.

java -jar target/myapp.jar --spring.config.location=classpath:file:///C:/Apps/springtest/jdbc.properties,classpath:file:///C:/Apps/springtest/jdbc-dev.properties

En función del valor del perfil establecido mediante la propiedad spring.profiles.active, se recuperará el valor de jdbc.host. Entonces cuando (en windows)

set spring.profiles.active=dev

jdbc.host tomará valor de jdbc-dev.properties.

para

set spring.profiles.active=default

jdbc.host tomará valor de jdbc.properties.


Cuando se utiliza Spring Boot, las propiedades se cargan en el siguiente orden (consulte Configuración externa en la guía de referencia Spring Boot).

  1. Argumentos de línea de comando.
  2. Propiedades del sistema Java (System.getProperties ()).
  3. Variables de entorno del sistema operativo.
  4. Atributos JNDI de java: comp / env
  5. Un RandomValuePropertySource que solo tiene propiedades al azar. *.
  6. Propiedades de aplicación fuera de su jar empaquetado (application.properties incluyendo YAML y variantes de perfil).
  7. Propiedades de aplicación empaquetadas dentro de su jar (application.properties incluyendo YAML y variantes de perfil).
  8. Anotaciones @PropertySource en tus clases @Configuration.
  9. Propiedades predeterminadas (especificadas utilizando SpringApplication.setDefaultProperties).

Al resolver propiedades (es decir, @Value("${myprop}") resolución se realiza en el orden inverso (empezando por 9).

Para agregar diferentes archivos, puede usar las propiedades spring.config.location , que toma una lista separada por comas de archivos de propiedades o ubicaciones de archivos (directorios).

-Dspring.config.location=your/config/dir/

El de arriba agregará un directorio que será consultado para application.properties archivos application.properties .

-Dspring.config.location=classpath:job1.properties,classpath:job2.properties

Esto agregará el archivo de 2 propiedades a los archivos que están cargados.

Los archivos y las ubicaciones de configuración predeterminadas se cargan antes que los de la spring.config.location adicionales, lo que significa que este último siempre anulará las propiedades establecidas en las anteriores. (Consulte también here de la Guía de referencia de arranque de primavera).

Si spring.config.location contiene directorios (a diferencia de los archivos) deben terminar en / (y se agregarán con los nombres generados desde spring.config.name antes de cargarse). La vía de classpath:,classpath:/config,file:,file:config/ búsqueda por defecto classpath:,classpath:/config,file:,file:config/ siempre se utiliza, independientemente del valor de spring.config.location . De esa manera, puede configurar valores predeterminados para su aplicación en application.properties (o cualquier otro nombre de base que elija con spring.config.name ) y anularlo en tiempo de ejecución con un archivo diferente, manteniendo los valores predeterminados.


Eche un vistazo al PropertyPlaceholderConfigurer, me parece más claro de usar que la anotación.

p.ej

@Configuration public class PropertiesConfiguration { @Bean public PropertyPlaceholderConfigurer properties() { final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); // ppc.setIgnoreUnresolvablePlaceholders(true); ppc.setIgnoreResourceNotFound(true); final List<Resource> resourceLst = new ArrayList<Resource>(); resourceLst.add(new ClassPathResource("myapp_base.properties")); resourceLst.add(new FileSystemResource("/etc/myapp/overriding.propertie")); resourceLst.add(new ClassPathResource("myapp_test.properties")); resourceLst.add(new ClassPathResource("myapp_developer_overrides.properties")); // for Developer debugging. ppc.setLocations(resourceLst.toArray(new Resource[]{})); return ppc; }


He encontrado que este es un patrón útil a seguir:

@RunWith(SpringRunner) @SpringBootTest(classes = [ TestConfiguration, MyApplication ], properties = [ "spring.config.name=application-MyTest_LowerImportance,application-MyTest_MostImportant" ,"debug=true", "trace=true" ] )

Aquí anulamos el uso de "application.yml" para usar "application-MyTest_LowerImportance.yml" y también "application-MyTest_MostImportant.yml"
(Spring también buscará archivos .properties)

También se incluyen como bonificación extra las configuraciones de depuración y rastreo, en una línea separada para que pueda comentarlas si es necesario;]

La depuración / rastreo es increíblemente útil ya que Spring vaciará los nombres de todos los archivos que carga y los que intenta cargar.
Verá líneas como esta en la consola en tiempo de ejecución:

TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./config/application-MyTest_MostImportant.properties'' (file:./config/application-MyTest_MostImportant.properties) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./config/application-MyTest_MostImportant.xml'' (file:./config/application-MyTest_MostImportant.xml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./config/application-MyTest_MostImportant.yml'' (file:./config/application-MyTest_MostImportant.yml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./config/application-MyTest_MostImportant.yaml'' (file:./config/application-MyTest_MostImportant.yaml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./config/application-MyTest_LowerImportance.properties'' (file:./config/application-MyTest_LowerImportance.properties) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./config/application-MyTest_LowerImportance.xml'' (file:./config/application-MyTest_LowerImportance.xml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./config/application-MyTest_LowerImportance.yml'' (file:./config/application-MyTest_LowerImportance.yml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./config/application-MyTest_LowerImportance.yaml'' (file:./config/application-MyTest_LowerImportance.yaml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./application-MyTest_MostImportant.properties'' (file:./application-MyTest_MostImportant.properties) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./application-MyTest_MostImportant.xml'' (file:./application-MyTest_MostImportant.xml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./application-MyTest_MostImportant.yml'' (file:./application-MyTest_MostImportant.yml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./application-MyTest_MostImportant.yaml'' (file:./application-MyTest_MostImportant.yaml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./application-MyTest_LowerImportance.properties'' (file:./application-MyTest_LowerImportance.properties) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./application-MyTest_LowerImportance.xml'' (file:./application-MyTest_LowerImportance.xml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./application-MyTest_LowerImportance.yml'' (file:./application-MyTest_LowerImportance.yml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./application-MyTest_LowerImportance.yaml'' (file:./application-MyTest_LowerImportance.yaml) resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/config/application-MyTest_MostImportant.properties'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/config/application-MyTest_MostImportant.xml'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/config/application-MyTest_MostImportant.yml'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/config/application-MyTest_MostImportant.yaml'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/config/application-MyTest_LowerImportance.properties'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/config/application-MyTest_LowerImportance.xml'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/config/application-MyTest_LowerImportance.yml'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/config/application-MyTest_LowerImportance.yaml'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/application-MyTest_MostImportant.properties'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/application-MyTest_MostImportant.xml'' resource not found DEBUG 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Loaded config file ''file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_MostImportant.yml'' (classpath:/application-MyTest_MostImportant.yml) TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/application-MyTest_MostImportant.yaml'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/application-MyTest_LowerImportance.properties'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/application-MyTest_LowerImportance.xml'' resource not found DEBUG 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Loaded config file ''file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_LowerImportance.yml'' (classpath:/application-MyTest_LowerImportance.yml) TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''classpath:/application-MyTest_LowerImportance.yaml'' resource not found TRACE 93941 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Skipped config file ''file:./config/application-MyTest_MostImportant-test.properties'' (file:./config/application-MyTest_MostImportant-test.properties) resource not found


Spring Boots nos permite escribir diferentes perfiles para escribir en diferentes entornos, por ejemplo, podemos tener archivos de propiedades separados para producción, qa y entornos locales

El archivo application-local.properties con configuraciones según mi máquina local es

spring.profiles.active=local spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 spring.data.mongodb.database=users spring.data.mongodb.username=humble_freak spring.data.mongodb.password=freakone spring.rabbitmq.host=localhost spring.rabbitmq.username=guest spring.rabbitmq.password=guest spring.rabbitmq.port=5672 rabbitmq.publish=true

Del mismo modo, podemos escribir application-prod.properties y application-qa.properties tantos archivos de propiedades como queramos

luego escriba algunos scripts para iniciar la aplicación para diferentes entornos, por ejemplo

mvn spring-boot:run -Drun.profiles=local mvn spring-boot:run -Drun.profiles=qa mvn spring-boot:run -Drun.profiles=prod


Yo tuve el mismo problema. Quería tener la capacidad de sobrescribir un archivo de configuración interno al inicio con un archivo externo, similar a la aplicación Spring Boot. Detección de propiedades. En mi caso, es un archivo user.properties donde se almacenan los usuarios de mis aplicaciones.

Mis requisitos:

Cargue el archivo desde las siguientes ubicaciones (en este orden)

  1. El camino de clases
  2. Subdirectorio A / config del directorio actual.
  3. El directorio actual
  4. Desde el directorio o una ubicación de archivo dada por un parámetro de línea de comando al inicio

Se me ocurrió la siguiente solución:

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.PathResource; import org.springframework.core.io.Resource; import java.io.IOException; import java.util.Properties; import static java.util.Arrays.stream; @Configuration public class PropertiesConfig { private static final Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class); private final static String PROPERTIES_FILENAME = "user.properties"; @Value("${properties.location:}") private String propertiesLocation; @Bean Properties userProperties() throws IOException { final Resource[] possiblePropertiesResources = { new ClassPathResource(PROPERTIES_FILENAME), new PathResource("config/" + PROPERTIES_FILENAME), new PathResource(PROPERTIES_FILENAME), new PathResource(getCustomPath()) }; // Find the last existing properties location to emulate spring boot application.properties discovery final Resource propertiesResource = stream(possiblePropertiesResources) .filter(Resource::exists) .reduce((previous, current) -> current) .get(); final Properties userProperties = new Properties(); userProperties.load(propertiesResource.getInputStream()); LOG.info("Using {} as user resource", propertiesResource); return userProperties; } private String getCustomPath() { return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + PROPERTIES_FILENAME; } }

Ahora la aplicación usa el recurso de ruta de clase, pero también busca un recurso en las otras ubicaciones especificadas. El último recurso que existe será recogido y utilizado. Puedo iniciar mi aplicación con java -jar myapp.jar --properties.location = / directory / myproperties.properties para usar una ubicación de propiedades que flote mi bote.

Aquí hay un detalle importante: use un String vacío como valor predeterminado para la propiedad properties.location en la anotación @Value para evitar errores cuando la propiedad no está configurada.

La convención para una ubicación de propiedades es: Usar un directorio o una ruta a un archivo de propiedades como properties.location.

Si desea sobrescribir solo propiedades específicas, se puede usar un Fail de Propiedades con setIgnoreResourceNotFound (verdadero) con el conjunto de recursos establecido como ubicaciones.

Estoy seguro de que esta solución se puede extender para manejar archivos múltiples ...

EDITAR

Aquí mi solución para múltiples archivos :) Como antes, esto se puede combinar con un PropertiesFactoryBean.

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.PathResource; import org.springframework.core.io.Resource; import java.io.IOException; import java.util.Map; import java.util.Properties; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toMap; @Configuration class PropertiesConfig { private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class); private final static String[] PROPERTIES_FILENAMES = {"job1.properties", "job2.properties", "job3.properties"}; @Value("${properties.location:}") private String propertiesLocation; @Bean Map<String, Properties> myProperties() { return stream(PROPERTIES_FILENAMES) .collect(toMap(filename -> filename, this::loadProperties)); } private Properties loadProperties(final String filename) { final Resource[] possiblePropertiesResources = { new ClassPathResource(filename), new PathResource("config/" + filename), new PathResource(filename), new PathResource(getCustomPath(filename)) }; final Resource resource = stream(possiblePropertiesResources) .filter(Resource::exists) .reduce((previous, current) -> current) .get(); final Properties properties = new Properties(); try { properties.load(resource.getInputStream()); } catch(final IOException exception) { throw new RuntimeException(exception); } LOG.info("Using {} as user resource", resource); return properties; } private String getCustomPath(final String filename) { return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + filename; } }


este es un enfoque simple usando arranque de primavera

TestClass.java

@Configuration @Profile("one") @PropertySource("file:/{selected location}/app.properties") public class TestClass { @Autowired Environment env; @Bean public boolean test() { System.out.println(env.getProperty("test.one")); return true; } }

el contexto de app.properties , en la ubicación seleccionada

test.one = 1234

su aplicación de arranque de primavera

@SpringBootApplication public class TestApplication { public static void main(String[] args) { SpringApplication.run(testApplication.class, args); } }

y el contexto predefinido de application.properties

spring.profiles.active = one

puede escribir tantas clases de configuración como desee y habilitarlas / deshabilitarlas simplemente configurando spring.profiles.active = el nombre / nombres del perfil {separados por comas}

como puede ver, la bota de primavera es genial, solo necesita familiarizarse con ella, vale la pena mencionar que también puede usar @Value en sus campos

@Value("${test.one}") String str;