Spring Boot 3.4: Усі нововведення детально
Spring Boot 3.4 приносить нативне структуроване логування, розширені virtual threads, graceful shutdown за замовчуванням та MockMvcTester. Повний огляд нових можливостей.

Spring Boot 3.4, випущений у листопаді 2024 року, надає значні покращення в продуктивності розробників та швидкодії додатків. Ця версія впроваджує нативне структуроване логування, активує graceful shutdown за замовчуванням та розширює підтримку virtual threads у всьому фреймворку.
Spring Boot 3.4 вимагає мінімум Java 17 та підтримує Java 21 для virtual threads. Ця версія використовує Spring Framework 6.2.
Нативне структуроване логування
Структуроване логування являє собою важливий крок вперед для спостережуваності додатків. Замість текстових логів, які важко аналізувати, Spring Boot 3.4 генерує логи у форматі JSON, придатні для обробки інструментами на кшталт Elasticsearch, Grafana Loki чи Datadog.
Три формати підтримуються нативно: Elastic Common Schema (ECS), Logstash та 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=logstashЦя проста конфігурація автоматично генерує форматовані структуровані JSON-логи.
@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");
}
}При увімкненому форматі ECS цей лог перетворюється на JSON-об'єкт, що містить timestamp, рівень, повідомлення, назву класу, потік та метадані додатку. Така структура спрощує пошук та агрегацію на платформах моніторингу.
Graceful Shutdown увімкнений за замовчуванням
Важлива зміна: graceful shutdown тепер увімкнений за замовчуванням. Поточні HTTP-запити обробляються перед зупинкою сервера, що запобігає помилкам 502 під час розгортання.
# 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=45sЦя поведінка застосовується до всіх вбудованих серверів: Tomcat, Jetty, Undertow та 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.
};
}
}Це покращення спрощує реалізацію розгортань без простою, без потреби додаткової конфігурації у більшості випадків.
Розширена підтримка Virtual Threads
Spring Boot 3.4 розширює підтримку virtual threads (Java 21+) на більшу кількість компонентів. OtlpMeterRegistry та сервер Undertow тепер використовують virtual threads при їх активації.
# application.properties
# Enable virtual threads globally
spring.threads.virtual.enabled=trueЦя єдина властивість трансформує модель потоків додатку. Кожен HTTP-запит отримує власний virtual 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);
}
}Virtual threads демонструють найкращі результати у додатках з інтенсивним I/O: HTTP-виклики, запити до баз даних, файлові операції. Потік операційної системи звільняється під час очікування та повторно призначається при відновленні.
Virtual threads вимагають мінімум Java 21. На Java 17 ця властивість ігнорується і застосовується класична поведінка.
Покращений RestClient та RestTemplate
Spring Boot 3.4 нормалізує конфігурацію HTTP-клієнта. Вибір HttpRequestFactory тепер дотримується чіткої послідовності на основі 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();
}
}Конфігурація поведінки перенаправлень також спрощена.
# application.properties
# Force specific implementation
spring.http.client.factory=jdk
# Configure redirect behavior
spring.http.client.redirects=dont-followДля більш детального контролю новий ClientHttpRequestFactoryBuilder дозволяє повну програмну конфігурацію.
@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();
}
}Цей підхід забезпечує максимальну гнучкість зі збереженням консистентного API незалежно від базової HTTP-реалізації.
Готовий до співбесід з Spring Boot?
Практикуйся з нашими інтерактивними симуляторами, flashcards та технічними тестами.
MockMvcTester для зручного тестування
Spring Boot 3.4 представляє MockMvcTester, альтернативу MockMvc на основі AssertJ. Цей новий підхід робить тести більш читабельними та виразними.
@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");
}
}Порівняно з попереднім підходом із MockMvc, перевірки стали більш лаконічними, а ланцюжки виглядають природніше.
@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 автоматично налаштовується, коли AssertJ присутній у classpath (за замовчуванням включений у spring-boot-starter-test).
Покращений Docker Compose та Testcontainers
Підтримка Docker Compose набуває гнучкості завдяки кільком файлам конфігурації та користувацьким аргументам.
# 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 60Нові сервіси автоматично виявляються та налаштовуються.
# 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 автоматично виявляє ці сервіси та налаштовує відповідні властивості з'єднання.
Для тестування з Testcontainers підтримуються нові контейнери.
@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");
}
}Анотація @ServiceConnection автоматично налаштовує властивості з'єднання, усуваючи потребу в @DynamicPropertySource у більшості випадків.
Actuator SSL та спостережуваність
Новий endpoint /actuator/info тепер надає інформацію про налаштовані SSL-сертифікати: дати дійсності, видавець та суб'єкт.
# 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=30dЦя функціональність дозволяє моніторити закінчення терміну дії сертифікатів безпосередньо через actuator, полегшуючи автоматизацію оновлення.
@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();
};
}
}Для спостережуваності OTLP-транспорт тепер підтримує gRPC на додаток до 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-servicesГрупа додатків (spring.application.group) дозволяє логічно групувати кілька сервісів у дашбордах спостережуваності.
Легші OCI-образи
Стандартний OCI-білдер образів змінюється з paketobuildpacks/builder-jammy-base на paketobuildpacks/builder-jammy-java-tiny, створюючи значно менші образи.
tasks.named("bootBuildImage") {
// Native ARM support (new)
imagePlatform = "linux/arm64"
// New security flag
trustBuilder = false
// Image configuration
imageName = "myregistry.com/myapp:${version}"
}Новий параметр imagePlatform спрощує кросплатформну збірку для ARM та 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>Ці оптимізовані образи запускаються швидше та споживають менше ресурсів, що особливо корисно для розгортань у Kubernetes.
Зміна білдера може вплинути на додатки, які залежать від певних системних інструментів. Нові образи слід протестувати перед розгортанням у продакшен.
Зміни в Bean Validation
Spring Boot 3.4 узгоджує поведінку валідації зі специфікацією Bean Validation. Валідація більше не каскадується автоматично до вкладених властивостей.
@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
}Ця зміна може вплинути на існуючі додатки. Слід перевірити класи @ConfigurationProperties та додати @Valid там, де валідація має каскадуватися.
Застарівання @MockBean та @SpyBean
Анотації @MockBean та @SpyBean у Spring Boot позначені як застарілі на користь нових анотацій 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");
}
}Старі анотації все ще працюють, але показують попередження про застарівання. Варто запланувати міграцію на @MockitoBean та @MockitoSpyBean.
Починай практикувати!
Перевір свої знання з нашими симуляторами співбесід та технічними тестами.
Висновок
Spring Boot 3.4 надає суттєві покращення в продуктивності та спостережуваності:
Контрольний список міграції:
- Увімкнути структуроване логування для покращення спостережуваності
- Перевірити поведінку graceful shutdown (тепер увімкнений за замовчуванням)
- Розглянути virtual threads для додатків з інтенсивним I/O (Java 21+)
- Мігрувати на MockMvcTester для більш читабельних тестів
- Додати
@Validна вкладені властивості@ConfigurationProperties - Замінити
@MockBean/@SpyBeanна@MockitoBean/@MockitoSpyBean - Протестувати нові OCI-образи перед розгортанням у продакшен
Spring Boot 3.4 зміцнює свою позицію як еталонний фреймворк для сучасної Java-розробки, з особливою увагою до стандартів спостережуваності та продуктивності.
Джерела:
Теги
Поділитися
Пов'язані статті

Питання на співбесіді з Node.js Backend: Повний посібник 2026
25 найпоширеніших питань на співбесіді з Node.js backend. Event loop, async/await, потоки, кластеризація та продуктивність з детальними відповідями.

Go: Основи для Java/Python-розробників у 2026 році
Швидке вивчення Go з використанням досвіду Java або Python. Goroutines, channels, інтерфейси та основні патерни для плавного переходу.

NestJS: Створення повноцінного REST API
Повний посібник зі створення професійного REST API з NestJS. Контролери, сервіси, модулі, валідація з class-validator та обробка помилок з практичними прикладами.