Как стать автором
Обновить

Примеры GraphQL на Java для начинающих [со Spring Boot]

Время на прочтение 8 мин
Количество просмотров 28K
Автор оригинала: Swathi Prasad

В этой статье мы рассмотрим пример GraphQL на Java и создадим простой сервер GraphQL со Spring Boot.



Таким цыпочкам тоже нравятся примеры GraphQL на Java со Spring Boot!


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


В этой статье мы рассмотрим пример GraphQL на Java и создадим простой сервер GraphQL со Spring Boot.


Добавление зависимостей Maven


Создайте пример Spring Boot приложения и добавьте следующие зависимости.


  1. graphql-spring-boot-starter используется для включения сервлета GraphQL и будет доступен по пути /graphql. Он инициализирует GraphQLSchema бин.
  2. graphql-java позволяет нам писать схемы на языке схем GraphQL, который прост для понимания.
  3. graphiql-spring-boot-starter предоставляет пользовательский интерфейс, с помощью которого мы сможем тестировать наши запросы на GraphQL и просматривать определения запросов.

        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-spring-boot-starter</artifactId>
            <version>5.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-java-tools</artifactId>
            <version>5.2.4</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphiql-spring-boot-starter</artifactId>
            <version>5.0.2</version>
        </dependency>

    Вот полное содержимое файла POM.

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.techshard.graphql</groupId>
    <artifactId>springboot-graphql</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath />
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-spring-boot-starter</artifactId>
            <version>5.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-java-tools</artifactId>
            <version>5.2.4</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphiql-spring-boot-starter</artifactId>
            <version>5.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    </project>

    Создание сущности и репозитория JPA


    Давайте создадим простую сущность с именем Vehicle и соответствующий JPA репозиторий. Мы будем использовать Lombok, чтобы избежать написания шаблоного кода, такого как геттеры, сеттеры и так далее.



    package com.techshard.graphql.dao.entity;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    import javax.persistence.*;
    import java.io.Serializable;
    import java.time.LocalDate;
    @Data
    @EqualsAndHashCode
    @Entity
    public class Vehicle implements Serializable {
        private static final long serialVersionUID = 1L;
        @Id
        @Column(name = "ID", nullable = false)
        @GeneratedValue(strategy = GenerationType.AUTO)
        private int id;
        @Column(name = "type", nullable = false)
        private String type;
        @Column(name = "model_code", nullable = false)
        private String modelCode;
        @Column(name = "brand_name")
        private String brandName;
        @Column(name = "launch_date")
        private LocalDate launchDate;
        private transient  String formattedDate;
        // Getter and setter
        public String getFormattedDate() {
            return getLaunchDate().toString();
        }
    }

    Вот соответствующий репозиторий JPA.


    package com.techshard.graphql.dao.repository;
    import com.techshard.graphql.dao.entity.Vehicle;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    @Repository
    public interface VehicleRepository extends JpaRepository<Vehicle, Integer> {
    }

    Схема GraphQL


    GraphQL поставляется с собственным языком для написания схем GraphQL, который называется Schema Definition Language (SDL — язык определения схемы). Определение схемы состоит из всех функций API, доступных в конечной точке.


    Типичный пример схемы GraphQL будет выглядеть так:


    type Vehicle {
    id: ID!,
    type: String,
    modelCode: String,
    brandName: String,
    launchDate: String
    }
    type Query {
    vehicles(count: Int):[Vehicle]
    vehicle(id: ID):Vehicle
    }
    type Mutation {
    createVehicle(type: String!, modelCode: String!, brandName: String, launchDate: String):Vehicle
    }

    Создайте папку graphql в папке src/main/resources и в ней создайте файл vehicleql.graphqls. Скопируйте вышеуказанное содержимое и вставьте его в файл vehicleql.graphqls. Обратите внимание, что именем файла может быть любое имя по вашему выбору. Просто убедитесь, что у имени файла есть расширение .graphqls.


    В приведенной выше схеме каждый объект имеет определенный тип. Система типов в GraphQL является базовым компонентом и она представляет тип объекта, который можно получить от сервиса и полей, которые содержит объект.


    В нашей схеме есть объект с именем Vehicle, который является нашим объектом домена. Тип Query представляет запрос, который можно сделать на сервер GraphQL для извлечения данных. Этот запрос является интерактивным, данные можно изменить, и новые результаты можно увидеть. Структура запроса и результат одинаковы. Это важно в мире GraphQL, потому что мы всегда получаем ожидаемый результат.


    Ниже в этой статье мы увидим рабочий пример.


    Тип Mutation представляет запросы, которые используются для выполнения операций записи данных.


    Root Query


    Объекты Query или Mutation являются основными объектами GraphQL. У них нет связанных классов данных. В таких случаях классы распознавателя (resolver) будут реализовывать GraphQLQueryResolver или GraphQLMutationResolver. Эти распознаватели будут искать методы, которые соответствуют полями в соответствующих основных типах.


    Давайте определим основные распознаватели для Vehicle.


    package com.techshard.graphql.query;
    import com.coxautodev.graphql.tools.GraphQLQueryResolver;
    import com.techshard.graphql.dao.entity.Vehicle;
    import com.techshard.graphql.service.VehicleService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import java.util.List;
    import java.util.Optional;
    @Component
    public class VehicleQuery implements GraphQLQueryResolver {
        @Autowired
        private VehicleService vehicleService;
        public List<Vehicle> getVehicles(final int count) {
            return this.vehicleService.getAllVehicles(count);
        }
        public Optional<Vehicle> getVehicle(final int id) {
            return this.vehicleService.getVehicle(id);
        }
    }

    В этом классе реализованы методы для получения одного объекта Vehicle и списка объектов Vehicle. Обратите внимание, что мы определили эти методы в нашей схеме выше.


    Теперь давайте определим распознаватель мутаций.


    package com.techshard.graphql.mutation;
    import com.coxautodev.graphql.tools.GraphQLMutationResolver;
    import com.techshard.graphql.dao.entity.Vehicle;
    import com.techshard.graphql.service.VehicleService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import java.time.LocalDate;
    @Component
    public class VehicleMutation implements GraphQLMutationResolver {
        @Autowired
        private VehicleService vehicleService;
        public Vehicle createVehicle(final String type, final String modelCode, final String brandName, final String launchDate) {
            return this.vehicleService.createVehicle(type, modelCode, brandName, launchDate);
        }
    }

    В этом классе у нас есть только один метод для создания объекта Vehicle, и это соответствует типу Mutation в нашем определении схемы.


    Теперь мы определим сервис, который будет выполнять реальные транзакции.


    package com.techshard.graphql.service;
    import com.techshard.graphql.dao.entity.Vehicle;
    import com.techshard.graphql.dao.repository.VehicleRepository;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    import java.time.LocalDate;
    import java.util.List;
    import java.util.Optional;
    import java.util.stream.Collectors;
    @Service
    public class VehicleService {
        private final VehicleRepository vehicleRepository ;
        public VehicleService(final VehicleRepository vehicleRepository) {
            this.vehicleRepository = vehicleRepository ;
        }
        @Transactional
        public Vehicle createVehicle(final String type,final String modelCode, final String brandName, final String launchDate) {
            final Vehicle vehicle = new Vehicle();
            vehicle.setType(type);
            vehicle.setModelCode(modelCode);
            vehicle.setBrandName(brandName);
            vehicle.setLaunchDate(LocalDate.parse(launchDate));
            return this.vehicleRepository.save(vehicle);
        }
        @Transactional(readOnly = true)
        public List<Vehicle> getAllVehicles(final int count) {
            return this.vehicleRepository.findAll().stream().limit(count).collect(Collectors.toList());
        }
        @Transactional(readOnly = true)
        public Optional<Vehicle> getVehicle(final int id) {
            return this.vehicleRepository.findById(id);
        }
    }

    Тестирование приложения


    Приложение теперь готово к тестированию. Запустите приложение Spring Boot и откройте в браузере эту ссылку: http://localhost:8080/graphiql. Мы увидим хороший пользовательский интерфейс, как показано ниже.



    В правой части пользовательского интерфейса мы можем изучить документацию.



    Теперь запустите следующий запрос.


    mutation {
      createVehicle(type: "car", modelCode: "XYZ0192", brandName: "XYZ", launchDate: "2016-08-16") 
      {
        id
      }
    }

    Это создаст строку в таблице Vehicle. Результат должен быть:


    {
      "data": {
        "createVehicle": {
          "id": "1"
        }
      }
    }

    Давайте теперь запустим запрос, чтобы получить данные.


    query {
      vehicles(count: 1) 
      {
        id, 
        type, 
        modelCode
    }
    }

    Вывод будет выглядеть так:


    {
      "data": {
        "vehicles": [
          {
            "id": "1",
            "type": "bus",
            "modelCode": "XYZ123"
          }
        ]
      }
    }

    Обратите внимание, что мы запрашиваем только ограниченное количество полей, мы можем изменить наш запрос, добавив или удалив поля и увидев новые результаты.


    Вывод


    В этой статье мы рассмотрели базовый пример GraphQL на Java со Spring Boot. Ознакомьтесь с подробной документацией здесь.


    Полный исходный код этого руководства можно найти на GitHub.


    Дальнейшее чтение


    Introduction to GraphQL


    GraphQL: Core Features, Architecture, Pros, and Cons


    Если вам понравилась эта статья и вы хотите больше узнать о GraphQL, ознакомьтесь с этой коллекцией учебников и статей по всем вопросам, связанным с GraphQL.


    Прим. Переводчика.
    На русском языке также есть «Руководство по GraphQL для начинающих»
Теги:
Хабы:
+6
Комментарии 2
Комментарии Комментарии 2

Публикации

Истории

Работа

Java разработчик
359 вакансий

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн
PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн