背景

本文是《JavaEE 后端从小白到大神》修仙系列第十一篇,正式进入JavaEE后端世界。若想详细学习请点击首篇博文,我们开始吧。

第十一篇:Jakarta EE 9+ 现代化与云原生转型

  • JavaEE → Jakarta EE 的迁移;
  • MicroProfile 标准;
  • 配置管理(Config API)、健康检查、容错(Fault Tolerance);
  • 与 Docker / Kubernetes 集成;
  • REST + CDI + JPA 的轻量级微服务架构;
  • 与 Spring Boot / Quarkus / Helidon 的对比。

一、JavaEE → Jakarta EE 的迁移

1. 为什么需要迁移

2017 年,Oracle 将 Java EE 移交给 Eclipse 基金会,标志着 Java 企业级技术进入了一个新的时代。由于 Oracle 保留了 javax.* 包名的所有权,Eclipse 基金会无法在新的开发中使用它,因此从 Jakarta EE 9 开始,所有的 API 都迁移到了 jakarta.* 命名空间下。

一句话总结:Jakarta EE 9 完成了一次“大爆炸式重命名”——将所有 javax.* 企业级包重命名为 jakarta.*

2. 命名空间迁移的影响

这次迁移是彻底且不可逆的。它影响了 Jakarta EE 体系中的每一个 API:

原 javax 包 新 jakarta 包 对应规范
javax.servlet jakarta.servlet Servlet
javax.persistence jakarta.persistence JPA
javax.ejb jakarta.ejb EJB
javax.inject jakarta.inject CDI/依赖注入
javax.jms jakarta.jms JMS
javax.ws.rs jakarta.ws.rs JAX-RS
javax.transaction jakarta.transaction JTA
javax.validation jakarta.validation Bean Validation

这意味着每一个 import 语句、每一个注解、每一个部署描述符,都必须从 javax.* 迁移到 jakarta.*

3. 版本演进路线图

版本 发布时间 关键变化
Java EE 8 2017 最后一个使用 javax.* 命名空间的版本
Jakarta EE 8 2019 内容与 Java EE 8 相同,仅更换了品牌名
Jakarta EE 9 2020 重大变更:所有 javax.*jakarta.*
Jakarta EE 9.1 2021 适配 Java SE 11
Jakarta EE 10 2022 新增 API 版本(Servlet 6.0、JPA 3.1、CDI 4.0)
Jakarta EE 11 2025 支持 Java SE 21、新增 Jakarta Data 规范
Jakarta EE 12 开发中 进入“数据时代”,查询、数据访问成为一等公民

4. 迁移实战指南

4.1 依赖版本对照

规范 Java EE 8(javax) Jakarta EE 10(jakarta)
Servlet 4.0.x 6.0.x
JPA 2.2.x 3.1.x
CDI 2.0.x 4.0.x
JAX-RS 2.1.x 3.1.x
Bean Validation 2.0.x 3.0.x

Maven 依赖示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!-- Jakarta EE 10 依赖(Tomcat 10+ / WildFly 27+) -->
<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.0.0</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>jakarta.persistence</groupId>
    <artifactId>jakarta.persistence-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

4.2 Tomcat 版本的兼容性

命名空间变更直接影响了 Tomcat 的版本选择:

Tomcat 版本 支持的命名空间 对应规范
Tomcat 9 及更早 javax.* Java EE 8
Tomcat 10 及更新 jakarta.* Jakarta EE 9+

关键规则

  • 使用 javax.* 依赖的应用只能部署在 Tomcat 9 或更早版本;
  • 使用 jakarta.* 依赖的应用必须部署在 Tomcat 10 或更新版本;
  • Jakarta EE API 依赖应标记为 provided 作用域,由容器在运行时提供。

4.3 迁移检查清单

