告別舊版本!帶你玩轉 Java 23、Spring Boot 3.3.4 與 Jakarta 10
在現代應用開發中,微服務架構與云原生設計已成為行業的主流方向。為了應對日益復雜的業務場景,開發者們需要一個既簡潔又強大的基礎模板,能夠在保證可維護性和可擴展性的同時,加速項目的落地。
本文將帶你深入理解一個基于 Java 23、Spring Boot 3.3.4 與 Jakarta 10 打造的快速啟動工程,它采用了 六邊形架構(Hexagonal Architecture),并集成了 JWT 安全認證、日志統一管理、Spring Profiles 環境切換、Docker 容器化部署 等關鍵特性,幫助開發團隊輕松應對 微服務與云原生應用開發的挑戰。
模板核心特性概覽
這個工程模板的設計目標是:清晰分層、易于擴展、貼合微服務場景。其關鍵特性包括:
- 六邊形架構(Ports & Adapters):核心業務邏輯與外部實現解耦,保證代碼高內聚、低耦合。
- AOP 切面編程:統一處理日志、異常、安全校驗等橫切關注點。
- JWT 認證與授權:通過令牌機制實現安全訪問控制。
- 完善的安全機制:請求與響應全流程攔截與校驗。
- 日志體系:支持文件滾動、統一日志格式與關鍵事件記錄。
- 多環境配置:內置 dev、staging、prod 三套配置,開發環境使用 H2,測試/生產使用 PostgreSQL。
- Docker 容器化:內置構建與測試腳本,便于云端部署與集成。
六邊形架構簡介
六邊形架構(Hexagonal Architecture),又稱 端口與適配器模式,由 Alistair Cockburn 在 2005 年提出。它的核心思想是:
- Domain/Core Logic(核心領域邏輯):不依賴外部系統,只關注業務規則。
- Ports(端口):定義交互契約,區分輸入(驅動端口)與輸出(被驅動端口)。
- Adapters(適配器):具體實現端口,負責數據庫、消息隊列、外部 API 等集成。
這種架構模式特別適合微服務,因為它能讓服務保持 模塊化、易擴展、可替換技術棧。
目錄結構與包劃分
/src/main/java/com/icoderoad/ms-vanilla
├── adapters # 外部適配層(REST 接口、Repository、AOP 過濾器)
├── domain # 領域層(接口、實體、異常定義)
├── server # 服務配置層(數據庫、緩存、消息隊列配置)
├── security # 安全認證層(JWT、簽名、加密組件)
├── utils # 工具類封裝(日期、校驗、字符串處理)
└── ServiceBootStrap.java # 啟動入口服務啟動與環境配置
package com.icoderoad.msvanilla;
@SpringBootApplication
public class ServiceBootStrap {
public static void main(String[] args) {
SpringApplication.run(ServiceBootStrap.class, args);
}
}- 啟動時會根據 spring.profiles.active 加載對應配置:
application-dev.yml → H2 內存數據庫
application-staging.yml → PostgreSQL
application-prod.yml → PostgreSQL
Swagger + OpenAPI 集成:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.6.0</version>
</dependency>API 分組配置:
@Bean
public GroupedOpenApi productApi() {
return GroupedOpenApi.builder()
.group("product-service")
.pathsToMatch("/api/v1/product/**")
.build();
}訪問接口文檔:http://localhost:9334/ms-vanilla/api/v1/swagger-ui/index.html
示例:產品接口 ProductController
package com.icoderoad.msvanilla.adapters.controller;
@RestController
@RequestMapping("${service.api.path}/product")
@Tag(name = "Product API", description = "產品查詢、創建、啟用/停用、刪除與更新")
public class ProductController {
@Operation(summary = "通過 UUID 獲取產品狀態")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "成功返回產品狀態"),
@ApiResponse(responseCode = "400", description = "無效的產品 ID")
})
@GetMapping("/status/{productId}")
public ResponseEntity<StandardResponse> getProductStatus(
@PathVariable UUID productId) {
ProductEntity product = productService.getProductById(productId);
return ResponseEntity.ok(StandardResponse.success(product));
}
}擴展:異常處理、日志、JWT 安全與過濾器
統一異常處理(GlobalExceptionHandler)
package com.icoderoad.msvanilla.adapters.exception;
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<StandardResponse> handleNotFound(EntityNotFoundException ex) {
log.error("Entity not found: {}", ex.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(StandardResponse.error("NOT_FOUND", ex.getMessage()));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<StandardResponse> handleGeneric(Exception ex) {
log.error("Unexpected error: ", ex);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(StandardResponse.error("INTERNAL_ERROR", "服務器內部錯誤"));
}
}統一日志攔截(AOP)
package com.icoderoad.msvanilla.adapters.aop;
@Aspect
@Component
public class LoggingAspect {
private static final Logger log = LoggerFactory.getLogger(LoggingAspect.class);
@Pointcut("execution(* com.icoderoad.msvanilla.adapters.controller..*(..))")
public void controllerMethods() {}
@Around("controllerMethods()")
public Object logController(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
log.info("調用方法: {} 參數: {}", joinPoint.getSignature(), Arrays.toString(joinPoint.getArgs()));
Object result = joinPoint.proceed();
log.info("方法 {} 執行完成,耗時: {}ms", joinPoint.getSignature(), System.currentTimeMillis() - start);
return result;
}
}JWT 工具類
package com.icoderoad.msvanilla.security;
@Component
public class JwtUtil {
private static final String SECRET_KEY = "ChangeThisSecretKey";
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setExpiration(Date.from(Instant.now().plus(1, ChronoUnit.HOURS)))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public String extractUsername(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY)
.parseClaimsJws(token).getBody().getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
return true;
} catch (JwtException e) {
return false;
}
}
}JWT 過濾器
package com.icoderoad.msvanilla.security;
@Component
public class JwtFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
if (jwtUtil.validateToken(token)) {
String username = jwtUtil.extractUsername(token);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(username, null, List.of());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(request, response);
}
}Spring Security 配置
package com.icoderoad.msvanilla.security;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private JwtFilter jwtFilter;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/v1/auth/**").permitAll()
.anyRequest().authenticated())
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
}結論
在 Java 23、Spring Boot 3.3.4 與 Jakarta 10 的加持下,這一快速啟動模板不僅在工程結構上體現了 六邊形架構的優雅設計,還通過 統一異常處理、日志體系、JWT 安全認證與過濾器機制,打造了一個 可擴展、可維護、適合云原生環境 的微服務工程。
未來,隨著更多微服務的加入,團隊能夠在不破壞核心邏輯的前提下,靈活替換數據庫、消息隊列、認證機制等外部實現,從而真正做到 技術無關、業務驅動。
這不僅是一份模板,更是一份現代化應用開發的 最佳實踐指南。




























