cxl
Published on 2025-07-21 / 6 Visits
0
0

Quarkus入门

自上一章了解Quarkus的核心特性后,让我们动手搭建开发环境并创建第一个Quarkus项目。Quarkus提供了多种便捷的项目创建方式,适合不同场景和开发者偏好。

环境准备

开始Quarkus开发前,需要确保系统满足以下基本要求​:

  • JDK​:推荐使用JDK 17或更高版本(LTS版本),这是运行Quarkus应用的基石。

  • 构建工具​:Quarkus支持Maven和Gradle,推荐使用Apache Maven 3.6.2+。

  • 开发工具​:任何Java IDE均可,IntelliJ IDEA和VS Code都有很好的Quarkus插件支持。

  • 可选组件​:

    • Docker:用于容器化部署

    • GraalVM:如需构建原生镜像

  # 检查环境是否符合要求
  java -version
  mvn -v

创建Quarkus项目

Quarkus提供多种项目创建方式,以下是三种最常用的方法:

1. 使用Maven命令创建

这是最直接的方式,适合习惯命令行的开发者:

  mvn io.quarkus.platform:quarkus-maven-plugin:3.10.1:create \
    -DprojectGroupId=com.cxl \
    -DprojectArtifactId=my-quarkus-app \
    -Dextensions="resteasy-reactive,io.quarkus:quarkus-jdbc-mysql"

参数说明:

  • projectGroupId:项目组织标识,通常采用反向域名

  • projectArtifactId:项目名称

  • extensions:要包含的Quarkus扩展,多个用逗号分隔,注意要用双引号

2. 使用在线生成器

Quarkus官方提供了Web界面​(https://code.quarkus.io),可直观选择需要的扩展并生成项目:

  1. 访问code.quarkus.io

  2. 选择扩展(如RESTEasy Reactive、Hibernate ORM等)

  3. 点击"Generate your application"下载zip包

  4. 解压后导入IDE

3. 使用IDE插件

主流Java IDE如IntelliJ IDEA都默认装有Quarkus插件或VS Code都支持通过插件创建Quarkus项目:

  1. 安装Quarkus插件

  2. 选择"New Project" → "Quarkus"

  3. 按照向导填写项目信息

  4. 选择初始扩展

项目结构分析

新创建的Quarkus项目遵循标准的Maven结构,但有一些特殊元素​:

  my-quarkus-app/
  ├── src/
  │   ├── main/
  │   │   ├── java/          # 主要Java代码
  │   │   ├── resources/
  │   │   │   ├── application.properties  # 配置文件
  │   │   │   └── META-INF/resources/    # 静态资源
  │   │   └── docker/        # Docker相关文件
  │   └── test/              # 测试代码
  ├── .dockerignore
  ├── .gitignore
  └── pom.xml                # Maven构建文件

关键文件说明:

  • GreetingResource.java:自动生成的REST资源类示例

  • application.properties:统一配置文件,类似Spring的application.properties

  • Dockerfile.native:用于构建原生镜像的Dockerfile

核心功能与代码实践

掌握了Quarkus的基本概念和项目创建后,让我们继续深入探讨Quarkus的核心功能,并通过实际代码示例演示如何开发各种云原生组件。这些实践将帮助您全面了解Quarkus的开发模式和最佳实践。

RESTful服务开发

作为微服务的核心构建块,RESTful API在Quarkus中得到了优雅的实现。Quarkus支持两种REST实现:传统的RESTEasy(JAX-RS)和新一代的RESTEasy Reactive。

基础REST端点

以下代码展示了一个简单的REST端点,返回"Hello Quarkus!":

  package org.acme;
  
  import javax.ws.rs.GET;
  import javax.ws.rs.Path;
  import javax.ws.rs.Produces;
  import javax.ws.rs.core.MediaType;
  
  @Path("/hello")
  public class GreetingResource {
  
      @GET
      @Produces(MediaType.TEXT_PLAIN)
      public String hello() {
          return "Hello Quarkus!";
      }
  }

关键注解:

  • @Path:定义资源路径

  • @GET:指定HTTP方法

  • @Produces:声明响应内容类型

启动应用后,访问http://localhost:8080/hello即可看到结果。

RESTEasy Reactive

Quarkus引入了RESTEasy Reactive,它基于Vert.x的异步非阻塞IO,特别适合高并发场景:

  @Path("/reactive")
  public class ReactiveResource {
  
      @GET
      @Produces(MediaType.TEXT_PLAIN)
      public Uni<String> reactiveHello() {
          return Uni.createFrom().item("Hello Reactive!")
                  .onItem().delayIt().by(Duration.ofSeconds(1));
      }
  }

这里使用了Mutiny的Uni类型,它代表可能尚未完成的异步操作。

异常处理

健壮的API需要良好的错误处理机制:

  @GET
  @Path("/{name}")
  public String personalizedHello(@PathParam String name) {
      if(name == null || name.isEmpty()) {
          throw new BadRequestException("Name cannot be empty");
      }
      return "Hello " + name;
  }

数据库访问

Quarkus提供了多种数据库访问方式,包括传统的JPA/Hibernate和更轻量级的Panache。

Hibernate ORM with Panache

Panache通过活动记录​(Active Record)和仓库​(Repository)模式简化了数据访问:

  1. 首先添加依赖:

  <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-hibernate-orm-panache</artifactId>
  </dependency>
  <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-jdbc-mysql</artifactId>
  </dependency>
  <!-- 没有引入这个依赖的话在post请求body的时候一直报415 -->
  <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
  </dependency>
  1. 配置数据源:

  # application.properties
  # 日志等级,利于排错
  quarkus.log.level=DEBUG
  quarkus.log.console.level=DEBUG
  # 数据源
  quarkus.datasource.db-kind=mysql
  quarkus.datasource.username=quarkus
  quarkus.datasource.password=quarkus
  quarkus.datasource.jdbc.url=jdbc:mysql://localhost:3306/quarkus_demo
  1. 定义实体:

  @Entity(name="person")
  public class Person extends PanacheEntityBase {
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)  // 使用数据库自增长
      public Long id;
      public String name;
      public String birth;
      public String status;
  }
  1. 实现REST端点:

  @Path("/person")
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public class PersonResource {
  
      @GET
      public List<Person> list() {
          return Person.listAll();
      }
  
      @POST
      @Transactional
      public Response create(Person person) {
          person.persist();
          return Response.status(201).build();
      }
  }

