背景
本文是《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.xml、beans.xml、ejb-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.properties、application.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. 构建与部署
构建:
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. 关键理解
- Jakarta EE 9 是分水岭:
javax.* → jakarta.* 是不可逆的彻底变更,影响所有 Java 企业应用;
- MicroProfile 是微服务的标准答案:在 Jakarta EE 基础上,提供了配置、容错、健康检查、可观测性等云原生能力;
- 容器化是云原生的基础:Docker 镜像 + Kubernetes 编排 + MicroProfile Health 探针,构成标准云原生部署方案;
- 标准化 vs 专有框架:Jakarta EE + MicroProfile 提供无厂商锁定的开放标准;Spring Boot 提供最成熟的生态;Quarkus 提供极致的云原生性能;
- 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 应用部署。