Spring Boot 3.4 : Toutes les nouveautés et améliorations
Découvrez les nouveautés de Spring Boot 3.4 : structured logging, virtual threads, graceful shutdown par défaut, RestClient amélioré et MockMvcTester.

Spring Boot 3.4, sorti en novembre 2024, apporte des améliorations majeures pour la productivité des développeurs et les performances des applications. Cette version introduit le structured logging natif, active le graceful shutdown par défaut, et étend le support des virtual threads.
Spring Boot 3.4 nécessite Java 17 minimum et supporte Java 21 pour les virtual threads. Cette version utilise Spring Framework 6.2.
Structured Logging natif
Le structured logging représente une avancée majeure pour l'observabilité des applications. Au lieu de logs textuels difficiles à parser, Spring Boot 3.4 génère des logs au format JSON exploitables par des outils comme Elasticsearch, Grafana Loki ou Datadog.
Trois formats sont supportés nativement : Elastic Common Schema (ECS), Logstash et Graylog Extended Log Format (GELF).
# application.properties
# Activer le structured logging en console
logging.structured.format.console=ecs
# Ou pour les fichiers de log
logging.structured.format.file=logstashCette configuration simple produit des logs JSON structurés automatiquement.
@RestController
@RequestMapping("/api/demo")
public class LoggingController {
// Injection du logger via SLF4J
private static final Logger logger = LoggerFactory.getLogger(LoggingController.class);
@GetMapping("/action")
public ResponseEntity<String> performAction(@RequestParam String userId) {
// Le log sera automatiquement formaté en JSON structuré
logger.info("Action performed by user: {}", userId);
return ResponseEntity.ok("Action completed");
}
}Avec le format ECS activé, ce log devient un objet JSON contenant le timestamp, le niveau, le message, le nom de la classe, le thread et les métadonnées de l'application. Cette structure facilite les recherches et l'agrégation dans les plateformes de monitoring.
Graceful Shutdown activé par défaut
Changement important : le graceful shutdown est maintenant activé par défaut. Les requêtes HTTP en cours sont traitées avant l'arrêt du serveur, évitant les erreurs 502 lors des déploiements.
# application.properties
# Le graceful shutdown est maintenant ON par défaut
# Pour restaurer l'ancien comportement (arrêt immédiat) :
server.shutdown=immediate
# Configurer le délai maximum d'attente (30s par défaut)
spring.lifecycle.timeout-per-shutdown-phase=45sCe comportement s'applique à tous les serveurs embarqués : Tomcat, Jetty, Undertow et Reactor Netty.
@Configuration
public class LifecycleConfig {
private static final Logger logger = LoggerFactory.getLogger(LifecycleConfig.class);
@Bean
public ApplicationListener<ContextClosedEvent> gracefulShutdownListener() {
// Ce listener s'exécute au début du shutdown
return event -> {
logger.info("Graceful shutdown initiated - completing in-flight requests");
// Logique personnalisée : fermer des connexions, sauvegarder l'état, etc.
};
}
}Cette amélioration rend les déploiements zero-downtime plus simples à implémenter, sans configuration supplémentaire dans la plupart des cas.
Virtual Threads étendus
Spring Boot 3.4 étend le support des virtual threads (Java 21+) à davantage de composants. Le OtlpMeterRegistry et le serveur Undertow utilisent maintenant les virtual threads lorsqu'ils sont activés.
# application.properties
# Activer les virtual threads globalement
spring.threads.virtual.enabled=trueCette simple propriété transforme le modèle de threading de l'application. Chaque requête HTTP obtient son propre virtual thread, permettant de gérer des milliers de connexions simultanées sans épuiser le pool de threads.
@Service
public class AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncService.class);
// Avec virtual threads activés, chaque appel bloquant
// ne consomme plus de thread OS
public String fetchExternalData() {
logger.info("Executing on thread: {}", Thread.currentThread());
// Appel HTTP bloquant - avec virtual threads,
// le thread OS est libéré pendant l'attente I/O
return restClient.get()
.uri("https://api.external.com/data")
.retrieve()
.body(String.class);
}
}Les virtual threads brillent pour les applications I/O-bound : appels HTTP, requêtes base de données, opérations fichiers. Le thread OS est libéré pendant l'attente, puis réassigné à la reprise.
Les virtual threads nécessitent Java 21 minimum. Sur Java 17, cette propriété est ignorée et le comportement classique s'applique.
RestClient et RestTemplate améliorés
Spring Boot 3.4 normalise la configuration des clients HTTP. La sélection du HttpRequestFactory suit maintenant une priorité claire basée sur le classpath.
@Configuration
public class HttpClientConfig {
@Bean
public RestClient restClient(RestClient.Builder builder) {
// Spring Boot choisit automatiquement l'implémentation :
// 1. Apache HTTP Components (si présent)
// 2. Jetty Client
// 3. Reactor Netty
// 4. JDK HttpClient (Java 11+)
// 5. SimpleClientHttpRequestFactory (fallback)
return builder
.baseUrl("https://api.example.com")
.defaultHeader("Accept", "application/json")
.build();
}
}La configuration du comportement de redirection est également simplifiée.
# application.properties
# Forcer une implémentation spécifique
spring.http.client.factory=jdk
# Configurer le comportement des redirections
spring.http.client.redirects=dont-followPour un contrôle plus fin, le nouveau ClientHttpRequestFactoryBuilder permet une configuration programmatique complète.
@Configuration
public class CustomHttpClientConfig {
@Bean
public RestClient customRestClient(ClientHttpRequestFactoryBuilder factoryBuilder) {
// Configuration avancée du factory
ClientHttpRequestFactory factory = factoryBuilder
.httpComponents()
.connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(30))
.build();
return RestClient.builder()
.requestFactory(factory)
.baseUrl("https://api.example.com")
.build();
}
}Cette approche offre une flexibilité maximale tout en gardant une API cohérente, quelle que soit l'implémentation HTTP sous-jacente.
Prêt à réussir tes entretiens Spring Boot ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
MockMvcTester pour des tests fluides
Spring Boot 3.4 introduit MockMvcTester, une alternative à MockMvc basée sur l'API fluide d'AssertJ. Cette nouvelle approche rend les tests plus lisibles et expressifs.
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvcTester mockMvc; // Nouvelle classe !
@Test
void shouldReturnUserById() {
// API fluide avec AssertJ
mockMvc.get().uri("/api/users/{id}", 1)
.assertThat()
.hasStatusOk()
.hasContentType(MediaType.APPLICATION_JSON)
.bodyJson()
.extractingPath("$.name")
.isEqualTo("John Doe");
}
@Test
void shouldReturn404ForUnknownUser() {
mockMvc.get().uri("/api/users/{id}", 999)
.assertThat()
.hasStatus(HttpStatus.NOT_FOUND)
.bodyJson()
.extractingPath("$.error")
.isEqualTo("User not found");
}
}Comparé à l'ancienne approche avec MockMvc, les assertions sont plus concises et le chaînage plus naturel.
@WebMvcTest(UserController.class)
class ComparisonTest {
@Autowired
private MockMvcTester mockMvcTester;
@Autowired
private MockMvc mockMvc;
@Test
void withMockMvcTester() {
// Nouvelle approche : fluide et concise
mockMvcTester.post().uri("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\": \"Jane\"}")
.assertThat()
.hasStatus(HttpStatus.CREATED)
.hasHeader("Location", "/api/users/2");
}
@Test
void withClassicMockMvc() throws Exception {
// Ancienne approche : plus verbeuse
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\": \"Jane\"}"))
.andExpect(status().isCreated())
.andExpect(header().string("Location", "/api/users/2"));
}
}MockMvcTester est auto-configuré lorsque AssertJ est présent dans le classpath (inclus par défaut avec spring-boot-starter-test).
Docker Compose et Testcontainers enrichis
Le support Docker Compose gagne en flexibilité avec la possibilité d'utiliser plusieurs fichiers de configuration et de passer des arguments personnalisés.
# application.properties
# Utiliser plusieurs fichiers Docker Compose
spring.docker.compose.file=compose.yaml,compose-dev.yaml
# Passer des arguments au démarrage
spring.docker.compose.start.arguments=--scale redis=2
# Arguments à l'arrêt
spring.docker.compose.stop.arguments=--timeout 60De nouveaux services sont automatiquement détectés et configurés.
# compose.yaml
services:
postgres:
image: postgres:16
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
redis-stack:
image: redis/redis-stack:latest
ports:
- "6379:6379"
- "8001:8001" # RedisInsight UI
grafana-lgtm:
image: grafana/otel-lgtm:latest
ports:
- "3000:3000" # Grafana
- "4317:4317" # OTLP gRPCSpring Boot 3.4 détecte automatiquement ces services et configure les propriétés de connexion correspondantes.
Pour les tests avec Testcontainers, de nouveaux conteneurs sont supportés.
@TestConfiguration(proxyBeanMethods = false)
public class IntegrationTestConfig {
@Bean
@ServiceConnection
public PostgreSQLContainer<?> postgresContainer() {
return new PostgreSQLContainer<>("postgres:16");
}
@Bean
@ServiceConnection
public RedisStackContainer redisStackContainer() {
// Nouveau support Redis Stack
return new RedisStackContainer("redis/redis-stack:latest");
}
@Bean
@ServiceConnection
public LgtmStackContainer observabilityContainer() {
// Nouveau support Grafana LGTM (Loki, Grafana, Tempo, Mimir)
return new LgtmStackContainer("grafana/otel-lgtm:latest");
}
}L'annotation @ServiceConnection configure automatiquement les propriétés de connexion, éliminant le besoin de @DynamicPropertySource dans la plupart des cas.
Actuator SSL et observabilité
Le nouveau endpoint /actuator/info expose maintenant des informations sur les certificats SSL configurés : dates de validité, émetteur et sujet.
# application.properties
# Activer les informations SSL dans l'actuator
management.info.ssl.enabled=true
# Configurer un seuil d'alerte pour les certificats expirant bientôt
management.health.ssl.certificate-validity-warning-threshold=30dCette fonctionnalité permet de monitorer l'expiration des certificats directement via l'actuator, facilitant l'automatisation des renouvellements.
@Configuration
public class SslMonitoringConfig {
@Bean
public HealthIndicator sslCertificateHealth(SslInfo sslInfo) {
return () -> {
// Vérification personnalisée de la validité des certificats
boolean allValid = sslInfo.getBundles().values().stream()
.flatMap(bundle -> bundle.getCertificates().stream())
.allMatch(cert -> cert.getValidityEnds().isAfter(Instant.now()));
return allValid
? Health.up().build()
: Health.down().withDetail("reason", "Certificate expiring soon").build();
};
}
}Pour l'observabilité, le transport OTLP supporte maintenant gRPC en plus de HTTP.
# application.properties
# Utiliser gRPC pour OTLP (traces et métriques)
management.otlp.tracing.transport=grpc
management.otlp.tracing.endpoint=http://localhost:4317
# Nouveau : grouper les applications
spring.application.group=payment-servicesLe groupe d'application (spring.application.group) permet de regrouper logiquement plusieurs services dans les dashboards d'observabilité.
Images OCI plus légères
Le builder par défaut pour les images OCI change de paketobuildpacks/builder-jammy-base vers paketobuildpacks/builder-jammy-java-tiny, produisant des images significativement plus petites.
tasks.named("bootBuildImage") {
// Support ARM natif (nouveau)
imagePlatform = "linux/arm64"
// Nouveau flag de sécurité
trustBuilder = false
// Configuration de l'image
imageName = "myregistry.com/myapp:${version}"
}Le nouveau paramètre imagePlatform facilite les builds cross-platform pour ARM et x64.
<!-- pom.xml -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<!-- Support ARM natif -->
<platform>linux/arm64</platform>
<!-- Builder optimisé pour images minimales -->
<builder>paketobuildpacks/builder-jammy-java-tiny</builder>
</image>
</configuration>
</plugin>Ces images optimisées démarrent plus rapidement et consomment moins de ressources, particulièrement avantageux pour les déploiements Kubernetes.
Le changement de builder peut affecter les applications dépendant de certains outils système. Testez la nouvelle image avant de déployer en production.
Changements de validation des beans
Spring Boot 3.4 aligne le comportement de validation sur la spécification Bean Validation. La validation ne cascade plus automatiquement vers les propriétés imbriquées.
@ConfigurationProperties(prefix = "app")
@Validated
public class AppConfig {
@NotBlank
private String name;
// IMPORTANT : @Valid requis pour cascader la validation
@Valid
private DatabaseConfig database;
// Sans @Valid, les contraintes de ServerConfig ne seront PAS vérifiées
private ServerConfig server;
// Getters et setters
}
public class DatabaseConfig {
@NotBlank
private String url;
@Min(1)
private int poolSize;
// Getters et setters
}
public class ServerConfig {
@NotNull // Cette contrainte ne sera PAS vérifiée sans @Valid sur le parent
private Integer port;
// Getters et setters
}Ce changement peut casser des applications existantes. Auditez les classes @ConfigurationProperties et ajoutez @Valid là où la validation doit cascader.
Dépréciation de @MockBean et @SpyBean
Les annotations @MockBean et @SpyBean de Spring Boot sont dépréciées au profit des nouvelles annotations Mockito.
@SpringBootTest
class UserServiceTest {
// Nouveau : annotations Mockito natives
@MockitoBean
private UserRepository userRepository;
@MockitoSpyBean
private EmailService emailService;
@Autowired
private UserService userService;
@Test
void shouldCreateUser() {
// Configuration du mock
when(userRepository.save(any())).thenReturn(new User(1L, "test@example.com"));
userService.createUser("test@example.com");
// Vérification du spy
verify(emailService).sendWelcomeEmail("test@example.com");
}
}Les anciennes annotations fonctionnent encore mais affichent un avertissement de dépréciation. Planifiez la migration vers @MockitoBean et @MockitoSpyBean.
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Conclusion
Spring Boot 3.4 apporte des améliorations substantielles pour la productivité et l'observabilité :
Checklist de migration :
- ✅ Activer le structured logging pour améliorer l'observabilité
- ✅ Vérifier le comportement du graceful shutdown (maintenant activé par défaut)
- ✅ Considérer les virtual threads pour les applications I/O-bound (Java 21+)
- ✅ Migrer vers MockMvcTester pour des tests plus lisibles
- ✅ Ajouter
@Validsur les propriétés imbriquées des@ConfigurationProperties - ✅ Remplacer
@MockBean/@SpyBeanpar@MockitoBean/@MockitoSpyBean - ✅ Tester les nouvelles images OCI avant déploiement en production
Spring Boot 3.4 consolide la position du framework comme référence pour le développement Java moderne, avec une attention particulière portée aux standards d'observabilité et aux performances.
Sources :
Tags
Partager
Articles similaires

30 questions d'entretien Spring Boot : Guide complet pour développeurs Java
Préparez vos entretiens Spring Boot avec ces 30 questions essentielles couvrant l'auto-configuration, les starters, Spring Data JPA, la sécurité et les tests.

Spring Modulith : architecture modulaire monolithique expliquée
Découvrez Spring Modulith pour construire des monolithes modulaires en Java. Architecture, modules, événements asynchrones et tests avec exemples Spring Boot 3.

Spring Batch 5 en entretien technique : partitioning, chunks et fault tolerance
Préparez vos entretiens Spring Batch 5 : 15 questions essentielles sur le partitioning, chunk-oriented processing, fault tolerance avec exemples de code Java 21.