Привет, Хабр!
Меня зовут Дмитрий, и я бэкенд-разработчик в SENSE с 10-летним опытом. За это время я успел поработать с финтех-проектами, автоматизировал обработку заказов для интернет-магазинов, но GraphQL долгое время оставался для меня загадочной технологией — я просто не сталкивался с ним в работе. А когда он мне понадобился, то обнаружил, что толковых материалов по Spring-реализации GraphQL очень мало. Поэтому, я решил не только разобраться самостоятельно в теме, но и написать гайд для тех, кто, как и я, только начинает погружаться в эту тему.
Разбираться будем постепенно: в первой статье покажу, как создать проект с GraphQL с нуля. Поехали!

Создание проекта
Создайте Spring Boot проект не ниже версии 3.5.3 (Java 21 + Maven) со следующими зависимостями:
- Spring for GraphQL 
- Lombok 
- Spring Web 

Проверьте в файле pom.xml наличие 2-х главных зависимостей, которые понадобятся для примера:
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-graphql</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.graphql</groupId>
   <artifactId>spring-graphql-test</artifactId>
   <scope>test</scope>
</dependency>Проверьте папку resources на наличие:
- папки - graphql
- файла - application(дальнейшие примеры содержат настройки в формате yml)

Чтобы работать через готовый UI с GraphQL включите его через application.yml:
spring:  
 graphql:
   graphiql:
     enabled: trueСоздайте в папке graphql файл query.graphqls.
Примечание: .graphqls и .gqls являются расширениями по умолчанию. Поменять их можно в конфиге spring.graphql.schema.file-extensions
В query.graphqls (далее по тексту — “схема graphql”) создайте query метод helloWorld:
type Query {
   helloWorld: String
}Положительным результат будет считаться тогда, когда при запуске приложения и при переходе по ссылке http://localhost:8080/graphiql, вам станет доступен UI интерфейс:


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

Выполните запрос helloWorld:

Поздравляю! Первичная настройка произведена ?
Создание простого @QueryMapping
На данном этапе запрос helloWorld возвращает всегда null, чтобы это изменить, необходимо создать контроллер для работы с запросом. 
Спойлер: разработчики Spring постарались сделать опыт работы со своим фреймворком понятным для тех, кто уже работал и реализовывал REST API. Поэтому многое покажется знакомым. 
Создайте контроллер для работы с запросом helloWorld:
@Controller
public class HelloWorldController {
   @QueryMapping
   public String helloWorld() {
       return "HI!";
   }
}Имя метода должно совпадать с именем запроса из схемы graphql по умолчанию или переопределено в аннотации @QueryMapping. 
Перезапустите приложение и повторно выполните запрос. Результат будет следующим:
{
   "data": {
       "helloWorld": "HI!"
   }
}Усложняем метод:
- передаем String и выводим его в ответе; 
- делаем входящий и исходящий String обязательным посредством добавления «!» в схеме graphQL. Для этого меняем схему graphql и Controller. 
type Query {
   helloWorld(text: String!): String!
}@QueryMapping
public String helloWorld(@Argument(name = "text") String msg) {
   return msg;
}Так как название параметров отличается, то в @Argument добавили параметр name. Если название будет одинаковым, то достаточно будет добавить @Argument без параметра.
Создание простого @MutationMapping
В GraphQL запросы делятся на три типа:
- mutation; 
- query; 
- subscription (его в данной статье рассматривать не будем). 
Мутации (mutation) используются для изменения данных, в то время как запросы (query) используются для получения данных.
Хотя технически и возможно выполнить все операции через запросы, делать это не рекомендуется, поскольку может привести к путанице и усложнению кода. Настраивать схему можно в одном файле, но рекомендуется делить ее на несколько файлов для улучшения читаемости и организации кода.
Создайте новый файл mutation.graphqls для определения мутаций в вашей схеме:
type Mutation {
   mutationHelloWorld(text: String!): String!
}Отредактируйте контроллер:
private String data = "Hello, World!";
@QueryMapping
public String helloWorld(@Argument String text) {
   return text + " " + data;
}
@MutationMapping
public String mutationHelloWorld(@Argument String text) {
   data = text;
   return data;
}Теперь mutation изменяет значение data, а query возвращает свое значение + data.
Тестирование @QueryMapping и @MutationMapping

@SpringBootTest
@AutoConfigureGraphQlTester
public class HelloWorldControllerTets {
   @Autowired
   protected GraphQlTester graphQlTester;
   @Test
   void queryTest() {
       String query = """
                   query MyQuery {
                     helloWorld(text: "123")
                   }
               """;
       String response = graphQlTester.document(query).execute().path("helloWorld").entity(String.class).get();
       assertThat(response).isEqualTo("123 Hello, World!");
   }
   @Test
   void mutationTest() {
       String query = """
                   mutation MyMutation {
                     mutationHelloWorld(text: "text")
                   }
               """;
       String response = graphQlTester.document(query).execute().path("mutationHelloWorld").entity(String.class).get();
       assertThat(response).isEqualTo("text");
   }
}Ожидаемо, что если тест mutationTest будет выполнен до queryTest, то queryTest провалится. Это связано с тем, что mutationTest изменяет данные, которые затем используются в queryTest.
В этой части гайда мы рассмотрели основы работы с Spring GraphQL: настройку проекта, создание схемы, реализацию запросов и мутаций, а также их тестирование.
В следующих частях мы углубимся в более сложные аспекты:
- Работа с DataLoader для оптимизации запросов; 
- Расширенная валидация и обработка ошибок; 
- Интеграция с Spring Security и другими компонентами экосистемы Spring. 
Spring GraphQL — это мощный инструмент, который сочетает гибкость GraphQL с удобством Spring, и в следующих статьях мы раскроем его потенциал еще больше.
А как вы уже испольовали GraphQL в своих проектах или только присматриваетесь? Буду рад обратной связи и готов ответить в комментариях на все оставшиеся вопросы!
 
           
 
KoIIIeY
Почему не котлин?
Richterdg92 Автор
Привет. Основная причина, что экспертизы больше на java :)