首页 > 解决方案 > 使用 PanacheEntityResource 的 Quarkus 自定义休息端点

问题描述

我试图完成一些 quarkus 教程,但在创建一个简单的 REST 端点时遇到了问题。我正在关注本教程:https ://quarkus.io/guides/rest-data-panache 。

我使用指南中的方法创建扩展 PanacheEntityResource<Entity, Id> 的接口

public interface ActorResource extends PanacheEntityResource<Actor, Long>{
    
        
}

相应的实体是:

@Entity
public class Actor extends PanacheEntity{
    
    
    public String first_name;
    public String last_name;
    public Timestamp last_update;
    
    public static List<Actor> findByFirstName(String name) {
        return list("first_name", name);
    }
    

}

如指南中所述,这样做会自动为 getById、getAll、create、update 和 delete 生成基本的 rest 端点。正如您在我的 Entity 类中看到的那样,我有一个 findByFirstName 方法,它获取所有与给定方法参数 "name" 匹配的实体。现在我想为这个方法公开一个 REST 端点。到目前为止,我已经找到了实现这一点的方法,但这似乎不太正确。我没有将方法的 REST 端点直接实现到接口中

@ResourceProperties(path = "actors")
public interface ActorResource extends PanacheEntityResource<Actor, Long>{
    
    
    @GET
    @Produces("application/json")
    @Path("/first_name={name}")
    public static List<Actor> getByFirstName(@PathParam("name") String name) {
        return Actor.findByFirstName(name);
    }
    
        
}

此实现没有错误,但未公开 REST 端点。现在正如我所说,我找到了一种方法来做到这一点,这是创建一个接口,如第一个代码括号中所示,其中没有任何内容,此外还有一个 ResourceClass,我在其中实现了我的自定义端点。为了减少混乱(在 IDE 中),我将其结合起来,因此在我的 ResourceClass 中创建接口,如下所示(示例是另一个实体):

@Path("/countries")
@ApplicationScoped
@Produces("application/json")
public class CountryResource  {
    
    @GET
    @Path("/name={name}")
    public List<Country> getByName(@PathParam("name") String name) {
        return Country.findByName(name);
    }
    
    @ResourceProperties(path = "/countries")
    public interface CountryResourceTest extends PanacheEntityResource<Country, Long>{
        
    }

}

这是可行的,通过创建接口,自动生成基本的其余端点,并且在资源类中我可以添加其他端点,但感觉这不是正确的方法。我错了,这就是我应该这样做的方式,还是有办法仅使用指南中最初使用的接口方法来实现这一点?

标签: javarestcode-generationquarkus

解决方案


我认为尚不支持将自定义端点直接添加到生成的资源类,因为这仍然是仅用于评估的实验性功能。随时在 quarkus 的 GitHub 问题跟踪器中提供反馈。

我认为添加自定义端点的最佳方法是创建具有相同路径的第二个资源类。然后您可以在那里定义您的自定义端点。如果您没有名称冲突,那将起作用。我使用hibernate-orm-panache-quickstart对其进行了测试,并进行了以下代码更改:

我的实体与我的自定义查询:

@Entity
@Cacheable
public class Fruit extends PanacheEntity {

    @Column(length = 40, unique = true)
    public String name;

    public Fruit() {
    }

    public Fruit(String name) {
        this.name = name;
    }

    public static Fruit findByName(String name) {
        return find("name=?1", name).firstResult();
    }
}

生成的 rest-api 的资源(删除本教程中的给定资源):

public interface FruitResource extends PanacheEntityResource<Fruit, Long> {
}

我的具体资源:

@Path("fruit")
@ApplicationScoped
@Produces("application/json")
@Consumes("application/json")
public class FruitSpecificResource {

    @GET
    @Path("/first_name={name}")
    public Fruit getByName(@PathParam("name") String name) {
        return Fruit.findByName(name);
    }

}

出于测试目的,我还添加了 openapi 并用 h2 替换了 postgres。这是我的依赖项:

        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-hibernate-orm-panache</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-jsonb</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-jdbc-h2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-smallrye-openapi</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-hibernate-orm-rest-data-panache</artifactId>
        </dependency>

我将 application.properties 更改为:

quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:mem:test
quarkus.datasource.jdbc.max-size=8
quarkus.datasource.jdbc.min-size=2

quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=true
quarkus.hibernate-orm.sql-load-script=import.sql

好的,现在我可以启动 quarkus:dev 并且在 localhost:8080/swagger-ui 下会有一个 swagger-ui

新的端点在那里。我手动测试了它。有用。


推荐阅读