1. введение
GraphQL – это относительно новая концепция от Facebook, которая выставляется в качестве альтернативы REST для веб-API.
В этой статье мы познакомимся с настройкой сервера GraphQL с помощью Spring Boot, чтобы его можно было добавлять в существующие приложения или использовать в новых.
2. Что Такое GraphQL?
Традиционные API REST работают с концепцией ресурсов, которыми управляет сервер. Этими ресурсами можно управлять некоторыми стандартными способами, следуя различным глаголам HTTP. Это работает очень хорошо, пока наш API соответствует концепции ресурсов, но быстро разваливается, когда нам нужно отклониться от нее.
Это также страдает, когда клиенту нужны данные из нескольких ресурсов одновременно. Например, запрос сообщения в блоге и комментариев. Обычно это решается либо тем, что клиент делает несколько запросов, либо тем, что сервер предоставляет дополнительные данные, которые не всегда могут потребоваться, что приводит к увеличению размера ответов.
GraphQL предлагает решение обеих этих проблем . Он позволяет клиенту точно указать, какие данные требуются, в том числе при навигации по дочерним ресурсам в одном запросе, и позволяет выполнять несколько запросов в одном запросе.
Он также работает гораздо более RPC-способом, используя именованные запросы и мутации вместо стандартного обязательного набора действий. Это работает для того, чтобы поместить элемент управления туда, где он должен находиться, с разработчиком API, указывающим, что возможно, и потребителем API, что желательно.
Например, блог может разрешить следующий запрос:
query { recentPosts(count: 10, offset: 0) { id title category author { id name thumbnail } } }
Этот запрос будет:
- запросите десять самых последних сообщений
- для каждой должности запросите идентификатор, название и категорию
- для каждой записи запрашивайте автора, возвращая идентификатор, имя и миниатюру
В традиционном API REST для этого требуется либо 11 запросов – 1 для сообщений и 10 для авторов, либо необходимо включить сведения об авторе в сведения о сообщениях.
2.1. Схемы GraphQL
Сервер GraphQL предоставляет схему, описывающую API. Эта схема состоит из определений типов. Каждый тип имеет одно или несколько полей, каждое из которых принимает ноль или более аргументов и возвращает определенный тип.
График составляется из того, как эти поля вложены друг в друга. Обратите внимание, что нет необходимости в том, чтобы график был ациклическим – циклы вполне приемлемы, – но он направлен. То есть клиент может перейти от одного поля к своим дочерним, но он не может автоматически вернуться к родительскому, если схема не определяет это явно.
Пример схемы GraphQL для блога может содержать следующие определения, описывающие сообщение, Автора сообщения и корневой запрос для получения последних сообщений в блоге.
type Post { id: ID! title: String! text: String! category: String author: Author! } type Author { id: ID! name: String! thumbnail: String posts: [Post]! } # The Root Query for the application type Query { recentPosts(count: Int, offset: Int): [Post]! } # The Root Mutation for the application type Mutation { writePost(title: String!, text: String!, category: String) : Post! }
“!” в конце некоторых имен указывает на то, что это тип, не допускающий обнуления. Любой тип, у которого этого нет, может быть равен нулю в ответе сервера. Служба GraphQL обрабатывает их правильно, позволяя нам безопасно запрашивать дочерние поля типов, допускающих обнуление.
Служба GraphQL также предоставляет саму схему, используя стандартный набор полей, что позволяет любому клиенту заранее запросить определение схемы.
Это может позволить клиенту автоматически определять, когда изменяется схема, и позволить клиентам динамически адаптироваться к тому, как работает схема. Одним из невероятно полезных примеров этого является инструмент GraphiQL, о котором мы поговорим позже, который позволяет нам взаимодействовать с любым API GraphQL.
3. Представляем GraphQL Spring Boot Starter
Spring Boot GraphQL Starter предлагает фантастический способ запустить сервер GraphQL за очень короткое время . В сочетании с библиотекой GraphQL Java Tools нам нужно только написать код, необходимый для нашего сервиса.
3.1. Настройка Сервиса
Все, что нам нужно для этого, – это правильные зависимости:
com.graphql-java graphql-spring-boot-starter 5.0.2 com.graphql-java graphql-java-tools 5.2.4
Spring Boot автоматически подберет их и настроит соответствующие обработчики для автоматической работы.
По умолчанию это откроет службу GraphQL на конечной точке /graphql нашего приложения и будет принимать запросы POST, содержащие полезную нагрузку GraphQL. При необходимости эту конечную точку можно настроить в файле application.properties .
3.2. Написание схемы
Библиотека инструментов GraphQL работает, обрабатывая файлы схем GraphQL для построения правильной структуры, а затем подключает к этой структуре специальные компоненты. Стартер Spring Boot GraphQL автоматически находит эти файлы схем .
Эти файлы должны быть сохранены с расширением “. графика ” и может присутствовать в любом месте пути к классу. Мы также можем иметь столько этих файлов, сколько пожелаем, поэтому мы можем разделить схему на модули по желанию.
Единственное требование состоит в том, что должен быть ровно один корневой запрос и до одной корневой мутации. Это не может быть разделено между файлами, в отличие от остальной части схемы. Это ограничение самого определения схемы GraphQL, а не реализации Java.
3.3. Распознаватель корневых запросов
Корневой запрос должен иметь специальные компоненты, определенные в контексте Spring, для обработки различных полей в этом корневом запросе . В отличие от определения схемы, нет никаких ограничений на наличие только одного компонента Spring для полей корневого запроса.
Единственные требования заключаются в том, что компоненты реализуют GraphQL Query Resolver и что каждое поле в корневом запросе из схемы имеет метод в одном из этих классов с тем же именем.
public class Query implements GraphQLQueryResolver { private PostDao postDao; public ListgetRecentPosts(int count, int offset) { return postsDao.getRecentPosts(count, offset); } }
Имена метода должны быть одним из следующих в следующем порядке:
- <поле>
- is – только если поле имеет тип Boolean
- получить<поле>
Метод должен иметь параметры, соответствующие любым параметрам в схеме GraphQL, и при необходимости может принимать конечный параметр типа DataFetchingEnvironment.
Метод также должен возвращать правильный тип возврата для типа в схеме GraphQL, как мы сейчас увидим. Любые простые типы – String, Int, List, и т. Д. – может использоваться с эквивалентными типами Java, и система просто автоматически сопоставляет их.
Выше был определен метод getRecentPosts , который будет использоваться для обработки любых запросов GraphQL для поля недавние сообщения в схеме, определенной ранее.
3.4. Использование бобов для представления типов
Каждый сложный тип на сервере GraphQL представлен компонентом Java – независимо от того, загружается ли он из корневого запроса или из любого другого места в структуре. Один и тот же класс Java всегда должен представлять один и тот же тип GraphQL, но имя класса необязательно.
Поля внутри компонента Java будут напрямую отображаться на поля в ответе GraphQL на основе имени поля .
public class Post { private String id; private String title; private String category; private String authorId; }
Любые поля или методы в Javabean, которые не сопоставляются со схемой GraphQL, будут проигнорированы, но не вызовут проблем. Это важно для работы полевых распознавателей.
Например, поле AuthorID здесь не соответствует ничему в нашей схеме, которую мы определили ранее, но оно будет доступно для использования на следующем шаге.
3.5. Преобразователи полей для комплексных значений
Иногда значение поля нетривиально для загрузки. Это может включать поиск в базе данных, сложные вычисления или что-то еще. GraphQL Tools имеет концепцию преобразователя полей, который используется для этой цели. Это компоненты Spring, которые могут предоставлять значения вместо компонента данных.
Преобразователь полей-это любой компонент в контексте Spring, который имеет то же имя , что и компонент данных, с суффиксом Resolver , и который реализует интерфейс GraphQLResolver . Методы в компоненте распознавателя полей следуют всем тем же правилам, что и в компоненте данных, но также предоставляются самому компоненту данных в качестве первого параметра.
Если распознаватель полей и компонент данных имеют методы для одного и того же поля GraphQL, то распознаватель полей будет иметь приоритет.
public class PostResolver implements GraphQLResolver{ private AuthorDao authorDao; public Author getAuthor(Post post) { return authorDao.getAuthorById(post.getAuthorId()); } }
Тот факт, что эти преобразователи полей загружаются из контекста Spring, важен. Это позволяет им работать с любыми другими управляемыми бобами Spring – например, DAOS.
Важно отметить, что если клиент не запрашивает поле, то сервер GraphQL никогда не выполнит работу по его извлечению . Это означает, что если клиент получает сообщение и не запрашивает автора, то описанный выше метод getAuthor() никогда не будет выполнен, и вызов DAO никогда не будет выполнен.
3.6. Обнуляемые значения
Схема GraphQL имеет концепцию, согласно которой некоторые типы могут быть обнулены, а другие-нет.
Это может быть обработано в коде Java с помощью прямого использования нулевых значений, но в равной степени новый Необязательный тип из Java 8 может быть использован непосредственно здесь для типов, допускающих обнуление, и система будет делать правильные вещи со значениями.
Это очень полезно, так как это означает, что наш Java-код более очевидно совпадает со схемой GraphQL из определений методов.
3.7. Мутации
До сих пор все, что мы делали, было связано с получением данных с сервера. GraphQL также имеет возможность обновлять данные, хранящиеся на сервере, с помощью мутаций.
С точки зрения кода, нет никаких причин, по которым запрос не может изменить данные на сервере. Мы могли бы легко написать распознаватели запросов, которые принимают аргументы, сохраняют новые данные и возвращают эти изменения. Это вызовет неожиданные побочные эффекты для клиентов API и считается плохой практикой.
Вместо этого Мутации должны использоваться для информирования клиента о том, что это приведет к изменению хранящихся данных .
Мутации определяются в коде Java с помощью классов, реализующих GraphQLMutationResolver вместо GraphQLQueryResolver .
В противном случае применяются те же правила, что и для запросов. Возвращаемое значение из поля мутации затем обрабатывается точно так же, как и из поля запроса, позволяя также извлекать вложенные значения.
public class Mutation implements GraphQLMutationResolver { private PostDao postDao; public Post writePost(String title, String text, String category) { return postDao.savePost(title, text, category); } }
4. Введение GraphiQL
GraphQL также имеет сопутствующий инструмент под названием GraphiQL. Это пользовательский интерфейс, который может взаимодействовать с любым сервером GraphQL и выполнять запросы и мутации против него. Загружаемая версия этого приложения существует в виде электронного приложения и может быть получена из здесь .
Также можно автоматически включить веб-версию GraphiQL в наше приложение, добавив зависимость GraphiQL Spring Boot Starter:
com.graphql-java graphiql-spring-boot-starter 5.0.2
Это будет работать только в том случае, если мы размещаем наш API GraphQL на конечной точке по умолчанию /graphql , поэтому в противном случае потребуется автономное приложение.
5. Резюме
GraphQL-это очень захватывающая новая технология, которая потенциально может революционизировать способ разработки веб-API.
Сочетание Spring Boot GraphQL Starter и библиотек Java-инструментов GraphQL позволяет невероятно легко добавлять эту технологию в любые новые или существующие приложения Spring Boot.
Фрагменты кода можно найти на GitHub .