检查项 说明
✅ 更新所有 Maven/Gradle 依赖 使用 Jakarta EE 10+ 版本的 API
✅ 全局替换 import 语句 javax.*jakarta.*
✅ 更新注解包名 @javax.ws.rs.Path@jakarta.ws.rs.Path
✅ 更新部署描述符 web.xmlbeans.xmlejb-jar.xml 中的命名空间
✅ 更新配置文件 persistence.xml 中的命名空间
✅ 确认容器版本 Tomcat 10+ / WildFly 27+ / Payara 6+
✅ 升级 Java 版本 Jakarta EE 10 要求 Java SE 11+

二、MicroProfile 标准

1. 什么是 MicroProfile

MicroProfile 是一个开源的社区项目,旨在为 Java 微服务开发提供一套可移植的、标准化的 API 集合。它基于 Jakarta EE 的核心规范(如 CDI、JAX-RS、JSON-B),并在此基础上增加了云原生微服务所需的关键能力。

一句话总结:MicroProfile = Jakarta EE 的微服务扩展,让标准化的 Java 企业技术也能构建云原生微服务。

2. MicroProfile 的演进

MicroProfile 采用火车模型(Train Model) 发布,每年发布多个平台版本:

版本 发布时间 关键变化
MicroProfile 1.0 2016 初始版本
MicroProfile 3.0 2019 基于 Java EE 8
MicroProfile 5.0 2021 基于 Jakarta EE 9/10
MicroProfile 6.0 / 6.1 2024 完善云原生能力
MicroProfile 7.0 2024 重大更新
MicroProfile 7.1 2025年6月 最新版本

3. MicroProfile 7.1 核心规范

MicroProfile 7.1 包含以下核心组件规范:

规范 版本 功能
MicroProfile Config 3.1 外部化配置管理
MicroProfile Fault Tolerance 4.1 容错模式(重试、熔断、超时、回退)
MicroProfile Health 4.0 健康检查端点(就绪/存活)
MicroProfile JWT Authentication 2.1 JWT 认证
MicroProfile OpenAPI 4.1 OpenAPI v3.1 文档生成
MicroProfile Telemetry 2.1 可观测性(追踪、指标、日志)
MicroProfile Rest Client 4.0 类型安全的 REST 客户端

此外,MicroProfile 7.1 基于 Jakarta EE 10 Core Profile,包含 CDI Lite、RESTful Web Services、JSON-B/P、拦截器等核心规范。

4. MicroProfile 的设计哲学

MicroProfile 的设计遵循以下原则:

  • 无厂商锁定:任何通过认证的实现都保证代码可移植性和运行时互操作性;
  • 注解优先:提供注解驱动的 API,减少样板代码;
  • 云原生聚焦:专注于 Kubernetes、容器化部署所需的特性;
  • 社区驱动:开源社区协作,快速迭代。

5. MicroProfile 实现

主流 Jakarta EE 应用服务器和框架都提供了 MicroProfile 实现:

实现 说明
Open Liberty IBM 开源,MicroProfile 7.1 的初始兼容实现
WildFly Red Hat 出品,完整支持 MicroProfile
Payara 完整支持 MicroProfile
Quarkus 云原生 Java 框架,支持 MicroProfile 规范
Helidon Oracle 出品,支持 MicroProfile

三、MicroProfile 核心规范详解

1. MicroProfile Config——配置管理

1.1 核心作用

MicroProfile Config 提供了统一的配置访问 API,支持从多种配置源(环境变量、application.propertiesapplication.yaml、系统属性等)加载配置。

1.2 使用示例

获取配置值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import jakarta.inject.Inject;

@ApplicationScoped
public class ProductService {
    
    // 方式1:字段注入
    @Inject
    @ConfigProperty(name = "products.cache.enabled", defaultValue = "true")
    private boolean cacheEnabled;
    
    // 方式2:构造方法注入
    @Inject
    public ProductService(@ConfigProperty(name = "products.max.size") int maxSize) {
        this.maxSize = maxSize;
    }
    
