Każdy programista zna ten problem: aplikacja działa lokalnie, ale po wdrożeniu na serwer przestaje działać. Często winne są różne konfiguracje – na lokalnej maszynie używasz bazy H2, na produkcji PostgreSQL. Spring Profiles rozwiązują ten problem elegancko.
W tym artykule dowiesz się jak skonfigurować różne środowiska w Spring bez zmieniania kodu źródłowego.
Dlaczego Spring Profiles są ważne
W profesjonalnym development masz co najmniej 3 środowiska: development (lokalne), test (staging) i production. Każde potrzebuje innych ustawień – innych baz danych, różnych poziomów logowania, innych adresów URL. Spring Profiles to standard industry w zarządzaniu konfiguracją.
Co się nauczysz:
- Czym są Spring Profiles i dlaczego są potrzebne
- Jak tworzyć profile dla różnych środowisk
- Konfigurację przez application.properties i YAML
- Aktywację profili na różne sposoby
- Najlepsze praktyki w zarządzaniu środowiskami
Wymagania wstępne:
Podstawowa znajomość Spring Framework i Spring Boot. Doświadczenie z application.properties. Znajomość Maven/Gradle mile widziana.
Czym są Spring Profiles
Tworzenie profili przez properties
Struktura plików konfiguracyjnych
Spring Boot automatycznie wczytuje pliki konfiguracyjne według wzorca:
src/main/resources/ ├── application.properties # Domyślna konfiguracja ├── application-dev.properties # Profil development ├── application-test.properties # Profil test └── application-prod.properties # Profil production
Przykładowa konfiguracja
application.properties (konfiguracja domyślna):
# Konfiguracja wspólna dla wszystkich środowisk app.name=Blog Application app.version=1.0.0 # Domyślnie włącz profil development spring.profiles.active=dev
application-dev.properties (development):
# Baza danych H2 w pamięci spring.datasource.url=jdbc:h2:mem:devdb spring.datasource.username=sa spring.datasource.password= # Włącz H2 console dla testów spring.h2.console.enabled=true # Debug level logging logging.level.com.example=DEBUG logging.level.org.springframework=INFO # Wyłącz cache dla szybszego developmentu spring.thymeleaf.cache=false
application-test.properties (testing):
# Baza testowa MySQL spring.datasource.url=jdbc:mysql://test-server:3306/blog_test spring.datasource.username=test_user spring.datasource.password=test_pass # Wyłącz DDL auto na testach spring.jpa.hibernate.ddl-auto=validate # Logowanie tylko błędów logging.level.com.example=WARN logging.level.org.springframework=WARN # Test-specific ustawienia app.feature.email-sending=false
application-prod.properties (production):
# Produkcyjna baza PostgreSQL spring.datasource.url=jdbc:postgresql://prod-db:5432/blog_prod spring.datasource.username=${DB_USER} spring.datasource.password=${DB_PASSWORD} # Bezpieczne ustawienia JPA spring.jpa.hibernate.ddl-auto=none spring.jpa.show-sql=false # Minimal logging logging.level.com.example=INFO logging.level.org.springframework=WARN # Production features app.feature.email-sending=true app.feature.analytics=true
Profile-specific beany
Możesz tworzyć beany które są aktywne tylko w określonych profilach:
@Configuration public class DatabaseConfig { @Bean @Profile("dev") public DataSource devDataSource() { return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .build(); } @Bean @Profile("prod") public DataSource prodDataSource() { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:postgresql://prod-db:5432/blog"); config.setMaximumPoolSize(20); return new HikariDataSource(config); } @Bean @Profile({"test", "integration"}) public DataSource testDataSource() { return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .setName("testdb") .build(); } }
Profile w komponentach
@Service @Profile("dev") public class MockEmailService implements EmailService { @Override public void sendEmail(String to, String subject, String body) { System.out.println("DEV: Wyślij email do " + to); System.out.println("Temat: " + subject); } } @Service @Profile("prod") public class SmtpEmailService implements EmailService { @Override public void sendEmail(String to, String subject, String body) { // Prawdziwe wysyłanie przez SMTP // ... } }
Aktywacja profili
1. Przez application.properties
# Aktywuj jeden profil spring.profiles.active=prod # Aktywuj wiele profili spring.profiles.active=prod,monitoring,security
2. Przez argumenty JVM
java -jar -Dspring.profiles.active=prod myapp.jar
3. Przez zmienne środowiskowe
export SPRING_PROFILES_ACTIVE=prod java -jar myapp.jar
4. Programowo
@SpringBootApplication public class BlogApplication { public static void main(String[] args) { SpringApplication app = new SpringApplication(BlogApplication.class); app.setAdditionalProfiles("prod"); app.run(args); } }
YAML configuration
Zamiast wielu plików properties możesz użyć jednego pliku YAML:
# application.yml spring: profiles: active: dev app: name: Blog Application version: 1.0.0 --- spring: profiles: dev datasource: url: jdbc:h2:mem:devdb username: sa password: h2: console: enabled: true logging: level: com.example: DEBUG --- spring: profiles: prod datasource: url: jdbc:postgresql://prod-db:5432/blog username: ${DB_USER} password: ${DB_PASSWORD} logging: level: com.example: INFO
Najlepsze praktyki
Konwencje nazewnictwa
- dev – lokalne środowisko developera
- test/staging – środowisko testowe
- prod – produkcja
- integration – testy integracyjne
Bezpieczeństwo
- Używaj zmiennych środowiskowych dla haseł
- Nigdy nie commituj prawdziwych danych produkcyjnych
- Różne klucze API dla każdego środowiska
- Wyłącz debug informacje na produkcji
Profile domyślne
# Profil używany gdy żaden nie jest aktywny spring.profiles.default=dev
W aplikacji: @Value("${spring.profiles.active}")
lub przez Environment bean. W logach Spring Boot wypisuje aktywne profile podczas startu. Można też sprawdzić przez endpoint /actuator/env jeśli Actuator jest włączony.
Tak! Można aktywować wiele profili: spring.profiles.active=prod,monitoring,security
. Spring Boot wczyta konfigurację ze wszystkich aktywnych profili. Jeśli są konflikty, ostatni profil ma pierwszeństwo.
Spring użyje profilu domyślnego określonego przez spring.profiles.default
. Jeśli nie jest ustawiony, aplikacja uruchomi się bez żadnego profilu – tylko z application.properties.
W IDE ustaw VM options: -Dspring.profiles.active=test
. W IntelliJ: Run Configuration → VM options. Możesz też tworzyć różne Run Configurations dla każdego profilu.
Tak! Profile świetnie współpracują z @ConfigurationProperties. Możesz mieć różne wartości properties dla każdego profilu i Spring automatycznie załaduje odpowiednie.
Przez zmienną środowiskową: docker run -e SPRING_PROFILES_ACTIVE=prod myapp
lub w docker-compose: environment: - SPRING_PROFILES_ACTIVE=prod
Przydatne zasoby
- Spring Boot Profiles – oficjalna dokumentacja
- Baeldung – Guide to Spring Profiles
- Spring Blog – Introducing @Profile
🚀 Zadanie dla Ciebie
Skonfiguruj profile dla aplikacji e-commerce:
1. Stwórz 3 profile: dev, test, prod
2. Dev: H2 database, debug logging, mock payment service
3. Test: MySQL database, warn logging, test payment service
4. Prod: PostgreSQL database, info logging, real payment service
5. Każdy profil ma mieć różne ustawienia email (dev – console, prod – SMTP)
6. Przetestuj uruchamianie aplikacji z różnymi profilami
Bonus: dodaj profil „docker” z konfiguracją dla kontenerów!
Spring Profiles to podstawowe narzędzie każdego Spring developera. Dzięki nim jedna aplikacja może działać w różnych środowiskach bez modyfikacji kodu. To klucz do profesjonalnego podejścia do deployment i konfiguracji.
Jakich profili używasz w swoich projektach? Masz jakieś ciekawe triki z konfiguracją? Podziel się w komentarzach!