Panache提供了大量内置方法listAll()persist()等,显著减少样板代码。

依赖注入

Quarkus采用CDI(Contexts and Dependency Injection)作为其依赖注入框架:

  @ApplicationScoped
  public class GreetingService {
      
      public String greet(String name) {
          return "Hello " + name;
      }
  }
  
  @Path("/greet")
  public class GreetingResource {
  
      @Inject
      GreetingService service;
  
      @GET
      @Path("/{name}")
      public String greet(@PathParam String name) {
          return service.greet(name);
      }
  }

Quarkus的DI具有以下特点:

  • 支持多种作用域:@ApplicationScoped@RequestScoped等,似曾相识呀!忘了当初是strutcs还是springmvc用过了...

  • 支持@Inject和CDI标准

  • 编译时验证依赖关系

配置管理

Quarkus提供统一的配置系统,支持多种配置源:

  1. application.properties

  greeting.message=Hello
  greeting.upper-case=false
  1. 通过@ConfigProperty注入:

  @ConfigProperty(name="greeting.message") 
  String message;
  
  @ConfigProperty(name="greeting.upper-case", defaultValue="true")
  boolean upperCase;
  1. 支持多环境配置​:

  # application-dev.properties
  quarkus.http.port=9091
  
  # application-prod.properties
  quarkus.http.port=8080

通过quarkus.profile系统属性指定环境:

  ./mvnw quarkus:dev -Dquarkus.profile=prod

Quarkus还支持从环境变量、Kubernetes ConfigMap等获取配置。

开发模式与测试

Quarkus不仅在生产环境中表现出色,还特别注重开发者的工作效率和体验。其独特的开发模式和全面的测试支持,让开发者能够快速迭代并保证代码质量。

开发模式与热重载

Quarkus的开发模式是提升生产力的关键特性。通过以下命令启动:

  ./mvnw quarkus:dev

开发模式提供以下强大功能:

  1. 热重载​:修改Java文件、配置文件或静态资源后,无需手动重启,Quarkus会自动检测并重新加载变更。这是通过字节码增强技术实现的,修改代码后通常1秒内就能看到变化。

  2. 开发者控制台​:访问http://localhost:8080/q/dev 可进入Dev UI,这里提供了:

    • 查看所有端点

    • 数据库管理工具

    • 配置信息查看器

    • 扩展管理界面

  3. 实时日志​:控制台输出详细的日志信息,包括启动时间、注册的资源类、配置的数据库连接等。

  4. 持续测试​:在开发模式下运行测试时,Quarkus会监控代码变化并自动重新运行相关测试。

  # 开发模式下运行测试
  ./mvnw quarkus:test

单元测试

Quarkus鼓励测试驱动开发,提供了全面的测试支持。以下是一个REST端点的测试示例:

  @QuarkusTest
  public class GreetingResourceTest {
  
      @Test
      public void testHelloEndpoint() {
          given()
            .when().get("/hello")
            .then()
               .statusCode(200)
               .body(is("Hello Quarkus!"));
      }
  }

关键点:

  • @QuarkusTest注解标记测试类

  • 使用RestAssured简化HTTP测试

  • 测试会自动在开发模式下运行

集成测试

对于需要数据库或其他外部服务的测试,Quarkus提供了测试资源管理​:

  @QuarkusTest
  @TestHTTPEndpoint(PersonResource.class)
  public class PersonResourceTest {
  
      @Test
      public void testCreatePerson() {
          Person person = new Person();
          person.name = "Alice";
          
          given()
            .body(person)
            .contentType(ContentType.JSON)
            .when().post()
            .then()
               .statusCode(201);
      }
  }

