Pull to refresh

GraphQL + SPQR + Spring Boot Starter 2021

Reading time3 min
Views5.2K

Привет, Хабр!

GraphQL — это язык запросов к API-интерфейсам. Он отображает предоставляемые сервером данные, чтобы клиент смог выбрать именно то, что ему нужно. GraphQL SPQR призван упростить добавление GraphQL API в любой Java-проект. SPQR работает динамически, генерируя схему GraphQL из кода Java, посредством аннотаций. Перейдем к самой сути!

Настройка проекта / Зависимости

Добавьте следующие зависимости в ваш maven проект:

<dependency>
    <groupId>io.leangen.graphql</groupId>
    <artifactId>graphql-spqr-spring-boot-starter</artifactId>
    <version>0.0.6</version>
</dependency>
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphiql-spring-boot-starter</artifactId>
    <version>5.0.2</version>
</dependency>

Чтобы понять основные подходы SpqrAutoConfigurationрегистрирует компонент для каждой из трех встроенных ResolverBuilderреализаций:

  • AnnotatedResolverBuilder- предоставляет только методы, аннотированные @GraphQLQuery@GraphQLMutationили@GraphQLSubscription

  • PublicResolverBuilder- предоставляет все publicметоды из исходного класса операций (возвращаемые методы voidсчитаются мутациями)

  • BeanResolverBuilder- предоставляет все геттеры как запросы и сеттеры как мутации (возвращаемые геттеры Publisher<T>считаются подписками)

Также возможно реализовать собственные, реализовав свой ResolverBuilder интерфейс.

Описание основных аннотаций SPQR

@GraphQLApi- аналог контроллера, в котором определены Query и Mutation.

@GraphQLQuery - QUERY, аналог read запросов

@GraphQLMutation- MUTATION, аналог create/delete/update запросов

Остальные аннотации будут описаны ниже.

Описание сущности

Сущность банковский счет имеет номер счета (numberAccount), валюту (currency) и текущий счет (balance).

@Getter
@Setter
@Entity
@Table(name = "bank_account")
@FieldDefaults(level = AccessLevel.PRIVATE)
@NoArgsConstructor
public class BankAccountEntity {
    @Id
    String numberAccount;
    
    Currency currency;

    BigDecimal balance;
}

Опишем dto для работы с этой сущностью:

@Getter
@Setter
@FieldDefaults(level = AccessLevel.PRIVATE)
public class BankAccountDto {
    @GraphQLId
    String numberAccount;

    @NotNull
    @GraphQLScalar
    @GraphQLInputField
    Currency currency;

    @NotNull
    @GraphQLInputField
    BigDecimal balance;
}

Здесь аннотация @GraphQLInputField говорит GraphQL, что текущее поле будет полем для обновления или ввода. Попрошу заметить, что у поля currency стоит аннотация @GraphQLScalar - один из способов реализовать сложный скаляр.

package ru.bank.web.dataFetcher;

import io.leangen.graphql.annotations.GraphQLArgument;
import io.leangen.graphql.annotations.GraphQLMutation;
import io.leangen.graphql.annotations.GraphQLNonNull;
import io.leangen.graphql.annotations.GraphQLQuery;
import io.leangen.graphql.spqr.spring.annotations.GraphQLApi;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import ru.bank.business.service.BankAccountService;
import ru.bank.web.dto.BankAccountDto;
import ru.bank.web.dto.DispatchMoneyDto;

import java.util.List;

@RequiredArgsConstructor
@Component
@GraphQLApi
public class BankAccountDataFetcher {
    private final BankAccountService service;

    @GraphQLQuery(name = "getAllBalance")
    public List<BankAccountDto> getAll(@GraphQLArgument(name = "page")Pageable pageable) {
        return service.getAll(pageable);
    }

    @GraphQLMutation(name = "createBankAccount", description = "create a new bank account")
    public BankAccountDto createBankAccount(@GraphQLArgument(name = "createBankAccountInput") @GraphQLNonNull BankAccountDto bankAccount) {
        return service.create(bankAccount);
    }

    @GraphQLMutation(name = "dispatchMoney", description = "dispatch money")
    public void dispatchMoney(@GraphQLArgument(name = "createDispatchMoneyInput") @GraphQLNonNull DispatchMoneyDto dispatchMoneyDto) {
        service.dispatchMoney(dispatchMoneyDto);
    }

    @GraphQLMutation(name = "removeBankAccount", description = "remove bank account")
    public void removeBankAccount(@GraphQLNonNull String numberAccount) {
        service.remove(numberAccount);
    }
}

Параметр аннотации @GraphQLMutation name - указывает имя метода для GraphQL, а description - соответственно описание метода для graphiql

Отправка запросов

Отправка Query с пагинацией для получения данных по аккаунтам
Отправка Query с пагинацией для получения данных по аккаунтам
Отправка Mutation для удаления аккаунта по ключу
Отправка Mutation для удаления аккаунта по ключу
Отправка Mutation для создания нового аккаунта
Отправка Mutation для создания нового аккаунта

Остальной код можно посмотреть, перейдя по ссылке: https://github.com/gibkin/graphql-sqpr-spring-boot-starter

Tags:
Hubs:
0
Comments12

Articles