支持JDK19虚拟线程的web框架,之二:完整开发一个支持虚拟线程的quarkus应用( 三 )

  • pom.xml的第一处改动如下图,要确保全部是19

支持JDK19虚拟线程的web框架,之二:完整开发一个支持虚拟线程的quarkus应用

文章插图
  • 第二处改动 , 是在quarkus-maven-plugin插件中增加额外的配置参数,如下图红框

支持JDK19虚拟线程的web框架,之二:完整开发一个支持虚拟线程的quarkus应用

文章插图
  • 接下来新增配置文件application.properties , 在resources目录下
quarkus.datasource.db-kind=postgresqlquarkus.datasource.jdbc.max-size=8quarkus.datasource.jdbc.min-size=2quarkus.datasource.username=quarkusquarkus.datasource.password=123456quarkus.datasource.reactive.url=postgresql://192.168.0.1:5432/quarkus_test
  • 开始写java代码了 , 首先是启动类VirtualThreadsDemoApp.java
package com.bolingcavalry;import io.quarkus.runtime.Quarkus;import io.quarkus.runtime.annotations.QuarkusMain;@QuarkusMainpublic class VirtualThreadsDemoApp {public static void main(String... args) {Quarkus.run(args);}}
  • 数据库对应的model类有两个,第一个是gender字段的枚举
package com.bolingcavalry.model;public enum Gender {MALE, FEMALE;}
  • 表对应的实体类
package com.bolingcavalry.model;import io.vertx.mutiny.sqlclient.Row;public class Person {private Long id;private String name;private int age;private Gender gender;private Integer externalId;public String getThreadInfo() {return threadInfo;}public void setThreadInfo(String threadInfo) {this.threadInfo = threadInfo;}private String threadInfo;public Person() {}public Person(Long id, String name, int age, Gender gender, Integer externalId) {this.id = id;this.name = name;this.age = age;this.gender = gender;this.externalId = externalId;this.threadInfo = Thread.currentThread().toString();}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Gender getGender() {return gender;}public void setGender(Gender gender) {this.gender = gender;}public Integer getExternalId() {return externalId;}public void setExternalId(Integer externalId) {this.externalId = externalId;}public static Person from(Row row) {return new Person(row.getLong("id"),row.getString("name"),row.getInteger("age"),Gender.valueOf(row.getString("gender")),row.getInteger("external_id"));}}
  • 接下来是操作数据库的dao类,可见使用操作方式还是很原始的,还要在代码中手写SQL,取出也要逐个字段匹配,其实quarkus也支持JPA,只不过本篇使用的是响应式数据库驱动,所以选用的是Vert.x生成的连接池PgPool
package com.bolingcavalry.repository;import com.bolingcavalry.model.Person;import io.vertx.mutiny.pgclient.PgPool;import io.vertx.mutiny.sqlclient.Row;import io.vertx.mutiny.sqlclient.RowSet;import io.vertx.mutiny.sqlclient.Tuple;import javax.enterprise.context.ApplicationScoped;import javax.inject.Inject;import java.util.ArrayList;import java.util.List;@ApplicationScopedpublic class PersonRepositoryAsyncAwait {@InjectPgPool pgPool;public Person findById(Long id) {RowSet<Row> rowSet = pgPool.preparedQuery("SELECT id, name, age, gender, external_id FROM person WHERE id = $1").executeAndAwait(Tuple.of(id));List<Person> persons = iterateAndCreate(rowSet);return persons.size() == 0 ? null : persons.get(0);}private List<Person> iterateAndCreate(RowSet<Row> rowSet) {List<Person> persons = new ArrayList<>();for (Row row : rowSet) {persons.add(Person.from(row));}return persons;}}
  • 接下来就是前面截图看到的web服务类VTPersonResource.java,它被注解@RunOnVirtualThread修饰 , 表示收到web请求在虚拟线程中执行响应代码
package com.bolingcavalry.resource;import com.bolingcavalry.model.Person;import com.bolingcavalry.repository.PersonRepositoryAsyncAwait;import io.smallrye.common.annotation.RunOnVirtualThread;import javax.inject.Inject;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.PathParam;@Path("/vt/persons")@RunOnVirtualThreadpublic class VTPersonResource {@InjectPersonRepositoryAsyncAwait personRepository;@GET@Path("/{id}")public Person getPersonById(@PathParam("id") Long id) {return personRepository.findById(id);}}
  • 最后是用于对比的常规web服务类PoolPersonResource.java,这个就是中规中矩的在线程池中取一个线程来执行响应代码
package com.bolingcavalry.resource;import com.bolingcavalry.model.Person;import com.bolingcavalry.repository.PersonRepositoryAsyncAwait;import io.smallrye.common.annotation.RunOnVirtualThread;import javax.inject.Inject;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.PathParam;@Path("/pool/persons")public class PoolPersonResource {@InjectPersonRepositoryAsyncAwait personRepository;@GET@Path("/{id}")public Person getPersonById(@PathParam("id") Long id) {return personRepository.findById(id);}}

推荐阅读