Spring Boot 3.4: Tutte le novità spiegate
Spring Boot 3.4 introduce logging strutturato nativo, virtual threads estesi, graceful shutdown predefinito e MockMvcTester. Guida completa alle nuove funzionalità.

Spring Boot 3.4, rilasciato a novembre 2024, offre miglioramenti significativi in termini di produttività e performance delle applicazioni. Questa versione introduce il logging strutturato nativo, abilita il graceful shutdown per impostazione predefinita ed estende il supporto ai virtual threads nell'intero framework.
Spring Boot 3.4 richiede Java 17 come minimo e supporta Java 21 per i virtual threads. Questa versione utilizza Spring Framework 6.2.
Logging strutturato nativo
Il logging strutturato rappresenta un avanzamento importante per l'osservabilità delle applicazioni. Invece di log testuali difficili da analizzare, Spring Boot 3.4 genera log in formato JSON consumabili da strumenti come Elasticsearch, Grafana Loki o Datadog.
Tre formati sono supportati nativamente: Elastic Common Schema (ECS), Logstash e Graylog Extended Log Format (GELF).
# application.properties
# Enable structured logging in console
logging.structured.format.console=ecs
# Or for log files
logging.structured.format.file=logstashQuesta semplice configurazione produce log JSON strutturati in modo automatico.
@RestController
@RequestMapping("/api/demo")
public class LoggingController {
// Logger injection via SLF4J
private static final Logger logger = LoggerFactory.getLogger(LoggingController.class);
@GetMapping("/action")
public ResponseEntity<String> performAction(@RequestParam String userId) {
// Log will be automatically formatted as structured JSON
logger.info("Action performed by user: {}", userId);
return ResponseEntity.ok("Action completed");
}
}Con il formato ECS abilitato, questo log diventa un oggetto JSON contenente timestamp, livello, messaggio, nome della classe, thread e metadati dell'applicazione. Questa struttura semplifica la ricerca e l'aggregazione nelle piattaforme di monitoraggio.
Graceful Shutdown abilitato per impostazione predefinita
Cambiamento importante: il graceful shutdown è ora abilitato per impostazione predefinita. Le richieste HTTP in corso vengono elaborate prima dell'arresto del server, evitando errori 502 durante i deployment.
# application.properties
# Graceful shutdown is now ON by default
# To restore previous behavior (immediate shutdown):
server.shutdown=immediate
# Configure maximum wait timeout (30s default)
spring.lifecycle.timeout-per-shutdown-phase=45sQuesto comportamento si applica a tutti i server embedded: Tomcat, Jetty, Undertow e Reactor Netty.
@Configuration
public class LifecycleConfig {
private static final Logger logger = LoggerFactory.getLogger(LifecycleConfig.class);
@Bean
public ApplicationListener<ContextClosedEvent> gracefulShutdownListener() {
// This listener executes at shutdown start
return event -> {
logger.info("Graceful shutdown initiated - completing in-flight requests");
// Custom logic: close connections, save state, etc.
};
}
}Questo miglioramento semplifica l'implementazione di deployment senza downtime, senza necessità di configurazione aggiuntiva nella maggior parte dei casi.
Supporto esteso ai Virtual Threads
Spring Boot 3.4 estende il supporto ai virtual threads (Java 21+) a più componenti. OtlpMeterRegistry e il server Undertow ora utilizzano virtual threads quando abilitati.
# application.properties
# Enable virtual threads globally
spring.threads.virtual.enabled=trueQuesta singola proprietà trasforma il modello di threading dell'applicazione. Ogni richiesta HTTP ottiene il proprio virtual thread, consentendo migliaia di connessioni simultanee senza esaurire il pool di thread.
@Service
public class AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncService.class);
// With virtual threads enabled, each blocking call
// no longer consumes an OS thread
public String fetchExternalData() {
logger.info("Executing on thread: {}", Thread.currentThread());
// Blocking HTTP call - with virtual threads,
// the OS thread is released during I/O wait
return restClient.get()
.uri("https://api.external.com/data")
.retrieve()
.body(String.class);
}
}I virtual threads eccellono nelle applicazioni con carico I/O elevato: chiamate HTTP, query al database, operazioni sui file. Il thread del sistema operativo viene rilasciato durante l'attesa e riassegnato alla ripresa.
I virtual threads richiedono Java 21 come minimo. Su Java 17, questa proprietà viene ignorata e si applica il comportamento classico.
RestClient e RestTemplate migliorati
Spring Boot 3.4 normalizza la configurazione del client HTTP. La selezione dell'HttpRequestFactory segue ora una precedenza chiara basata sul classpath.
@Configuration
public class HttpClientConfig {
@Bean
public RestClient restClient(RestClient.Builder builder) {
// Spring Boot automatically chooses implementation:
// 1. Apache HTTP Components (if present)
// 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();
}
}Anche la configurazione del comportamento dei redirect è semplificata.
# application.properties
# Force specific implementation
spring.http.client.factory=jdk
# Configure redirect behavior
spring.http.client.redirects=dont-followPer un controllo più dettagliato, il nuovo ClientHttpRequestFactoryBuilder consente una configurazione programmatica completa.
@Configuration
public class CustomHttpClientConfig {
@Bean
public RestClient customRestClient(ClientHttpRequestFactoryBuilder factoryBuilder) {
// Advanced factory configuration
ClientHttpRequestFactory factory = factoryBuilder
.httpComponents()
.connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(30))
.build();
return RestClient.builder()
.requestFactory(factory)
.baseUrl("https://api.example.com")
.build();
}
}Questo approccio offre massima flessibilità mantenendo un'API coerente indipendentemente dall'implementazione HTTP sottostante.
Pronto a superare i tuoi colloqui su Spring Boot?
Pratica con i nostri simulatori interattivi, flashcards e test tecnici.
MockMvcTester per test fluenti
Spring Boot 3.4 introduce MockMvcTester, un'alternativa basata su AssertJ a MockMvc. Questo nuovo approccio rende i test più leggibili ed espressivi.
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvcTester mockMvc; // New class!
@Test
void shouldReturnUserById() {
// Fluent API with 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");
}
}Rispetto all'approccio precedente con MockMvc, le asserzioni sono più concise e il concatenamento risulta più naturale.
@WebMvcTest(UserController.class)
class ComparisonTest {
@Autowired
private MockMvcTester mockMvcTester;
@Autowired
private MockMvc mockMvc;
@Test
void withMockMvcTester() {
// New approach: fluent and 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 {
// Old approach: more verbose
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\": \"Jane\"}"))
.andExpect(status().isCreated())
.andExpect(header().string("Location", "/api/users/2"));
}
}MockMvcTester viene configurato automaticamente quando AssertJ è presente nel classpath (incluso di default con spring-boot-starter-test).
Docker Compose e Testcontainers migliorati
Il supporto Docker Compose guadagna flessibilità con file di configurazione multipli e argomenti personalizzati.
# application.properties
# Use multiple Docker Compose files
spring.docker.compose.file=compose.yaml,compose-dev.yaml
# Pass arguments at startup
spring.docker.compose.start.arguments=--scale redis=2
# Arguments at shutdown
spring.docker.compose.stop.arguments=--timeout 60I nuovi servizi vengono rilevati e configurati automaticamente.
# 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 rileva automaticamente questi servizi e configura le proprietà di connessione corrispondenti.
Per i test con Testcontainers, nuovi container sono supportati.
@TestConfiguration(proxyBeanMethods = false)
public class IntegrationTestConfig {
@Bean
@ServiceConnection
public PostgreSQLContainer<?> postgresContainer() {
return new PostgreSQLContainer<>("postgres:16");
}
@Bean
@ServiceConnection
public RedisStackContainer redisStackContainer() {
// New Redis Stack support
return new RedisStackContainer("redis/redis-stack:latest");
}
@Bean
@ServiceConnection
public LgtmStackContainer observabilityContainer() {
// New Grafana LGTM support (Loki, Grafana, Tempo, Mimir)
return new LgtmStackContainer("grafana/otel-lgtm:latest");
}
}L'annotazione @ServiceConnection configura automaticamente le proprietà di connessione, eliminando la necessità di @DynamicPropertySource nella maggior parte dei casi.
Actuator SSL e osservabilità
Il nuovo endpoint /actuator/info espone ora informazioni sui certificati SSL configurati: date di validità, emittente e soggetto.
# application.properties
# Enable SSL information in actuator
management.info.ssl.enabled=true
# Configure warning threshold for expiring certificates
management.health.ssl.certificate-validity-warning-threshold=30dQuesta funzionalità consente il monitoraggio della scadenza dei certificati direttamente tramite actuator, facilitando l'automazione dei rinnovi.
@Configuration
public class SslMonitoringConfig {
@Bean
public HealthIndicator sslCertificateHealth(SslInfo sslInfo) {
return () -> {
// Custom certificate validity check
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();
};
}
}Per l'osservabilità, il trasporto OTLP ora supporta gRPC oltre a HTTP.
# application.properties
# Use gRPC for OTLP (traces and metrics)
management.otlp.tracing.transport=grpc
management.otlp.tracing.endpoint=http://localhost:4317
# New: group applications together
spring.application.group=payment-servicesIl gruppo applicazione (spring.application.group) consente di raggruppare logicamente più servizi nei dashboard di osservabilità.
Immagini OCI più leggere
Il builder predefinito per le immagini OCI passa da paketobuildpacks/builder-jammy-base a paketobuildpacks/builder-jammy-java-tiny, producendo immagini significativamente più piccole.
tasks.named("bootBuildImage") {
// Native ARM support (new)
imagePlatform = "linux/arm64"
// New security flag
trustBuilder = false
// Image configuration
imageName = "myregistry.com/myapp:${version}"
}Il nuovo parametro imagePlatform semplifica le build multipiattaforma per ARM e x64.
<!-- pom.xml -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<!-- Native ARM support -->
<platform>linux/arm64</platform>
<!-- Builder optimized for minimal images -->
<builder>paketobuildpacks/builder-jammy-java-tiny</builder>
</image>
</configuration>
</plugin>Queste immagini ottimizzate si avviano più velocemente e consumano meno risorse, particolarmente vantaggioso per i deployment su Kubernetes.
Il cambio di builder può influenzare applicazioni che dipendono da determinati strumenti di sistema. Si consiglia di testare le nuove immagini prima del deployment in produzione.
Modifiche alla Bean Validation
Spring Boot 3.4 allinea il comportamento della validazione alla specifica Bean Validation. La validazione non si propaga più automaticamente alle proprietà annidate.
@ConfigurationProperties(prefix = "app")
@Validated
public class AppConfig {
@NotBlank
private String name;
// IMPORTANT: @Valid required to cascade validation
@Valid
private DatabaseConfig database;
// Without @Valid, ServerConfig constraints will NOT be checked
private ServerConfig server;
// Getters and setters
}
public class DatabaseConfig {
@NotBlank
private String url;
@Min(1)
private int poolSize;
// Getters and setters
}
public class ServerConfig {
@NotNull // This constraint will NOT be checked without @Valid on parent
private Integer port;
// Getters and setters
}Questa modifica può influenzare le applicazioni esistenti. Si consiglia di verificare le classi @ConfigurationProperties e aggiungere @Valid dove la validazione deve propagarsi.
Deprecazione di @MockBean e @SpyBean
Le annotazioni @MockBean e @SpyBean di Spring Boot sono deprecate a favore delle nuove annotazioni Mockito.
@SpringBootTest
class UserServiceTest {
// New: native Mockito annotations
@MockitoBean
private UserRepository userRepository;
@MockitoSpyBean
private EmailService emailService;
@Autowired
private UserService userService;
@Test
void shouldCreateUser() {
// Mock configuration
when(userRepository.save(any())).thenReturn(new User(1L, "test@example.com"));
userService.createUser("test@example.com");
// Spy verification
verify(emailService).sendWelcomeEmail("test@example.com");
}
}Le vecchie annotazioni funzionano ancora ma mostrano avvisi di deprecazione. Si consiglia di pianificare la migrazione a @MockitoBean e @MockitoSpyBean.
Inizia a praticare!
Metti alla prova le tue conoscenze con i nostri simulatori di colloquio e test tecnici.
Conclusione
Spring Boot 3.4 offre miglioramenti sostanziali in produttività e osservabilità:
Checklist di migrazione:
- Abilitare il logging strutturato per migliorare l'osservabilità
- Verificare il comportamento del graceful shutdown (ora abilitato per impostazione predefinita)
- Considerare i virtual threads per applicazioni con carico I/O elevato (Java 21+)
- Migrare a MockMvcTester per test più leggibili
- Aggiungere
@Validsulle proprietà@ConfigurationPropertiesannidate - Sostituire
@MockBean/@SpyBeancon@MockitoBean/@MockitoSpyBean - Testare le nuove immagini OCI prima del deployment in produzione
Spring Boot 3.4 consolida la sua posizione come framework di riferimento per lo sviluppo Java moderno, con particolare attenzione agli standard di osservabilità e performance.
Fonti:
Tag
Condividi
Articoli correlati

Domande colloquio Node.js Backend: Guida completa 2026
Le 25 domande più frequenti nei colloqui Node.js backend. Event loop, async/await, stream, clustering e performance spiegate con risposte dettagliate.

Go: Fondamenti per Sviluppatori Java/Python nel 2026
Imparare Go rapidamente sfruttando l'esperienza in Java o Python. Goroutines, channels, interfaces e pattern essenziali per una transizione fluida.

NestJS: Creare una REST API completa da zero
Guida passo dopo passo per costruire una REST API pronta per la produzione con NestJS, TypeScript, Prisma e class-validator. CRUD, validazione, gestione errori e interceptor.