# Spring Boot 3.4: ฟีเจอร์ใหม่ทั้งหมดอธิบายครบถ้วน > Spring Boot 3.4 นำเสนอ structured logging แบบ native, virtual threads ที่ขยายเพิ่ม, graceful shutdown เป็นค่าเริ่มต้น และ MockMvcTester คู่มือฉบับสมบูรณ์ของฟีเจอร์ใหม่ - Published: 2026-01-16 - Updated: 2026-04-10 - Author: SharpSkill - Tags: spring boot, java, spring boot 3.4, spring framework, backend - Reading time: 12 min --- Spring Boot 3.4 เปิดตัวในเดือนพฤศจิกายน 2024 พร้อมการปรับปรุงที่สำคัญด้านประสิทธิภาพการพัฒนาและประสิทธิภาพของแอปพลิเคชัน เวอร์ชันนี้แนะนำ structured logging แบบ native เปิดใช้งาน graceful shutdown เป็นค่าเริ่มต้น และขยายการรองรับ virtual threads ทั่วทั้ง framework > **ข้อกำหนดเบื้องต้น** > > Spring Boot 3.4 ต้องการ Java 17 เป็นขั้นต่ำ และรองรับ Java 21 สำหรับ virtual threads เวอร์ชันนี้ใช้ Spring Framework 6.2 ## Structured logging แบบ native Structured logging ถือเป็นก้าวสำคัญสำหรับ observability ของแอปพลิเคชัน แทนที่จะใช้ log แบบข้อความที่วิเคราะห์ได้ยาก Spring Boot 3.4 สร้าง log ในรูปแบบ JSON ที่สามารถประมวลผลโดยเครื่องมืออย่าง Elasticsearch, Grafana Loki หรือ Datadog สามรูปแบบที่รองรับแบบ native ได้แก่ Elastic Common Schema (ECS), Logstash และ Graylog Extended Log Format (GELF) ```properties # application.properties # Enable structured logging in console logging.structured.format.console=ecs # Or for log files logging.structured.format.file=logstash ``` การตั้งค่าง่ายๆ นี้จะสร้าง structured JSON log โดยอัตโนมัติ ```java // LoggingController.java @RestController @RequestMapping("/api/demo") public class LoggingController { // Logger injection via SLF4J private static final Logger logger = LoggerFactory.getLogger(LoggingController.class); @GetMapping("/action") public ResponseEntity 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 log นี้จะกลายเป็นอ็อบเจกต์ JSON ที่มี timestamp, level, ข้อความ, ชื่อคลาส, thread และ metadata ของแอปพลิเคชัน โครงสร้างนี้ช่วยให้การค้นหาและการรวบรวมข้อมูลบนแพลตฟอร์มการตรวจสอบทำได้ง่ายขึ้น ## Graceful Shutdown เปิดใช้งานเป็นค่าเริ่มต้น การเปลี่ยนแปลงสำคัญ: graceful shutdown เปิดใช้งานเป็นค่าเริ่มต้นแล้ว HTTP request ที่กำลังดำเนินการจะถูกประมวลผลจนเสร็จก่อนที่เซิร์ฟเวอร์จะปิด ป้องกันข้อผิดพลาด 502 ระหว่างการ deploy ```properties # 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 ``` พฤติกรรมนี้ใช้ได้กับ embedded server ทุกตัว: Tomcat, Jetty, Undertow และ Reactor Netty ```java // LifecycleConfig.java @Configuration public class LifecycleConfig { private static final Logger logger = LoggerFactory.getLogger(LifecycleConfig.class); @Bean public ApplicationListener 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. }; } } ``` การปรับปรุงนี้ทำให้การ deploy แบบไม่มี downtime ง่ายขึ้น โดยไม่ต้องตั้งค่าเพิ่มเติมในกรณีส่วนใหญ่ ## การรองรับ Virtual Threads ที่ขยายเพิ่ม Spring Boot 3.4 ขยายการรองรับ virtual threads (Java 21+) ไปยังคอมโพเนนต์มากขึ้น `OtlpMeterRegistry` และเซิร์ฟเวอร์ Undertow ใช้ virtual threads เมื่อเปิดใช้งาน ```properties # application.properties # Enable virtual threads globally spring.threads.virtual.enabled=true ``` property เดียวนี้เปลี่ยนโมเดล threading ของแอปพลิเคชัน HTTP request แต่ละตัวจะได้รับ virtual thread ของตัวเอง ทำให้รองรับการเชื่อมต่อพร้อมกันนับพันได้โดยไม่ทำให้ thread pool หมด ```java // AsyncService.java @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, การ query ฐานข้อมูล, การดำเนินการกับไฟล์ OS thread จะถูกปล่อยระหว่างเวลารอและถูกกำหนดใหม่เมื่อทำงานต่อ > **ความเข้ากันได้** > > Virtual threads ต้องการ Java 21 เป็นขั้นต่ำ บน Java 17 property นี้จะถูกละเว้นและใช้พฤติกรรมแบบดั้งเดิม ## RestClient และ RestTemplate ที่ปรับปรุงแล้ว Spring Boot 3.4 ทำให้การตั้งค่า HTTP client เป็นมาตรฐาน การเลือก `HttpRequestFactory` จะเป็นไปตามลำดับความสำคัญที่ชัดเจนตาม classpath ```java // HttpClientConfig.java @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(); } } ``` การตั้งค่าพฤติกรรม redirect ก็ถูกทำให้ง่ายขึ้นเช่นกัน ```properties # application.properties # Force specific implementation spring.http.client.factory=jdk # Configure redirect behavior spring.http.client.redirects=dont-follow ``` สำหรับการควบคุมที่ละเอียดยิ่งขึ้น `ClientHttpRequestFactoryBuilder` ตัวใหม่ช่วยให้ตั้งค่าแบบ programmatic ได้อย่างสมบูรณ์ ```java // CustomHttpClientConfig.java @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 implementation ตัวใด ## MockMvcTester สำหรับการทดสอบที่ลื่นไหล Spring Boot 3.4 แนะนำ `MockMvcTester` ทางเลือกที่ใช้ AssertJ แทน `MockMvc` แนวทางใหม่นี้ทำให้ test อ่านง่ายขึ้นและแสดงออกได้มากขึ้น ```java // UserControllerTest.java @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` การ assert กระชับขึ้นและการ chain เป็นธรรมชาติมากขึ้น ```java // ComparisonTest.java @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 มีความยืดหยุ่นมากขึ้นด้วยไฟล์การตั้งค่าหลายไฟล์และ argument ที่กำหนดเอง ```properties # 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 ``` service ใหม่จะถูกตรวจจับและตั้งค่าโดยอัตโนมัติ ```yaml # 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 gRPC ``` Spring Boot 3.4 ตรวจจับ service เหล่านี้โดยอัตโนมัติและตั้งค่า property การเชื่อมต่อที่เกี่ยวข้อง สำหรับการทดสอบด้วย Testcontainers มี container ใหม่ที่รองรับ ```java // IntegrationTestConfig.java @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"); } } ``` annotation `@ServiceConnection` ตั้งค่า property การเชื่อมต่อโดยอัตโนมัติ ลดความจำเป็นในการใช้ `@DynamicPropertySource` ในกรณีส่วนใหญ่ ## Actuator SSL และ observability endpoint `/actuator/info` ใหม่แสดงข้อมูลเกี่ยวกับใบรับรอง SSL ที่ตั้งค่าไว้: วันที่หมดอายุ ผู้ออกใบรับรอง และเจ้าของ ```properties # 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 ได้โดยตรง ทำให้การต่ออายุอัตโนมัติทำได้ง่ายขึ้น ```java // SslMonitoringConfig.java @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(); }; } } ``` สำหรับ observability การขนส่ง OTLP รองรับ gRPC นอกเหนือจาก HTTP ```properties # 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`) ช่วยให้จัดกลุ่ม service หลายตัวอย่างมีเหตุผลใน observability dashboard ## OCI image ที่เบาลง ตัวสร้าง OCI image เริ่มต้นเปลี่ยนจาก `paketobuildpacks/builder-jammy-base` เป็น `paketobuildpacks/builder-jammy-java-tiny` ซึ่งสร้าง image ที่เล็กลงอย่างมาก ```groovy // build.gradle tasks.named("bootBuildImage") { // Native ARM support (new) imagePlatform = "linux/arm64" // New security flag trustBuilder = false // Image configuration imageName = "myregistry.com/myapp:${version}" } ``` พารามิเตอร์ `imagePlatform` ใหม่ทำให้การ build ข้ามแพลตฟอร์มสำหรับ ARM และ x64 ง่ายขึ้น ```xml org.springframework.boot spring-boot-maven-plugin linux/arm64 paketobuildpacks/builder-jammy-java-tiny ``` image ที่ถูก optimize เหล่านี้เริ่มต้นเร็วขึ้นและใช้ทรัพยากรน้อยลง เป็นประโยชน์อย่างยิ่งสำหรับการ deploy บน Kubernetes > **หมายเหตุการย้ายระบบ** > > การเปลี่ยน builder อาจส่งผลกระทบต่อแอปพลิเคชันที่พึ่งพาเครื่องมือระบบบางอย่าง ควรทดสอบ image ใหม่ก่อน deploy ไปยัง production ## การเปลี่ยนแปลงใน Bean Validation Spring Boot 3.4 ปรับพฤติกรรมการ validate ให้สอดคล้องกับข้อกำหนด Bean Validation การ validate จะไม่ส่งต่อไปยัง property ที่ซ้อนกันโดยอัตโนมัติอีกต่อไป ```java // ConfigProperties.java @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` ในตำแหน่งที่การ validate ควรส่งต่อ ## การเลิกใช้ @MockBean และ @SpyBean annotation `@MockBean` และ `@SpyBean` ของ Spring Boot ถูกเลิกใช้เพื่อเปลี่ยนไปใช้ annotation ใหม่ของ Mockito ```java // UserServiceTest.java (new approach) @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"); } } ``` annotation เดิมยังใช้งานได้แต่จะแสดงคำเตือนการเลิกใช้ ควรวางแผนย้ายไปใช้ `@MockitoBean` และ `@MockitoSpyBean` ## สรุป Spring Boot 3.4 มอบการปรับปรุงที่สำคัญด้านประสิทธิภาพการพัฒนาและ observability: **รายการตรวจสอบการย้ายระบบ:** - เปิดใช้งาน structured logging เพื่อ observability ที่ดีขึ้น - ตรวจสอบพฤติกรรม graceful shutdown (เปิดใช้งานเป็นค่าเริ่มต้นแล้ว) - พิจารณา virtual threads สำหรับแอปพลิเคชันที่มี I/O สูง (Java 21+) - ย้ายไปใช้ MockMvcTester เพื่อ test ที่อ่านง่ายขึ้น - เพิ่ม `@Valid` บน property `@ConfigurationProperties` ที่ซ้อนกัน - แทนที่ `@MockBean`/`@SpyBean` ด้วย `@MockitoBean`/`@MockitoSpyBean` - ทดสอบ OCI image ใหม่ก่อน deploy ไปยัง production Spring Boot 3.4 เสริมความแข็งแกร่งในฐานะ framework อ้างอิงสำหรับการพัฒนา Java สมัยใหม่ โดยให้ความสำคัญเป็นพิเศษกับมาตรฐาน observability และประสิทธิภาพ **แหล่งข้อมูล:** - [Spring Boot 3.4.0 Release Announcement](https://spring.io/blog/2024/11/21/spring-boot-3-4-0-available-now/) - [Spring Boot 3.4 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.4-Release-Notes) - [Bootiful Spring Boot 3.4](https://spring.io/blog/2024/11/24/bootiful-34-boot/) --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/th/blog/spring-boot/spring-boot-3-4-new-features