    // 方式3:通过 Config API 获取
    @Inject
    private Config config;
    
    public String getDatabaseUrl() {
        return config.getValue("db.url", String.class);
    }
}

配置文件(application.yaml)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
mp:
  config:
    profile: dev

products:
  cacheEnabled: true
  maxSize: 100

db:
  url: jdbc:mysql://localhost:3306/mydb

health:
  liveness:
    path: /health/live
  readiness:
    path: /health/ready

2. MicroProfile Health——健康检查

2.1 核心作用

MicroProfile Health 提供了标准化的健康检查端点,与 Kubernetes 的存活探针(Liveness Probe)和就绪探针(Readiness Probe)无缝集成。

2.2 使用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Liveness;
import org.eclipse.microprofile.health.Readiness;
import jakarta.enterprise.context.ApplicationScoped;

// 存活检查:应用是否还在运行
@Liveness
@ApplicationScoped
public class LivenessCheck implements HealthCheck {
    
    @Override
    public HealthCheckResponse call() {
        return HealthCheckResponse.named("app-liveness")
                .up()  // 正常运行
                .build();
    }
}

// 就绪检查:应用是否可以接收请求
@Readiness
@ApplicationScoped
public class ReadinessCheck implements HealthCheck {
    
    @Inject
    private DatabaseService dbService;
    
    @Override
    public HealthCheckResponse call() {
        boolean dbReady = dbService.isConnected();
        return HealthCheckResponse.named("db-readiness")
                .status(dbReady)
                .withData("db.connected", dbReady)
                .build();
    }
}

端点访问

  • /health/live:存活检查
  • /health/ready:就绪检查

3. MicroProfile Fault Tolerance——容错机制

3.1 核心作用

MicroProfile Fault Tolerance 提供了声明式的容错模式,通过注解即可实现重试、超时、熔断、回退等能力。

3.2 使用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import org.eclipse.microprofile.faulttolerance.Retry;
import org.eclipse.microprofile.faulttolerance.Timeout;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.List;

@ApplicationScoped
public class ProductService {
    
    // 1. 重试 + 超时 + 回退
    @Retry(maxRetries = 3, delay = 1000, maxDuration = 5000)
    @Timeout(2000)
    @Fallback(fallbackMethod = "fallbackProducts")
    public List<Product> getAllProducts() {
        return fetchFromDatabase();
    }
    
    public List<Product> fallbackProducts() {
        return List.of(new Product("default", "Fallback product"));
    }
    
    // 2. 熔断器
    @CircuitBreaker(
        requestVolumeThreshold = 10,   // 10次请求后开始统计
        failureRatio = 0.5,            // 失败率超过50%则打开
        delay = 5000,                  // 5秒后尝试半开
        successThreshold = 2           // 连续成功2次则关闭
    )
    public Product getProductById(Long id) {
        return externalService.fetchProduct(id);
    }
}

4. MicroProfile Rest Client——类型安全 REST 客户端

4.1 核心作用

MicroProfile Rest Client 提供了声明式的 REST 客户端,通过接口和注解即可调用远程 REST 服务。

4.2 使用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 1. 定义 REST 客户端接口
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/api/users")
@RegisterRestClient(configKey = "user-service")
public interface UserServiceClient {
    
    @GET
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    User getUser(@PathParam("id") Long id);
    
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    List<User> getAllUsers();
}

// 2. 注入并使用客户端
@ApplicationScoped
public class OrderService {
    
    @Inject
    @RestClient
    private UserServiceClient userClient;
    
    public void processOrder(Order order) {
        User user = userClient.getUser(order.getUserId());
        // 处理订单...
    }
}

// 3. 配置文件(application.yaml)
user-service:
  mp-rest:
    url: http://user-service:8080
    connectTimeout: 5000
    readTimeout: 3000

5. MicroProfile Telemetry——可观测性

