En Spring Boot, el archivo principal de configuración se ubica por defecto en src/main/resources/application.properties. Este archivo centraliza ajustes cruciales del sistema, tales como el puerto del servidor, datos de conexión a bases de datos como MySQL y parámetros de servicios externos.
Formatos disponibles para archivos de configuración
El framework soporta dos formatos principales:
- Formato .properties: Utiliza pares clave-valor en texto plano. Por ejemplo:
clave=valor. Para estructuras jerárquicas se usa notación de punto:a.b.c.clave=valor. Los comentarios se indican con el símbolo#. - Formato .yml (YAML): Ofrece mayor legibilidad. La sintaxis básica es
clave: valor. Para múltiples niveles, es obligatorio usar saltos de línea y mantener la indentación. Ejemplo: ``` clave1: clave2: nombre: Juan_Perez edad: 25 clave3: nombre: Ana_Lopez edad: 28
No existe una ventaja técnica definitiva entre ambos formatos; la elección suele basarce en preferencias del equipo o convenciones del proyecto. Es crucial no mezclar ambos formatos para la misma configuración, ya que, en caso de conflicto, el archivo .properties (creado por defecto por el IDE) prevalecerá.
Parámetros de configuración del servidor
A continuación, un ejemplo de configuraciones comunes del embebido servidor web Tomcat:
# Puerto de la aplicación
server.port=9090
# Ruta base del contexto
server.servlet.context-path=/aplicacion
# Ruta para páginas de error
server.error.path=/error-customizado
# Tiempo de expiración de la sesión (en minutos)
server.servlet.session.timeout=45
# Dirección IP de enlace del servidor
server.address=192.168.1.100
# Número máximo de hilos de Tomcat
server.tomcat.threads.max=150
# Codificación de caracteres para URIs
server.tomcat.uri-encoding=UTF-8
Acceso a los valores de configuración
1. Mediante la anotación @Value
Se puede inyectar un valor único o compuesto directamente en un campo.
// Para un valor simple
@Value("${app.titulo}")
private String tituloAplicacion;
// Para un valor anidado
@Value("${base.datos.url}")
private String urlBaseDatos;
Es imperativo que la clave solicitada exista en los archivos de configuración; de lo contrario, la aplicación fallará al iniciar.
2. Usando el componente Environment
Esta interfaz del contenedor de Spring ofrece un enfoque más flexible, permitiendo manejar claves opcionales con valores predeterminados.
@Autowired
private Environment entorno;
// Verificar si una propiedad existe
boolean existe = entorno.containsProperty("clave.opcional");
// Obtener valor pudiendo devolver null
String valorOpcional = entorno.getProperty("clave.opcional");
// Proporcionar un valor por defecto si la clave no existe
String valorSeguro = entorno.getProperty("clave.inexistente", "valor_seguro");
// Especificar el tipo de dato del valor devuelto
Integer puerto = entorno.getProperty("server.port", Integer.class, 8080);
3. Vinculación mediante clases de configuración con @ConfigurationProperties
Este método permite mapear un grupo de propiedades relacionadas en un objeto Java tipado.
Opción A: Declarar la clase como un componente Spring.
# En application.properties
empleado.departamento.nombre=Desarrollo
empleado.departamento.codigo=DEV-001
empleado.departamento.sede=Madrid
@Component
@ConfigurationProperties(prefix = "empleado.departamento")
public class DatosDepartamento {
private String nombre;
private String codigo;
private String sede;
// Getters y Setters
}
Posteriormente, se inyecta el componente donde se necesite.
Opción B: Registrar la instancia como un Bean explícito.
// La clase no requiere anotaciones
public class DatosDepartamento {
private String nombre;
private String codigo;
private String sede;
// Getters y Setters
}
// En una clase de configuración
@Configuration
public class AppConfig {
@Bean
@ConfigurationProperties(prefix = "empleado.departamento")
public DatosDepartamento datosDepartamento() {
return new DatosDepartamento();
}
}
La inyección posterior del bean DatosDepartamento funcionará igual. El registro explícito como Bean facilita la gestión de alias y la centralización de la configuración. No deben combinarse ambos enfoques para la misma clase, ya que generaría beans duplicados.
Gestión de múltiples archivos de configuración
Spring Boot permite cargar configuraciones adicionales para diferentes contextos o entornos.
Carga de archivos personalizados
Se pueden crear archivos como propiedades-externas.properties en src/main/resources. Para cargarlos, se utiliza la anotación @PropertySource en la clase principle de la aplicación.
@SpringBootApplication
@PropertySource(value = "classpath:propiedades-externas.properties")
public class AplicacionPrincipal {
public static void main(String[] args) {
SpringApplication.run(AplicacionPrincipal.class, args);
}
}
Si el archivo se encuentra en un subdirectorio, por ejemplo config, la ruta sería classpath:config/propiedades-externas.properties.
Activación de perfiles
Para cargar configuraciones específicas de un entorno (desarrollo, producción, etc.), se define el perfil activo en application.properties:
spring.profiles.active=produccion
Esto hará que Spring Boot cargue, además del archivo principal, el archivo application-produccion.properties.
Personalización con clases de configuración
La anotación @Configuration permite definir beans que sobreescriben o complementan los configurados automáticamente por Spring Boot.
Ejemplo: Personalización de páginas de error.
Por defecto, el framework muestra páginas de errer genéricas. Se pueden reemplazar con respuestas personalizadas.
@Configuration
public class ConfiguracionErrores {
@Bean
public ErrorPageRegistrar customErrorPageRegistrar() {
return registry -> {
// Redirigir error 404 a una ruta controlada
ErrorPage pagina404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
// Redirigir error 500 a una ruta controlada
ErrorPage pagina500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");
registry.addErrorPages(pagina404, pagina500);
};
}
}
En un controlador, se definen los manejadores para esas rutas de error:
@Controller
public class ManejadorErrores {
@RequestMapping("/error/404")
@ResponseBody
public String manejar404() {
return "El recurso solicitado no fue encontrado.";
}
@RequestMapping("/error/500")
@ResponseBody
public String manejar500() {
return "Ocurrió un error interno en el servidor.";
}
}