Quarkus还支持:

  • @TestProfile:定义特定测试配置

  • @InjectMock:注入模拟对象

  • @QuarkusMock:模拟CDI bean

数据库测试

测试数据库交互时,可以使用H2内存数据库Testcontainers​:

  @QuarkusTest
  @TestProfile(TestProfile.class)
  public class PersonRepositoryTest {
  
      @Inject
      PersonRepository repository;
  
      @Test
      public void testPersist() {
          Person person = new Person();
          person.name = "Bob";
          repository.persist(person);
          assertNotNull(person.id);
      }
  }
  
  public class TestProfile implements QuarkusTestProfile {
      @Override
      public Map<String, String> getConfigOverrides() {
          return Map.of(
              "quarkus.datasource.db-kind", "h2",
              "quarkus.datasource.jdbc.url", "jdbc:h2:mem:test"
          );
      }
  }

这种灵活的测试支持确保了应用在各种场景下的行为正确性

构建与部署

开发完成后,将Quarkus应用高效地构建并部署到生产环境是至关重要的环节。Quarkus提供了多种构建和部署选项,适应不同的运行环境和性能需求。

构建选项

Quarkus支持三种主要的构建模式,每种适合不同的场景:

1. JVM模式

这是最传统的构建方式,生成在JVM上运行的字节码:

  ./mvnw package

生成的target/quarkus-app目录包含:

  • quarkus-run.jar:可运行的主JAR

  • lib/:依赖库目录

  • app/:应用类和资源文件

运行方式:

  java -jar target/quarkus-app/quarkus-run.jar

特点​:

  • 兼容性好

  • 支持动态类加载和反射

  • 启动速度和内存占用优于传统Java框架但仍不及原生镜像

2. 原生镜像模式

利用GraalVM将应用编译为本地可执行文件​:

  ./mvnw package -Pnative

要求:

  • 已安装GraalVM

  • 配置了必要的环境变量(GRAALVM_HOME)

  • 对于Linux/macOS,需要安装native-image组件

优势​:

  • 启动时间:毫秒级(通常<0.1秒)

  • 内存占用:降低80%以上

  • 打包体积:更小的容器镜像

限制​:

  • 构建时间较长

  • 某些Java特性(如反射、动态代理)需要特别处理

  • 调试相对困难

3. 选择quarkus的maven插件

容器化部署

Quarkus与Docker和Kubernetes有深度集成,简化了云原生部署。

生成Dockerfile

Quarkus在项目构建时在docker目录下自动生成了多种Dockerfile模板​:

  1. JVM模式Dockerfile​:

  FROM registry.access.redhat.com/ubi8/openjdk-21:1.19
  ENV LANGUAGE='en_US:en'

  # We make four distinct layers so if there are application changes the library layers can be re-used
  COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
  COPY --chown=185 target/quarkus-app/*.jar /deployments/
  COPY --chown=185 target/quarkus-app/app/ /deployments/app/
  COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/
  
  EXPOSE 8080
  USER 185
  ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
  ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
  
  ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
  1. 原生模式Dockerfile​:

  FROM quay.io/quarkus/quarkus-micro-image:2.0
  WORKDIR /work/
  RUN chown 1001 /work \
      && chmod "g+rwX" /work \
      && chown 1001:root /work
  COPY --chown=1001:root target/*-runner /work/application
  
  EXPOSE 8080
  USER 1001
  
  ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]

生成命令:

  ./mvnw quarkus:add-extension -Dextensions="container-image-docker"

构建容器镜像

使用Quarkus容器镜像扩展简化构建:

  # JVM模式
  ./mvnw package -Dquarkus.container-image.build=true
  
  # 原生模式
  ./mvnw package -Pnative -Dquarkus.container-image.build=true

这些命令会自动:

  1. 打包应用

  2. 构建Docker镜像

  3. 标记镜像

Kubernetes集成

Quarkus提供了强大的Kubernetes支持​:

  1. 添加扩展:

  ./mvnw quarkus:add-extension -Dextensions="kubernetes"
  1. 配置application.properties:

  quarkus.kubernetes.deploy=true
  quarkus.kubernetes.client.trust-certs=true
  quarkus.container-image.registry=quay.io
  quarkus.container-image.group=mygroup
  1. 构建时将自动生成:

  • kubernetes.json

  • kubernetes.yml

  • 并自动部署(如果配置了deploy=true)

部署策略选择

根据应用场景选择最佳部署方式​:

场景

推荐构建方式

部署目标

特点

开发测试

JVM模式

本地/Docker

快速构建,方便调试

传统云环境

JVM模式

VM/Kubernetes

平衡性能与兼容性

无服务器

原生镜像

Knative/OpenFaaS

极致启动速度

边缘计算

原生镜像

边缘设备

低资源消耗

CI/CD流水线

容器化原生构建

Kubernetes

无需管理构建环境

无论选择哪种方式,Quarkus都提供了相应的工具和扩展来简化部署流程,真正实现了"​构建一次,随处运行​"的理念。


Comment