GraphQL — это язык запросов для API, который позволяет клиентам запрашивать ограниченные данные, в которых они нуждаются, что позволяет клиентам собирать данные в ограниченном количестве запросов. GraphQL — это строго типизированный протокол, и все операции с данными проверяются по схеме GraphQL.
В этой статье мы рассмотрим пример GraphQL Java и создадим простой сервер GraphQL с Spring Boot.
Вам также может понравиться:
Выход за пределы REST с GraphQL
Добавление зависимостей Maven
Создайте пример приложения Spring Boot и добавьте следующие зависимости.
- graphql-spring-boot-starter используется для включения сервлета GraphQL и становится доступным по пути / graphql. Инициализирует
GraphQLSchema
бин. - graphql-java позволяет нам писать схемы на языке схем GraphQL, который прост для понимания.
- 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, называемым языком определения схем (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, который является нашим доменным объектом. Запрос типа представляет собой запрос , который может быть сделан на сервер GraphQL для извлечения данных. Этот запрос является интерактивным, их можно изменить, и можно увидеть новые результаты. Структура запроса и результат одинаковы. Это важно в мире GraphQL, потому что мы всегда получаем ожидаемый результат.
Мы увидим рабочий пример в этой статье позже.
Мутация типа представляет запросы, которые используются для выполнения операции записи на данных.
Root Query
Объекты Query или Mutation являются корневыми объектами GraphQL. У них нет связанных классов данных. В таких случаях классы распознавателя будут реализовывать 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
}
}
Это создаст строку в таблице транспортных средств . Результат должен быть:
{
"data": {
"createVehicle": {
"id": "1"
}
}
}
Давайте теперь запустим запрос, чтобы получить данные.
query {
vehicles(count: 1)
{
id,
type,
modelCode
}
}
Выход будет:
{
"data": {
"vehicles": [
{
"id": "1",
"type": "bus",
"modelCode": "XYZ123"
}
]
}
}
Обратите внимание, что мы запрашиваем только ограниченное количество полей, мы можем изменить наш запрос, добавив или удалив поля и увидев новые результаты.
Заключение
В этой статье мы рассмотрели базовый пример GraphQL Java с Spring Boot. Ознакомьтесь с подробной документацией здесь .
Полный исходный код этого руководства можно найти на GitHub .
Дальнейшее чтение
GraphQL: основные характеристики, архитектура, плюсы и минусы
Если вам понравилась эта статья и вы хотите больше узнать о GraphQL, ознакомьтесь с этой коллекцией руководств и статей по всем вопросам, связанным с GraphQL.