MicroProfile Telemetry 基于 OpenTelemetry 标准,提供分布式追踪、指标和日志的统一 API。它让微服务架构中的可观测性变得标准化和可移植。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import org.eclipse.microprofile.telemetry.Telemetry;
import jakarta.inject.Inject;

@ApplicationScoped
public class OrderProcessor {
    
    @Inject
    private Telemetry telemetry;
    
    public void process(Order order) {
        // Telemetry 自动注入追踪上下文
        // 所有下游调用自动关联追踪信息
        // ...
    }
}

6. MicroProfile OpenAPI——API 文档

MicroProfile OpenAPI 自动从 JAX-RS 注解生成 OpenAPI v3.1 文档:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;

@Path("/products")
public class ProductResource {
    
    @GET
    @Operation(summary = "获取所有产品", description = "返回产品列表")
    @APIResponse(responseCode = "200", description = "成功返回产品列表")
    public List<Product> listProducts() {
        // ...
    }
}

端点 /openapi 自动生成 OpenAPI 文档,可用于 Swagger UI 等工具。

四、与 Docker / Kubernetes 集成

1. 容器化部署的优势

将 Jakarta EE 应用容器化部署到 Kubernetes,可以获得以下优势:

  • 标准化交付:Docker 镜像确保环境一致性;
  • 弹性伸缩:Kubernetes 根据负载自动扩缩容;
  • 自愈能力:健康检查失败时自动重启;
  • 服务发现:Kubernetes Service 实现服务注册与发现;
  • 滚动更新:零停机发布。

2. Dockerfile 示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 使用 WildFly 基础镜像
FROM quay.io/wildfly/wildfly:latest

# 设置环境变量
ENV WILDFLY_USER=admin
ENV WILDFLY_PASS=admin123

# 复制部署包
COPY target/myapp.war /opt/jboss/wildfly/standalone/deployments/

# 复制自定义配置
COPY standalone.xml /opt/jboss/wildfly/standalone/configuration/

# 暴露端口
EXPOSE 8080 9990

# 启动 WildFly
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-bmanagement", "0.0.0.0"]

构建和推送

1
2
3
docker build -t myapp:1.0.0 .
docker tag myapp:1.0.0 myregistry/myapp:1.0.0
docker push myregistry/myapp:1.0.0

3. Kubernetes 部署清单

Deployment(部署配置):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
  labels:
    app: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myregistry/myapp:1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: DB_URL
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: url
        - name: DB_USERNAME
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: username
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        # 存活探针(使用 MicroProfile Health 端点)
        livenessProbe:
          httpGet:
            path: /health/live
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        # 就绪探针
        readinessProbe:
          httpGet:
            path: /health/ready
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5

Service(服务暴露):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer

4. 与 MicroProfile Health 的集成

Kubernetes 的存活探针和就绪探针可以直接使用 MicroProfile Health 提供的端点:

Kubernetes 探针 MicroProfile Health 端点 作用
livenessProbe /health/live 检查应用是否存活(死锁、死循环等)
readinessProbe /health/ready 检查应用是否可以接收流量(依赖服务是否就绪)

5. 配置外部化(ConfigMap + Secret)

通过 Kubernetes ConfigMap 和 Secret 管理配置,实现环境隔离:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# ConfigMap(非敏感配置)
apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-config
data:
  application.yaml: |
    products:
      cacheEnabled: true
      maxSize: 100
    health:
      liveness:
        path: /health/live    

# Secret(敏感配置)
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  url: amRiYzpteXNxbDovL2RiOjMzMDYvbXlkYg==  # base64 编码
  username: cm9vdA==
  password: cGFzc3dvcmQ=

五、REST + CDI + JPA 的轻量级微服务架构

1. 架构概述

Jakarta EE + MicroProfile 可以构建轻量级、标准化的微服务架构,核心组件组合为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌─────────────────────────────────────────────────────────────┐
│                    客户端(浏览器/API调用)                  │
└──────────────────────────┬──────────────────────────────────┘
                           │ HTTP/REST
