Introducción
Una de las características más poderosas de Spring Boot es la capacidad de trabajar con perfiles, lo que permite a los desarrolladores definir diferentes configuraciones para diferentes entornos (desarrollo, prueba, producción, etc.). En este artículo, vamos a explorar cómo trabajar con perfiles en Spring Boot y cómo utilizarlos para gestionar configuraciones específicas de cada entorno.
¿Qué son los perfiles en Spring Boot?
Los perfiles en Spring Boot constituyen un mecanismo fundamental para segmentar configuraciones específicas según el entorno de ejecución. Permiten definir conjuntos de configuraciones independientes para entornos como desarrollo (dev), pruebas (test) o producción (prod), facilitando así la transición entre diferentes contextos sin necesidad de modificar el código.
Esta funcionalidad resulta especialmente valiosa porque permite:
- Mantener configuraciones aisladas para cada entorno
- Prevenir conflictos entre configuraciones de diferentes ambientes
- Cargar dinámicamente beans, propiedades y configuraciones específicas según el contexto activo
- Gestionar de manera eficiente las diferencias entre conexiones a bases de datos, configuraciones de seguridad o parámetros de servicios externos según el entorno de despliegue
Configuración de perfiles
Para trabajar con perfiles, vamos a crear archivos independientes para cada perfil en el directorio src/main/resources con la sintaxis application-{perfil}.properties o application-{perfil}.yml. A continuación, se muestra un ejemplo de cómo estructurar los archivos de configuración:
-
application.properties: Configuración común y predeterminada (se carga siempre)spring.application.name=mi-aplicacionlogging.level.root=INFOserver.port=8080 -
application-dev.properties: Configuración específica para desarrollospring.datasource.url=jdbc:mysql://localhost:3306/dev_dbspring.datasource.username=dev_userspring.datasource.password=dev_passwordlogging.level.org.springframework=DEBUG -
application-test.properties: Configuración específica para pruebasspring.datasource.url=jdbc:mysql://localhost:3306/test_dbspring.datasource.username=test_userspring.datasource.password=test_passwordlogging.level.org.springframework=ERROR -
application-prod.properties: Configuración específica para producciónspring.datasource.url=jdbc:mysql://production-server:3306/prod_dbspring.datasource.username=prod_userspring.datasource.password=${PROD_DB_PASSWORD}logging.level.org.springframework=WARN
IMPORTANTLos perfiles tiene un orden de prioridad. Si se define un perfil activo, Spring Boot cargará primero la configuración común y luego la específica del perfil. Si hay propiedades duplicadas, las del perfil específico sobrescribirán las comunes.
Activar un perfil
Existen varias formas de activar un perfil en Spring Boot. Al iniciar la aplicación, Spring Boot busca automáticamente el archivo application.properties o application.yml y carga la configuración base. Luego, dependiendo del perfil activo, carga las propiedades específicas del perfil correspondiente. A continuación, vamos a ver algunas formas de activar un perfil:
- A través de la línea de comandos: Podemos pasar el perfil como un argumento al iniciar la aplicación:
# Si estás ejecutando el JAR de la aplicaciónjava -jar mi-aplicacion.jar --spring.profiles.active=prod
# O si estás usando Mavenmvn spring-boot:run -Dspring-boot.run.profiles=prod- A través de variables de entorno: Podemos establecer la variable de entorno
SPRING_PROFILES_ACTIVEpara activar un perfil específico:
# En Windowsset SPRING_PROFILES_ACTIVE=prod
# En Linux o macOSexport SPRING_PROFILES_ACTIVE=prod- A través de la configuración de la aplicación: Podemos definir el perfil activo en el archivo
application.propertiesoapplication.yml:
spring.profiles.active=prodTambién podemos activar múltiples perfiles separándolos por comas (ya sea en la línea de comandos, variables de entorno o archivos de configuración):
spring.profiles.active=dev,qaPara verificar qué perfil está activo, podemos usar la anotación @Value para inyectar el valor de la propiedad spring.profiles.active en nuestro código:
import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;
@Componentpublic class ActiveProfileChecker { @Value("${spring.profiles.active}") private String activeProfile;
public String getActiveProfile() { return activeProfile; }}NOTECuando se establece la variable de entorno
SPRING_PROFILES_ACTIVE, este valor se refleja en la propiedadspring.profiles.activedentro de la aplicación.
Usar perfiles en Beans
Una de las características más potentes de los perfiles en Spring Boot es la capacidad de cargar beans específicos para cada perfil. Esto permite que ciertos componentes de la aplicación se carguen solo cuando el perfil correspondiente está activo.
Ejemplo básico: Servicio de mensajes
Veamos un ejemplo muy sencillo donde usaremos perfiles para mostrar diferentes mensajes según el entorno:
- Vamos a crear una interfaz de servicio:
public interface IMessageService { String sendMessage();}- Ahora, vamos a crear dos implementaciones de la interfaz, una para
desarrolloy otra paraproducción:
import org.springframework.context.annotation.Profile;import org.springframework.stereotype.Service;
// Esta implementación solo se cargará si el perfil activo es "dev"@Service@Profile("dev")public class MessageServiceDev implements IMessageService { @Override public String sendMessage() { return "Hello from Development!"; }}import org.springframework.context.annotation.Profile;import org.springframework.stereotype.Service;
// Esta implementación solo se cargará si el perfil activo es "prod"@Service@Profile("prod")public class MessageServiceProd implements IMessageService { @Override public String sendMessage() { return "Hello from Production!"; }}- Vamos a crear un controlador que utiliza el servicio de mensajes:
import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.bind.annotation.RequestMapping;
@RestController@RequestMapping("/api/messages")public class MessageController { private final IMessageService messageService;
// Inyectamos el servicio de mensajes public MessageController(IMessageService messageService) { this.messageService = messageService; }
@GetMapping public String getMessage() { return messageService.sendMessage(); }}- Activaremos el perfil correspondiente al iniciar la aplicación. Para este caso, optaremos por activarlo desde el archivo
application.properties:
spring.profiles.active=dev- El resultado al acceder a la ruta
/api/messagesserá:- Perfil
dev: “Hello from Development!” - Perfil
prod: “Hello from Production!”
- Perfil
Perfiles múltiples
En algunas situaciones, es posible que desees que un bean esté disponible en múltiples perfiles. Para ello, puedes especificar varios perfiles en la anotación @Profile. Por ejemplo, si deseas que un servicio esté disponible tanto en dev como en qa, puedes hacerlo de la siguiente manera:
import org.springframework.context.annotation.Profile;import org.springframework.stereotype.Service;
// Esta implementación se cargará si el perfil activo es "dev" o "qa"@Service@Profile({"dev", "qa"})public class MessageServiceDevOrQa implements IMessageService { @Override public String sendMessage() { return "Hello from Development or QA!"; }}Operadores lógicos
Spring Boot permite usar operadores lógicos en la anotación @Profile. Esto te permite activar beans según condiciones más complejas.
Operador ! (NOT)
El operador ! se usa para excluir un perfil. El bean solo se activará si ese perfil no está presente.
import org.springframework.context.annotation.Profile;import org.springframework.stereotype.Service;
// Esta implementación se cargará si el perfil "prod" NO está activo@Service@Profile("!prod")public class MessageServiceNoProd implements IMessageService { @Override public String sendMessage() { return "Hello from Non-Production!"; }}Operador & (AND)
El operador & se usa para indicar que todos los perfiles listados deben estar activos al mismo tiempo para activar el bean.
import org.springframework.context.annotation.Profile;import org.springframework.stereotype.Service;
// Esta implementación se cargará solo si están activos los perfiles "x" y "y"@Service@Profile("x & y")public class MessageServiceXAndY implements IMessageService { @Override public String sendMessage() { return "Hello from X and Y!"; }}Combinación de ! y &
También puedes combinar ambos operadores para aplicar lógica más específica.
import org.springframework.context.annotation.Profile;import org.springframework.stereotype.Service;
// Esta implementación se cargará si el perfil "x" NO está activo y el perfil "y" NO está activo@Service@Profile("!x & !y")public class MessageServiceNotXAndY implements IMessageService { @Override public String sendMessage() { return "Hello from Not X and Not Y!"; }}Conclusión
Los perfiles en Spring Boot son una herramienta poderosa para gestionar configuraciones específicas de entorno. Nos permiten mantener el código limpio y organizado, evitando la necesidad de modificar configuraciones manualmente al cambiar de entorno. Al utilizar perfiles, podemos asegurarnos de que nuestra aplicación se comporte de manera coherente y predecible en diferentes contextos.