Quarkus、Grpc、kotlin学习

1、搭建Quarkus框架

mvn io.quarkus:quarkus-maven-plugin:create \
-DprojectGroupId=com.quarkus \
-DprojectArtifactId=grpc-kotlin \
-DprojectVersion=1.0 \
-DclassName=StockResource \
-Dpath=stock

quarkus.platform.version 改为3.6.8
添加kotlin支持

    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-kotlin</artifactId>
    </dependency>

添加3个module:grpc-proto、grpc-server、grpc-client

  <modules>
    <module>grpc-proto</module>
    <module>grpc-server</module>
    <module>grpc-client</module>
  </modules>

2、搭建Grpc环境

1)在grpc-proto module中,引入quarkus-grpc,创建proto文件

    <dependencies>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-grpc</artifactId>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/proto</directory>
                <targetPath>proto</targetPath>
            </resource>
        </resources>
    </build>
syntax = "proto3";

package model;

option java_package = "com.quarkus.grpc.model";
option java_outer_classname = "StockProto";

service StockService {
  rpc getQuantity(Stock) returns (Stocks) {}
}

message Stock {
  int64 id = 1;
  string stockDate = 2;
  int32 storeCode = 3;
  string productCode = 4;
  double quantity = 5;
  string operationTime = 6;
  string transferTime = 7;
  string registeredAt = 8;
  string registeredBy = 9;
}

message Stocks {
  repeated Stock stock = 1;
}

grpc-proto目录下运行命令:mvn install
2)在gprc-server模块中,引入postgresql、jpa支持

        <dependency>
            <groupId>com.yunyan</groupId>
            <artifactId>quarkus-grpc-proto</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-jdbc-postgresql</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-spring-data-jpa</artifactId>
        </dependency>

配置端口号,数据库连接、jpa命名策略

quarkus.http.port=8082
quarkus.grpc.server.port=9092

quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = postgres
quarkus.datasource.password = postgre
quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/postgres

quarkus.hibernate-orm.physical-naming-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
quarkus.hibernate-orm.implicit-naming-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
quarkus.hibernate-orm.log.sql=true

创建Stock类

@Entity
@Table(name = "init_stock")
open class Stock {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long = 0
    var stockDate: LocalDateTime? = null
    var storeCode: Int? = null
    var productCode: String? = null
    var quantity: BigDecimal? = null
    var operationTime: LocalDateTime? = null
    var transferTime: LocalDateTime? = null
    var registeredAt: LocalDateTime? = null
    var registeredBy: String? = null
}

StockRepository类

interface StockRepository : JpaRepository<Stock, Long> {
    fun findByStoreCodeAndStockDateAndProductCode(
        storeCode: Int,
        stockDate: LocalDateTime,
        productCode: String
    ): List<Stock>
}

StockServiceImpl类

@Blocking
@GrpcService
class StockServiceImpl : StockService {
    @Inject
    lateinit var stockRepository: StockRepository

    override fun getQuantity(request: StockProto.Stock): Uni<Stocks> {
        val stockList = stockRepository.findByStoreCodeAndStockDateAndProductCode(
            request.storeCode,
            LocalDate.parse(request.stockDate).atStartOfDay(),
            request.productCode
        )
        val stockMap: MutableMap<String, Stock> = HashMap(16)
        stockList.forEach { t: Stock ->
            val key = t.storeCode.toString() + t.stockDate.toString() + t.productCode
            if (stockMap.containsKey(key)) {
                val stock = stockMap[key]
                stock!!.quantity = stock.quantity!!.add(t.quantity)
            } else {
                stockMap.put(key, t)
            }
        }
        val stocks = stockMap.values.stream().collect(Collectors.toList())
        return Uni.createFrom().item(stocks).map { stocks: List<Stock> -> toProtoStocks(stocks) }
    }

    private fun toProtoStocks(stocks: List<Stock>): Stocks {
        val builder = Stocks.newBuilder()
        stocks.forEach { t: Stock -> builder.addStock(toProtoStock(t)) }
        return builder.build()
    }

    private fun toProtoStock(stock: Stock): StockProto.Stock {
        val builder = StockProto.Stock.newBuilder()
        builder.setStoreCode(stock.storeCode!!)
            .setStockDate(stock.stockDate!!.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
            .setProductCode(stock.productCode).quantity = stock.quantity!!.toDouble()
        return builder.build()
    }
}

运行grpc-server:mvn quarkus:dev
进入http://localhost:8082/q/dev-ui,点击Extensions、gRPC Services显示如下页面:

image.png

3)grpc-client端创建
pom文件中引入如下包:

        <dependency>
            <groupId>com.quarkus</groupId>
            <artifactId>grpc-proto</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-mutiny</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-jackson</artifactId>
        </dependency>

配置端口:

quarkus.http.port=8081
quarkus.grpc.server.port=9091

quarkus.grpc.clients.stockService.port=9092

测试代码:

@Path("/stock")
class StockResource {
    @GrpcClient
    lateinit var stockService: StockService

    @POST
    @Path("/getQuantity")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    fun getQuantity(model: Model): Uni<List<Model>> {
        val builder: StockProto.Stock.Builder = StockProto.Stock.newBuilder()
        builder.setStockDate(model.stockDate)
            .setStoreCode(model.stockCode).productCode = model.productCode
        val stocks: Uni<StockProto.Stocks> = stockService.getQuantity(builder.build())
        return stocks.onItem().transform { stocks: StockProto.Stocks -> transToModel(stocks) }
    }

    private fun transToModel(stocks: StockProto.Stocks): List<Model> {
        val list: MutableList<Model> = ArrayList()
        stocks.stockList.forEach { t: StockProto.Stock ->
            var model = Model()
            model.stockCode = t.storeCode
            model.stockDate = t.stockDate
            model.productCode = t.productCode
            model.quantity = t.quantity
            list.add(model)
        }
        return list
    }
}

数据库数据:


image.png

运行grpc-client:mvn quarkus:dev ,postman调用结果如下:


image.png

源码地址:https://gitee.com/chris2812/quarkus-grpc-kotlin

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容