Introducción
Contenido
En este artículo, nos sumergiremos en la configuración de propiedades de Spring Boot.
Spring permite a los desarrolladores configurar una gran cantidad de propiedades para sus proyectos. Spring Boot, además de permitir a los desarrolladores comenzar con un proyecto desde cero con mucha más facilidad y facilidad de uso que Spring, también hace que sea mucho más fácil configurar propiedades para sus aplicaciones.
Hay varias formas de configurar un proyecto Spring:
- Basado en Java
- Basado en XML
- Basado en propiedades
La configuración de propiedades basada en Java y XML era una forma clásica de configurar aplicaciones Spring antes de que Spring Boot nos presentara un application.properties
archivo.
Esta adición nos permite configurar externamente la aplicación y acceder fácilmente a las propiedades definidas en el archivo.
Por defecto, el application.properties
El archivo se puede utilizar para almacenar pares de propiedades, aunque también puede definir cualquier número de archivos de propiedades adicionales.
Para registrar un archivo de propiedad, puede anotar un @Configuration
clase con el adicional @PropertySource
anotación:
@Configuration
@PropertySource("classpath:custom.properties")
public class ConfigClass {
// Configuration
}
Con este método, puede registrar cualquier cantidad de .properties
archivos:
@Configuration
@PropertySource("classpath:custom.properties")
@PropertySource("classpath:another.properties")
public class ConfigClass {
// Configuration
}
Inyección de propiedades de Spring Boot
Configuración de la aplicación
La forma más fácil de comenzar con un proyecto esqueleto es usar Spring Initializr. Seleccione su versión preferida de Spring Boot, agregue el Web
dependencia y generarlo como un proyecto Maven:
Si abre el proyecto, notará que un archivo application.properties
se mantiene en el src/main/resources
camino.
Este es el archivo predeterminado en el que se basa Spring para cargar las propiedades. Podemos escribir nuestras propiedades personalizadas o específicas de Spring como pares clave-valor aquí:
message.default.welcome=Welcome...
message.default.goodbye=Goodbye...
En vez de properties
archivo, también podemos utilizar un .yml
archivo y defina las mismas propiedades que:
message:
default:
welcome: Welcome...
goodbye: Goodbye...
Esto funciona debido a la Serpiente Yaml jar presente en el classpath. Los archivos YAML son más concisos y admiten mapas, listas, etc.
Depende de usted y su equipo qué tipo usar. Estaremos usando el .properties
escriba en este tutorial.
Inyectar propiedades usando @Value
Veamos cómo podemos usar estas propiedades en una API REST simple:
@RestController
public class GreetController {
@Value("${message.default.welcome}")
private String welcomeMessage;
@Value("${message.default.goodbye}")
private String goodBye;
@RequestMapping("/welcome")
public String welcome() {
return welcomeMessage;
}
@RequestMapping("/bye")
public String bye() {
return goodBye;
}
}
Esto es bastante sencillo. Utilizando el @Value
anotación, podemos inyectar los valores de la application.properties
archivo en campos de clase en el bean administrado por Spring GreetController
.
Luego tenemos un par de puntos finales REST que simplemente devuelven estos valores:
Utilizando @Value
le permite establecer un valor predeterminado si el solicitado, por cualquier motivo, no está disponible:
@Value("${message.default.welcome:SomeDefaultValue}")
private String welcomeMessage;
Si el message.default.welcome
el valor no está presente, el valor se establecerá como SomeDefaultValue
.
Si desea leer más sobre el @Value
anotación, ¡tenemos un artículo detallado sobre eso!
Inyectar propiedades usando @ConfigurationProperties
Si nuestras propiedades tienen algún contexto común como el mismo prefijo, podemos usar el @ConfigurationProperties
anotación que asignará estas propiedades a los objetos Java:
@Configuration
@ConfigurationProperties(prefix = "message.default")
public class MessageProperties {
private String welcome;
private String goodbye;
// Getters and Setters
}
@Configuration
le dirá a Spring que cree un bean de esta clase.@ConfigurationProperties
inicializará los campos con los nombres de propiedad correspondientes.
Ahora podemos usar este bean en otros beans gestionados por Spring:
@Autowired
MessageProperties messageProperties;
Propiedades primordiales
Naturalmente, a medida que nuestro entorno de aplicaciones se expande y cambia (desarrollo, control de calidad, producción, etc.), algunas de nuestras propiedades también cambiarán. Estos pueden interferir entre sí si no los segregamos de alguna manera.
Logramos esto manteniendo diferentes archivos u obteniendo los valores de las propiedades a través de variables de entorno.
Usar perfiles de Spring
La forma más común de escribir propiedades «cambiantes» es almacenarlas en diferentes archivos. Estos archivos son específicos del entorno y nuestra aplicación puede cargarlos en función de las variables del entorno.
Spring Boot proporciona una forma muy elegante de manejar esto.
Todo lo que tenemos que hacer es seguir una convención de nomenclatura: application-<environment>.properties
para nuestros archivos de propiedad:
- application-dev.properties
- application-qa.properties
- application-production.propertiesetc.
Para notificar a Spring qué archivos usar, tenemos que establecer una variable de entorno: spring.profiles.active
.
Dicho esto, si el valor de spring.profiles.active
es dev
, por ejemplo, Spring boot cargará el application-dev.properties
archivo e igualmente.
Nota: application.properties
siempre está cargado, independientemente de la spring.profiles.active
valor. Si hay el mismo valor-clave presente tanto en application.properties
y application-<environment>.properties
, este último anulará al primero.
Normalmente escribimos todas las propiedades comunes de cada entorno en application.properties
y anular las propiedades específicas del entorno utilizando el perfil específico application-<environment>.properties
.
Veamos esto creando un application-dev.properties
:
message.default.welcome = Welcome to DEV environment...
Hay algunas formas de configurar spring.profiles.active
variable.
Si estamos ejecutando la aplicación a través de Eclipse, podemos configurar esto en argumentos de VM:
Podemos configurarlo en las variables de entorno del sistema operativo, como en Windows:
Comencemos nuestra aplicación y en los registros, puede ver el dev
perfil que se está cargando:
Revisemos nuestros dos puntos finales REST anteriores:
Como podemos ver, message.default.welcome
el valor vino de application-dev.properties
archivo y message.default.goodbye
la propiedad vino de application.properties
.
Podemos tener varios valores en spring.profiles.active
me gusta dev,qa
:
Cualquier clave duplicada sería anulada por el último perfil, en el caso anterior siendo qa
.
También podemos pasar en el spring.profiles.active
como un argumento de línea de comandos como:
java -jar -Dspring.profiles.active=dev greeting-service-0.0.1-SNAPSHOT.jar
Crear application.properties desde la ubicación de la compilación
También podemos anular las propiedades internas creando un application.properties
archivo en el mismo nivel desde donde .jar
es ejecutado. El contexto de Spring anulará las propiedades usando este archivo recién creado.
Esta es una excelente manera de distribuir su aplicación a otros, quienes pueden anular ciertas propiedades en función de su entorno, como configuraciones de bases de datos, por ejemplo.
También hay otras formas de externalizar sus propiedades, como las variables de entorno del sistema operativo, los argumentos de la línea de comandos, etc. El orden en el que Spring lo considera se puede encontrar aquí.
Externalización de propiedades mediante el servidor de configuración en la nube
Muchas de las aplicaciones creadas hoy en día se basan en la arquitectura de microservicios. Estas aplicaciones no solo se implementan por separado, sino que podrían tener varias instancias de sí mismas (según la carga) y el recuento total podría superar fácilmente los 100.
Gestionar propiedades en este estilo arquitectónico particular a través de métodos convencionales requiere demasiado esfuerzo. Además, para cambiar una propiedad, tenemos que volver a construir la aplicación e implementarla o, en el mejor de los casos, reiniciar la aplicación. Esto requiere tiempo de inactividad, lo que frustra todo el propósito de los microservicios.
Otro problema con el enfoque tradicional, especialmente si las propiedades se externalizaron a través de variables de archivo o entorno, es que no hay trazabilidad. Siempre se toman las últimas y no sabemos cuáles eran las propiedades antes ni quién las cambió.
Configuración de Spring Cloud proporciona una forma centralizada, externalizada, segura y fácil de almacenar y servir configuraciones para aplicaciones para diferentes entornos:
En resumen, tenemos un servidor de configuración ejecutándose como una aplicación separada que se conecta a un repositorio de Git.
Cuando iniciamos una nueva aplicación (Config Client), obtiene todas las propiedades necesarias del Config Server. No importa si la aplicación existía cuando configuramos el servidor o no.
Crear un servidor de configuración
Como siempre, comenzamos usando Spring Initializr.
Seleccione su versión preferida de Spring Boot, agregue la dependencia del servidor de configuración y generela como un proyecto de Maven:
Anotando nuestra clase principal con @EnableConfigServer
, lo marcamos como un servidor de configuración:
@SpringBootApplication
@EnableConfigServer
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Y ahora, tenemos que configurar algunas cosas en el application.properties
archivo:
server.port = 8888
spring.cloud.config.server.git.uri = https://github.com/dhananjay12/spring-cloud-config
spring.cloud.config.server.git.searchPaths = app-properties
Aquí, definimos el puerto en el que se ejecutará el servidor de configuración. Luego especificamos la URL de Git que necesita conectar para las propiedades.
Nota: De forma predeterminada, Spring busca los archivos de propiedades en la raíz. Si tenemos que especificar una carpeta en particular, podemos proporcionar la ubicación a través de searchPaths
.
Así es como se ve el repositorio de Git:
Podemos iniciar el servidor de configuración ahora. Si desea verificar la configuración del Spring Config Server, siguiendo la convención: http://localhost:8888/<application-name>/<spring-profiles>
nos mostrará toda la información necesaria.
En nuestro caso, sería – http: // localhost: 8888 / greeting-service-cloud / default:
Crear un cliente de configuración
Creemos el mismo servicio de saludo pero con un par de dependencias adicionales:
Aquí creamos greeting-service-cloud
servicio con Web
, Config Client
y Actuator
dependencias.
Tiene las mismas asignaciones REST que antes, con la adición de @RefreshScope
anotación. Esta anotación permite que el bean se actualice dinámicamente en tiempo de ejecución:
@RestController
@RefreshScope
public class GreetController {
@Value("${message.default.welcome}")
private String welcomeMessage;
@Value("${message.default.goodbye}")
private String goodBye;
@RequestMapping("/welcome")
public String welcome() {
return welcomeMessage;
}
@RequestMapping("/bye")
public String bye() {
return goodBye;
}
}
Aparte de application.properties
ahora tenemos que crear bootstrap.properties
, que se carga antes del application.properties
.
Por lo general, el cliente de configuración de Spring lo usa para obtener propiedades del servidor de configuración de Spring:
spring.application.name = greeting-service-cloud
spring.cloud.config.uri = http://localhost:8888
Aquí, primero establecemos el nombre de la aplicación. Spring Config Server buscará este nombre de archivo en el repositorio de Git y entregará su contenido.
También tenemos que mencionar dónde se está ejecutando el servidor de configuración especificándolo en spring.cloud.config.uri
.
Iniciemos este servicio y echemos un vistazo a los registros:
Observe que primero obtuvo las propiedades del Spring Config Server.
Nota: Si no se puede acceder al servidor de configuración, la aplicación no se iniciará.
Ahora revisemos nuestros puntos finales REST:
Así que externalizamos nuestras propiedades y tenemos una buena trazabilidad en nuestro repositorio de Git. Algunos puntos importantes a destacar:
- Nosotros podemos usar
spring-profiles-active
aquí también. Si esta variable se establece en el entorno del cliente de configuración, por ejemplo.dev
, se pasará al servidor de configuración mientras se solicitan propiedades. El servidor de configuración buscarágreeting-service-cloud-dev.properties
en el repositorio de Git y entregarlo al cliente. - Si hay un
application.properties
presente en el repositorio de Git, será servido a todos los clientes además de otros archivos. - Si el cliente de configuración solicita propiedades, por ejemplo, diga
dev
perfil, el servidor de configuración volveráapplication.properties
,application-dev.properties
ygreeting-service-cloud-dev.properties
. Las propiedades comunes serán anuladas por la última.
Propiedades refrescantes sin reiniciar
De forma predeterminada, los valores de configuración de los archivos de propiedades están listos o se recuperan al inicio de la aplicación y no nuevamente. Si hay algunos cambios por hacer, aún tenemos que reiniciar la aplicación.
Para resolver esto, agregamos la dependencia Actuator a nuestra aplicación. Proporciona algunos productos listos para la producción puntos finales que puede brindar información sobre nuestra aplicación que se puede utilizar con fines administrativos.
Tenemos que habilitar estos puntos finales manualmente especificando management.endpoints.web.exposure.include = *
en las propiedades de la aplicación.
Agreguemos esto al repositorio de Git y reiniciemos la aplicación. Podemos comprobar muchos detalles de nuestra aplicación visitando puntos finales como http: // localhost: 8080 / actuator / env, http: // localhost: 8080 / actuator / mappingsetc.
El que nos interesa es el /actuator/refresh
. Podemos forzar a un bean a actualizar su configuración (es decir, a extraer la configuración de nuevo del servidor de configuración) anotando el bean con @RefreshScope
.
Nota: Si se actualiza un bean, la próxima vez que se accede al bean (es decir, se ejecuta un método) se crea una nueva instancia.
Esto se puede activar enviando una solicitud HTTP POST vacía al punto final de actualización del cliente: http://<host:port>/actuator/refresh
.
Cambiemos el valor de uno en el repositorio de Git por otro:
message.default.welcome = Welcome from cloud config server changed...
message.default.goodbye = Goodbye...
management.endpoints.web.exposure.include = *
Ahora activemos el punto final de actualización:
curl localhost:8080/actuator/refresh -d {} -H "Content-Type: application/json"
Comprobar el /welcome
punto final:
Entonces, pudimos actualizar la propiedad de una aplicación en ejecución sin reiniciarla.
Conclusión
En este artículo, hemos cubierto cómo configurar propiedades en nuestra aplicación Spring Boot.
En primer lugar, hemos discutido formas simples de inyectar propiedades a nuestra aplicación y luego cambiar / anular estas propiedades en función de diferentes entornos.
En segundo lugar, hemos cubierto cómo obtener propiedades de Spring Config Server y cómo actualizar las propiedades sin una reconstrucción o reinicio.
Como siempre, el código de los ejemplos utilizados en este artículo se puede encontrar en Github.