┌─────────────────────────────────────────────────────────────┐
│              JAX-RS(资源层——REST API)                     │
│              @Path、@GET、@POST、@Produces                  │
└──────────────────────────┬──────────────────────────────────┘
                           │ @Inject
┌─────────────────────────────────────────────────────────────┐
│              CDI(业务层——依赖注入)                        │
│              @ApplicationScoped、@Inject、@Named            │
└──────────────────────────┬──────────────────────────────────┘
                           │ JPA
┌─────────────────────────────────────────────────────────────┐
│              JPA(持久化层——数据访问)                      │
│              @Entity、EntityManager、JPQL                   │
└──────────────────────────┬──────────────────────────────────┘
                           │ JDBC
┌─────────────────────────────────────────────────────────────┐
│                      数据库(MySQL/PostgreSQL)              │
└─────────────────────────────────────────────────────────────┘

2. 完整示例:产品微服务

实体类(JPA)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import jakarta.persistence.*;
import java.math.BigDecimal;

@Entity
@Table(name = "t_product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, length = 100)
    private String name;
    
    private BigDecimal price;
    
    private Integer stock;
    
    // getter/setter 省略
}

Repository(数据访问)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.util.List;

@ApplicationScoped
public class ProductRepository {
    
    @PersistenceContext
    private EntityManager em;
    
    public List<Product> findAll() {
        return em.createQuery("SELECT p FROM Product p", Product.class)
                 .getResultList();
    }
    
    public Product findById(Long id) {
        return em.find(Product.class, id);
    }
    
    public Product save(Product product) {
        if (product.getId() == null) {
            em.persist(product);
            return product;
        }
        return em.merge(product);
    }
    
    public void delete(Long id) {
        Product product = findById(id);
        if (product != null) {
            em.remove(product);
        }
    }
}

Service(业务逻辑 + 容错)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import org.eclipse.microprofile.faulttolerance.Retry;
import org.eclipse.microprofile.faulttolerance.Timeout;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.util.List;

@ApplicationScoped
public class ProductService {
    
    @Inject
    private ProductRepository repository;
    
    @Inject
    @ConfigProperty(name = "products.cache.enabled", defaultValue = "true")
    private boolean cacheEnabled;
    
    @Retry(maxRetries = 3, delay = 1000)
    @Timeout(2000)
    @Fallback(fallbackMethod = "getDefaultProducts")
    public List<Product> getAllProducts() {
        return repository.findAll();
    }
    
    public List<Product> getDefaultProducts() {
        return List.of();
    }
    
    public Product getProduct(Long id) {
        return repository.findById(id);
    }
    
    public Product createProduct(Product product) {
        return repository.save(product);
    }
}

REST 资源(JAX-RS)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import java.util.List;

