Spring Boot 3.4: ฟีเจอร์ใหม่ทั้งหมดอธิบายครบถ้วน
Spring Boot 3.4 นำเสนอ structured logging แบบ native, virtual threads ที่ขยายเพิ่ม, graceful shutdown เป็นค่าเริ่มต้น และ MockMvcTester คู่มือฉบับสมบูรณ์ของฟีเจอร์ใหม่

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)
# application.properties
# Enable structured logging in console
logging.structured.format.console=ecs
# Or for log files
logging.structured.format.file=logstashการตั้งค่าง่ายๆ นี้จะสร้าง structured JSON log โดยอัตโนมัติ
@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 log นี้จะกลายเป็นอ็อบเจกต์ JSON ที่มี timestamp, level, ข้อความ, ชื่อคลาส, thread และ metadata ของแอปพลิเคชัน โครงสร้างนี้ช่วยให้การค้นหาและการรวบรวมข้อมูลบนแพลตฟอร์มการตรวจสอบทำได้ง่ายขึ้น
Graceful Shutdown เปิดใช้งานเป็นค่าเริ่มต้น
การเปลี่ยนแปลงสำคัญ: graceful shutdown เปิดใช้งานเป็นค่าเริ่มต้นแล้ว HTTP request ที่กำลังดำเนินการจะถูกประมวลผลจนเสร็จก่อนที่เซิร์ฟเวอร์จะปิด ป้องกันข้อผิดพลาด 502 ระหว่างการ deploy
# 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
@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.
};
}
}การปรับปรุงนี้ทำให้การ deploy แบบไม่มี downtime ง่ายขึ้น โดยไม่ต้องตั้งค่าเพิ่มเติมในกรณีส่วนใหญ่
การรองรับ Virtual Threads ที่ขยายเพิ่ม
Spring Boot 3.4 ขยายการรองรับ virtual threads (Java 21+) ไปยังคอมโพเนนต์มากขึ้น OtlpMeterRegistry และเซิร์ฟเวอร์ Undertow ใช้ virtual threads เมื่อเปิดใช้งาน
# application.properties
# Enable virtual threads globally
spring.threads.virtual.enabled=trueproperty เดียวนี้เปลี่ยนโมเดล threading ของแอปพลิเคชัน HTTP request แต่ละตัวจะได้รับ virtual thread ของตัวเอง ทำให้รองรับการเชื่อมต่อพร้อมกันนับพันได้โดยไม่ทำให้ thread pool หมด
@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
@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 ก็ถูกทำให้ง่ายขึ้นเช่นกัน
# application.properties
# Force specific implementation
spring.http.client.factory=jdk
# Configure redirect behavior
spring.http.client.redirects=dont-followสำหรับการควบคุมที่ละเอียดยิ่งขึ้น ClientHttpRequestFactoryBuilder ตัวใหม่ช่วยให้ตั้งค่าแบบ programmatic ได้อย่างสมบูรณ์
@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 ตัวใด
พร้อมที่จะพิชิตการสัมภาษณ์ Spring Boot แล้วหรือยังครับ?
ฝึกฝนด้วยตัวจำลองแบบโต้ตอบ, flashcards และแบบทดสอบเทคนิคครับ
MockMvcTester สำหรับการทดสอบที่ลื่นไหล
Spring Boot 3.4 แนะนำ MockMvcTester ทางเลือกที่ใช้ AssertJ แทน MockMvc แนวทางใหม่นี้ทำให้ test อ่านง่ายขึ้นและแสดงออกได้มากขึ้น
@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 เป็นธรรมชาติมากขึ้น
@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 ที่กำหนดเอง
# 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 60service ใหม่จะถูกตรวจจับและตั้งค่าโดยอัตโนมัติ
# 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 ตรวจจับ service เหล่านี้โดยอัตโนมัติและตั้งค่า property การเชื่อมต่อที่เกี่ยวข้อง
สำหรับการทดสอบด้วย Testcontainers มี container ใหม่ที่รองรับ
@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 ที่ตั้งค่าไว้: วันที่หมดอายุ ผู้ออกใบรับรอง และเจ้าของ
# 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();
};
}
}สำหรับ observability การขนส่ง 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) ช่วยให้จัดกลุ่ม service หลายตัวอย่างมีเหตุผลใน observability dashboard
OCI image ที่เบาลง
ตัวสร้าง OCI image เริ่มต้นเปลี่ยนจาก paketobuildpacks/builder-jammy-base เป็น paketobuildpacks/builder-jammy-java-tiny ซึ่งสร้าง image ที่เล็กลงอย่างมาก
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 ง่ายขึ้น
<!-- 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>image ที่ถูก optimize เหล่านี้เริ่มต้นเร็วขึ้นและใช้ทรัพยากรน้อยลง เป็นประโยชน์อย่างยิ่งสำหรับการ deploy บน Kubernetes
การเปลี่ยน builder อาจส่งผลกระทบต่อแอปพลิเคชันที่พึ่งพาเครื่องมือระบบบางอย่าง ควรทดสอบ image ใหม่ก่อน deploy ไปยัง production
การเปลี่ยนแปลงใน Bean Validation
Spring Boot 3.4 ปรับพฤติกรรมการ validate ให้สอดคล้องกับข้อกำหนด Bean Validation การ validate จะไม่ส่งต่อไปยัง property ที่ซ้อนกันโดยอัตโนมัติอีกต่อไป
@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
@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 และประสิทธิภาพ
แหล่งข้อมูล:
แท็ก
แชร์
บทความที่เกี่ยวข้อง

คำถามสัมภาษณ์ Backend Node.js: คู่มือฉบับสมบูรณ์ 2026
25 คำถามสัมภาษณ์ Backend Node.js ที่พบบ่อยที่สุด Event loop, async/await, streams, clustering และประสิทธิภาพอธิบายพร้อมคำตอบโดยละเอียด

Go: พื้นฐานสำหรับนักพัฒนา Java/Python ในปี 2026
เรียนรู้ Go อย่างรวดเร็วโดยใช้ประสบการณ์จาก Java หรือ Python Goroutine, channel, interface และ pattern สำคัญสำหรับการเปลี่ยนผ่านอย่างราบรื่น

NestJS: สร้าง REST API ที่สมบูรณ์ตั้งแต่เริ่มต้น
คู่มือฉบับสมบูรณ์สำหรับการสร้าง REST API ระดับมืออาชีพด้วย NestJS ครอบคลุม Controller, Service, Module, การตรวจสอบข้อมูลด้วย class-validator และการจัดการข้อผิดพลาด