GraphQL Java — серверная библиотека для реализации GraphQL API на Java
GraphQL Java — это мощная и гибкая серверная библиотека для реализации спецификации GraphQL на языке Java. Она позволяет разработчикам создавать эффективные, типобезопасные и легко расширяемые API, предоставляя клиентам возможность запрашивать только необходимые данные. Библиотека активно поддерживается сообществом и используется в production-среде многими крупными компаниями.
Основные возможности
- Полная поддержка спецификации GraphQL — реализация всех типов, директив, мутаций, подписок и фрагментов.
- Гибкая система типов — возможность определять схемы как на основе Java классов (code-first), так и через SDL (schema-first).
- Встроенная поддержка асинхронности — использование
CompletableFutureдля эффективной обработки запросов. - DataLoader — встроенная утилита для решения проблемы N+1 запросов и пакетной загрузки данных.
- Инструменты для тестирования — встроенные классы для unit-тестирования схем и резолверов.
- Расширяемость — поддержка кастомных скаляров, директив и инструментов валидации.
Архитектура библиотеки
Библиотека состоит из нескольких ключевых компонентов:
- GraphQLSchema — объект, представляющий схему API.
- DataFetcher — функциональный интерфейс для получения данных (аналог резолвера в GraphQL).
- TypeResolver — интерфейс для разрешения полиморфных типов (интерфейсы и union).
- ExecutionStrategy — стратегия выполнения запроса (по умолчанию асинхронная).
- Instrumentation — механизм для внедрения дополнительной логики (логирование, метрики).
Пример использования
Рассмотрим простой пример создания GraphQL сервера для управления книгами.
1. Определение схемы через SDL
// schema.graphqls
type Query {
books: [Book]
bookById(id: ID!): Book
}
type Book {
id: ID!
title: String!
author: String!
year: Int
}
2. Создание резолверов
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
public class BookDataFetcher {
public static DataFetcher<List<Book>> getBooksDataFetcher() {
return environment -> {
// В реальном приложении здесь будет запрос к БД
return List.of(
new Book("1", "1984", "George Orwell", 1949),
new Book("2", "Brave New World", "Aldous Huxley", 1932)
);
};
}
public static DataFetcher<Book> getBookByIdDataFetcher() {
return environment -> {
String id = environment.getArgument("id");
// Поиск книги по ID
return findBookById(id);
};
}
}
3. Сборка схемы и выполнение запроса
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.TypeDefinitionRegistry;
public class GraphQLExample {
public static void main(String[] args) {
// Загрузка SDL
String schema = "type Query { books: [Book] } type Book { id: ID! title: String! }";
SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry typeRegistry = schemaParser.parse(schema);
// Настройка runtime wiring
RuntimeWiring wiring = RuntimeWiring.newRuntimeWiring()
.type("Query", builder -> builder
.dataFetcher("books", BookDataFetcher.getBooksDataFetcher()))
.build();
// Генерация схемы
SchemaGenerator generator = new SchemaGenerator();
GraphQLSchema graphQLSchema = generator.makeExecutableSchema(typeRegistry, wiring);
// Создание GraphQL объекта
GraphQL graphQL = GraphQL.newGraphQL(graphQLSchema).build();
// Выполнение запроса
String query = "{ books { title } }";
ExecutionResult result = graphQL.execute(query);
System.out.println(result.getData().toString());
}
}
Работа с мутациями
Для изменения данных используются мутации. Пример добавления новой книги:
// schema
type Mutation {
addBook(title: String!, author: String!): Book!
}
// DataFetcher для мутации
public static DataFetcher<Book> addBookDataFetcher() {
return environment -> {
String title = environment.getArgument("title");
String author = environment.getArgument("author");
Book newBook = new Book(UUID.randomUUID().toString(), title, author, 2024);
// Сохранение в БД
return newBook;
};