@Path("/api/products")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ProductResource {
    
    @Inject
    private ProductService productService;
    
    @GET
    @Operation(summary = "获取所有产品")
    public List<Product> listProducts() {
        return productService.getAllProducts();
    }
    
    @GET
    @Path("/{id}")
    @Operation(summary = "根据ID获取产品")
    @APIResponse(responseCode = "404", description = "产品不存在")
    public Response getProduct(@PathParam("id") Long id) {
        Product product = productService.getProduct(id);
        if (product == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
        return Response.ok(product).build();
    }
    
    @POST
    @Operation(summary = "创建产品")
    @APIResponse(responseCode = "201", description = "创建成功")
    public Response createProduct(Product product) {
        Product created = productService.createProduct(product);
        return Response.status(Response.Status.CREATED)
                       .entity(created)
                       .build();
    }
}

3. 架构优势

优势 说明
标准化 基于 Jakarta EE 和 MicroProfile 开放标准,无厂商锁定
轻量化 无需厚重的应用服务器,可部署为独立 JAR(如 Quarkus)
云原生 内置健康检查、配置外部化、容错机制
可观测 Telemetry 提供追踪、指标、日志
可移植 可在任何兼容的 Jakarta EE 实现上运行

六、与 Spring Boot / Quarkus / Helidon 的对比

1. 框架定位

框架 定位 核心特点
Jakarta EE + MicroProfile 企业级标准 开放标准、无厂商锁定、可移植
Spring Boot 全栈框架 生态完善、快速开发、社区庞大
Quarkus 云原生 Java 极速启动、低内存、GraalVM 原生镜像
Helidon 轻量级微服务 Oracle 出品、SE/MP 两种模式

2. 详细对比

对比维度 Jakarta EE + MicroProfile Spring Boot Quarkus Helidon
标准 vs 专有 ✅ 开放标准 ❌ 专有框架 ❌ 专有框架 ❌ 专有框架
启动速度 中等 中等 极快 中等
内存占用 中等 中等 极低 中等
原生镜像支持 有限(Quarkus 实现) 有限(Spring Native) ✅ 原生支持 ✅ 原生支持
生态成熟度 成熟 最成熟 快速增长 中等
学习曲线 中等 中等 中等 较低
云原生特性 ✅ MicroProfile ✅ Spring Cloud ✅ 原生支持 ✅ 原生支持
厂商锁定 ❌ 无 ✅ 有 ✅ 有 ✅ 有(Oracle)
适用场景 标准化企业应用 通用首选 Serverless/云原生 轻量微服务

3. 选型建议

场景 推荐方案 理由
追求标准化、避免厂商锁定 Jakarta EE + MicroProfile 开放标准,可在多个实现间切换
快速开发、生态完善 Spring Boot 社区庞大、文档丰富、生产力最高
Serverless / 极致云原生 Quarkus 启动毫秒级、内存极小、原生镜像
Oracle 云环境 Helidon Oracle 官方支持,与 OCI 深度集成
传统企业系统维护 Jakarta EE 与现有 EJB、JPA 等无缝兼容
微服务 + 标准化 Jakarta EE + MicroProfile 标准化的微服务能力

4. Spring Boot 3 与 Jakarta EE 的关系

值得注意的是,Spring Boot 3 实际上实现了 Jakarta EE 10 规范(使用 Hibernate 6、Jakarta Persistence 3.1 等)。这意味着:

  • Spring Boot 3 的应用也使用了 jakarta.* 命名空间;
  • 开发者在 Spring Boot 3 中使用的 JPA、Servlet API 等,底层已经是 Jakarta EE 规范;
  • Jakarta EE 和 Spring Boot 并非对立关系,而是规范与实现的关系在演化

七、实战案例:云原生产品微服务

1. 项目结构

product-service/
├── src/main/java/
│   └── com/example/product/
│       ├── ProductApplication.java      # 应用启动类
│       ├── entity/
│       │   └── Product.java             # JPA 实体
│       ├── repository/
│       │   └── ProductRepository.java   # 数据访问
│       ├── service/
│       │   └── ProductService.java      # 业务逻辑 + 容错
│       ├── rest/
│       │   └── ProductResource.java     # REST API
│       └── health/
│           ├── LivenessCheck.java       # 存活检查
│           └── ReadinessCheck.java      # 就绪检查
├── src/main/resources/
│   ├── application.yaml                 # 配置文件
│   └── META-INF/
│       └── beans.xml                    # CDI 配置
├── Dockerfile
├── kubernetes/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── configmap.yaml
└── pom.xml

2. 依赖配置(pom.xml)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.example</groupId>
    <artifactId>product-service</artifactId>
    <version>1.0.0</version>
    <packaging>war</packaging>
    
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencies>
        <!-- Jakarta EE 10 Core -->
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>10.0.0</version>
            <scope>provided</scope>
        </dependency>
        
        <!-- MicroProfile 7.1 -->
        <dependency>
            <groupId>org.eclipse.microprofile</groupId>
            <artifactId>microprofile</artifactId>
            <version>7.1</version>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>
        
        <!-- JPA 实现(Hibernate) -->
        <dependency>
            <groupId>org.hibernate.orm</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.4.0.Final</version>
        </dependency>
        
        <!-- MySQL 驱动 -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.2.0</version>
        </dependency>
    </dependencies>
    
    <build>
        <finalName>product-service</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.4.0</version>
            </plugin>
        </plugins>
    </build>
</project>

3. 配置文件(application.yaml)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
mp:
  config:
    profile: dev

products:
  cacheEnabled: true
  maxSize: 100

db:
  url: jdbc:mysql://db:3306/productdb
  username: product_user
  password: product_pass
  pool:
    maxSize: 10
    minIdle: 5

health:
  liveness:
    path: /health/live
  readiness:
    path: /health/ready

user-service:
  mp-rest:
    url: http://user-service:8080
    connectTimeout: 5000
    readTimeout: 3000

4. 应用启动类

1
2
3
4
5
6
7
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationPath("/api")
public class ProductApplication extends Application {
    // 自动扫描所有 @Path 资源
}

5. 构建与部署

构建

1
mvn clean package

Docker 构建

1
docker build -t product-service:1.0.0 .

部署到 Kubernetes

1
2
3
kubectl apply -f kubernetes/configmap.yaml
kubectl apply -f kubernetes/deployment.yaml
kubectl apply -f kubernetes/service.yaml

验证

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 查看 Pod 状态
kubectl get pods

# 查看健康检查端点
kubectl port-forward pod/product-service-xxx 8080:8080
curl http://localhost:8080/health/live
curl http://localhost:8080/health/ready

# 调用 API
curl http://localhost:8080/api/products

八、总结

1. 核心知识脉络

层级 技术 核心概念
命名空间迁移 javax.*jakarta.* Jakarta EE 9 大爆炸式重命名
微服务标准 MicroProfile Config、Health、Fault Tolerance、Rest Client、Telemetry、OpenAPI
云原生部署 Docker + Kubernetes 容器化、探针、配置外部化
轻量架构 REST + CDI + JPA 标准化微服务架构
框架对比 Spring Boot / Quarkus / Helidon 标准 vs 专有、生态 vs 性能

2. 关键理解

  1. Jakarta EE 9 是分水岭javax.*jakarta.*不可逆的彻底变更,影响所有 Java 企业应用;
  2. MicroProfile 是微服务的标准答案:在 Jakarta EE 基础上,提供了配置、容错、健康检查、可观测性等云原生能力;
  3. 容器化是云原生的基础:Docker 镜像 + Kubernetes 编排 + MicroProfile Health 探针,构成标准云原生部署方案;
  4. 标准化 vs 专有框架:Jakarta EE + MicroProfile 提供无厂商锁定的开放标准;Spring Boot 提供最成熟的生态;Quarkus 提供极致的云原生性能
  5. Spring Boot 3 已融入 Jakarta EE:Spring Boot 3 底层使用 Jakarta EE 10 规范,两者并非对立。

3. 架构演进趋势

1
2
3
4
5
6
7
传统 Java EE(单体 + 应用服务器)
Jakarta EE(标准化 + 模块化)
Jakarta EE + MicroProfile(微服务 + 云原生)
Quarkus / Spring Boot(轻量级云原生运行时)

核心趋势:从“重型应用服务器”到“轻量级云原生运行时”,从“专有框架”到“开放标准 + 多种实现”。

4. 与后续学习的衔接

理解 Jakarta EE 现代化与云原生转型后,你将能更好地理解:

  • 实际项目中的技术选型:根据场景选择 Jakarta EE、Spring Boot 还是 Quarkus;
  • 微服务架构设计:服务拆分、API 网关、服务发现、配置中心;
  • 云原生基础设施:Kubernetes、Service Mesh、可观测性平台;
  • Serverless 架构:FaaS 环境中的 Java 应用部署。