使用Spring Boot创建GraphQL API

Introduction

在本教程中,我们将构建一个Pokemon API,该API消耗Postgres数据库中的数据,并带有一个简单的端点,该端点按ID执行搜索。

The final code is in this Github repository.

Postgres setup

If you already have Postgres installed locally, you can skip this part, otherwise the easiest way to do it is by running a Docker image. Just install Docker and then:

docker run -p5432:5432 -d postgres:11.4-alpine

此命令将使用默认用户在端口5432上启动Postgres实例Postgres和默认数据库Postgres。

Spring Boot setup

We will start by creating the initial project files using Spring Initializr. I've selected:

  • 摇篮爪哇Spring Boot 2.1.6Spring Web StarterSpring Data JPAPostgreSQL驱动

除了Spring依赖项之外,我们还需要添加GraphQL库:

  • GraphQL Spring Boot Starter: will automatically create an /graphql endpoint
  • GraphQL Spring Boot Starter Test: for our unit tests
  • GraphQL Java Tools: from its own documentation: "maps fields on your GraphQL objects to methods and properties on your java objects". This library requires version 1.3.* of Kotlin, so you need to create a gradle.properties file on the project root directory with content:
kotlin.version=1.3.10

Database connection

添加依赖项后,您可以编辑src / main / resources / application.properties文件以添加Postgres配置。 如果您使用上面的Docker命令在本地启动Postgres,则文件应如下所示:

## PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=

#drop n create table again, good for testing, comment this in production
spring.jpa.hibernate.ddl-auto=create-drop

运行您的应用程序以测试到目前为止一切是否正常:。/gradlew bootRun。

GraphQL Schema

GraphQL具有出色的模式语言,可将类型声明添加到其请求中并返回值,并将其耦合到API实现。 这意味着必须实现您在架构上声明的内容。

如果我们想添加一个端点以按其ID搜索神奇宝贝,则应在src / main / resources / schema.graphqls文件:

type Pokemon {
    id: ID!
    name: String!
}

type Query {
    pokemon(id: ID!): Pokemon
}

现在,我们的下一步必须是通过其ID对Pokemon实例进行数据库搜索,否则应用程序将无法运行。

Query resolver

声明的架构期望返回Pokemon类型包含必需的属性ID和名称。

对于我们的应用程序,这意味着宠物小精灵是一个Java类,ID和名称属性,但还有一个数据库表。 我们可以用javax.persistence annotations to automatically map 宠物小精灵 to database table with columns ID和名称:

@Entity
@Table(name = "pokemon")
public class Pokemon {

    public Pokemon(final Long id, final String name) {
        this.id = id;
        this.name = name;
    }

    @Id
    public Long id;

    @Column
    public String name;
}

另一个预期类别应该是春豆实现GraphQLQueryResolver接口,并应具有名称的方法getPokemon,与我们在方案中定义的参数和响应完全匹配:

@Component
public class Query implements GraphQLQueryResolver {

    public Pokemon getPokemon(Long id) {
        return new Pokemon(1L, "Pikachu");
    }
}

现在,我们可以在新端点执行一个请求,以检查其响应是否是我们的皮卡丘。

Pikachu appearing

GraphiQL

GraphiQL在我们的API上配置了一个端点,使我们可以测试任何查询。 在我们的项目中,它将在地址上运行http:// localhost:8080 / graphiql。

左列是我们应该编写查询的位置,右列是结果。 例如,如果我们输入查询:

# Searches a Pokemon with id 25 and returns its field 'name'
query {
  pokemon(id: 25){
    name
  }
}

我们应该期望结果在右列:

{
  "data": {
    "pokemon": {
      "name": "Pikachu"
    }
  }
}

到目前为止,哪个参数都没有关系ID我们通过了,因为我们已经修复了响应对象,但是现在我们将实现数据库搜索。

Fetch Pokemons from database

当前,我们的应用程序未在进行真正的数据库搜索,而是返回一个固定的实例。 现在让我们实现这一部分。

首先,我们创建一个宠物小精灵存储库扩展的接口Jpa存储库:

@Repository
public interface PokemonRepository extends JpaRepository<Pokemon, Long> {
}

然后我们改变我们的询问类以自动装配该bean并执行实际的数据库提取:

@Component
public class Query implements GraphQLQueryResolver {

    @Autowired
    private PokemonRepository repository;

    public Pokemon getPokemon(Long id) {
        // Not returning a fixed instance anymore
        return repository.findById(id).orElse(null);
    }
}

Unit test

我们的自动化测试将利用GraphQLTestTemplate允许我们输入询问 and verify its response. For example, if we want to test the search pokemon by id 询问, we first have to create a file in src / test / resources with this 询问:

# src/test/resources/get-pokemon-by-id.graphql
query {
    pokemon(id: "1") {
        id
        name
    }
}

测试类应带有注释@GraphQLTest这样就可以解决GraphQLTestTemplate实例和宠物小精灵存储库应该用@MockBean因此我们可以使用莫基托。

@RunWith(SpringRunner.class)
@GraphQLTest
public class DemoApplicationTests {

    @Autowired
    private GraphQLTestTemplate graphQLTestTemplate;

    @MockBean
    private PokemonRepository pokemonRepository;

    @Test
    public void getById() throws IOException {
        Pokemon pokemon = new Pokemon(1L, "Pikachu");
        when(pokemonRepository.findById(any()))
                .thenReturn(Optional.of(pokemon));

        GraphQLResponse response =
                graphQLTestTemplate.postForResource("get-pokemon-by-id.graphql");

        assertTrue(response.isOk());
        assertEquals("1", response.get("$.data.pokemon.id"));
        assertEquals("Pikachu", response.get("$.data.pokemon.name"));
    }
}

基本上,我们在这里测试的场景如下:

  • 给定存储库,当调用findById方法当我们查询GraphQL Api与通过id.graphql获取神奇宝贝然后我们期望响应是一个包含存储库中的皮卡丘的JSON

Conclusion

使用Spring Boot实现GraphQL Api的挑战主要取决于Spring Boot功能的配置和小细节。 总的来说,我认为集成效果很好,特别是用于执行代码实现的GraphQL Java工具。

from: https://dev.to//fabiothiroki/create-a-graphql-api-using-spring-boot-32o2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值