Вы когда-нибудь задумывались о том, существует ли лучший способ получения данных для ваших приложений, чем REST API? В области разработки серверной части приложений GraphQL выделился как мощная альтернатива, предлагающая более гибкий и эффективный подход к извлечению данных. Для разработчиков, знакомых с Java, интеграция GraphQL в современную серверную часть открывает доступ к масштабируемым и производительным API, настраиваемым для широкого спектра использования.
В этом блоге мы рассмотрим основные различия между GraphQL и REST, выделим уникальные преимущества использования GraphQL для получения данных и проведем вас через реализацию GraphQL API на Java с примером из реального мира.
Что такое GraphQL?
GraphQL – это язык запросов для API и среда выполнения этих запросов. В отличие от REST, где фиксированные конечные точки возвращают предопределенные данные, GraphQL позволяет клиентам запрашивать именно те данные, которые им нужны. Такая детализация делает GraphQL очень эффективным, особенно для сложных или данных-интенсивных приложений.
Преимущества подхода GraphQL:
- Детализированное извлечение данных: Клиент может запрашивать только имя и должность, без извлечения ненужных полей, таких как отдел.
- Вложенные запросы: Получение сведений о менеджере вместе с информацией о сотруднике в одном запросе.
- Развитие на основе схемы: Схема действует как контракт, облегчая эволюцию API.
Что такое REST API?
Представительное состояние передачи (REST) — это архитектурный стиль для создания API. Он использует стандартные методы HTTP, такие как GET, POST, PUT и DELETE, для выполнения операций CRUD. REST известен своей простотой и широким распространением.
Ограничения REST:
- Избыточная или недостаточная выборка данных.
- Требует нескольких конечных точек и версионирования для учета изменений.
- Не имеет встроенных возможностей реального времени.
GraphQL и REST API: В чем разница?
GraphQL и REST — это два популярных подхода к созданию API, каждый из которых имеет свои сильные стороны. Хотя REST был стандартом на протяжении многих лет, GraphQL предлагает большую гибкость и эффективность, особенно в извлечении данных и сотрудничестве между командами фронтенда и бэкенда.
Ключевые различия
- В отличие от REST, который использует несколько конечных точек и требует версионирования для изменений, GraphQL объединяет извлечение данных в один запрос и снижает необходимость в версионировании, поскольку клиенты указывают требования к данным.
- В то время как REST использует коды состояния HTTP для указания успеха или ошибок, GraphQL всегда возвращает статус 200 OK и передает ошибки в теле ответа.
- GraphQL также поддерживает обновления в реальном времени через подписки, в отличие от REST, который не имеет встроенной поддержки реального времени.
- Хотя REST широко распространен с множеством инструментов, экосистема GraphQL быстро развивается, предлагая мощные инструменты, такие как GraphiQL, для упрощения разработки.
- В заключение, в то время как REST использует заголовки для кэширования, GraphQL требует более сложных техник из-за динамических запросов, но предлагает такие варианты, как постоянные запросы для эффективного кэширования.
Основные концепции GraphQL
1. Язык определения схемы (SDL)
GraphQL имеет свою собственную типовую систему, которая используется для определения схемы API. Синтаксис для написания схем называется языком определения схемы (SDL).
2. Запросы vs. Мутации vs. Подписки
- Запросы используются для получения данных с сервера. В отличие от REST, который использует несколько фиксированных конечных точек, GraphQL использует одну конечную точку, и клиент указывает необходимые данные в запросе, предлагая гибкость.
- Мутации используются для изменения данных на сервере, например, для создания, обновления или удаления данных. Они позволяют клиентам отправлять изменения на сервер и являются необходимыми для приложений, которые нуждаются в записи данных.
- Подписки обеспечивают обновления в реальном времени, поддерживая постоянное соединение между клиентом и сервером. Когда происходит подписанное событие, сервер отправляет обновления клиенту, предоставляя непрерывные потоки данных, в отличие от запросов и мутаций, которые следуют циклу запрос-ответ.
3. Схема GraphQL
Он определяет структуру данных, которая может быть запрошена или изменена, выступая в качестве контракта между сервером и клиентом. Он указывает типы, поля и отношения, доступные для доступа клиентами. Схема обычно включает специальные корневые типы: Query для извлечения данных, Mutation для изменения данных и Subscription для обновлений в реальном времени. Эти типы совместно определяют возможности API и то, как клиенты могут с ним взаимодействовать.
4. Резолверы: Отображение запросов GraphQL на данные
Резолверы — это функции, которые обрабатывают логику извлечения данных на сервере GraphQL. Каждое поле в схеме связано с резолвером, который определяет, как извлечь или вычислить данные для этого поля. Когда выполняется запрос, сервер вызывает соответствующие резолверы для запрашиваемых полей. Резолверы могут возвращать скаляры или объекты, при этом выполнение продолжается для дочерних полей, если возвращается объект, и завершается, если возвращается скаляр. Если возвращается null, выполнение останавливается. Резолверы необходимы для отображения запросов GraphQL на фактические источники данных.
Преимущества использования GraphQL в Java
- Точное извлечение данных: Запрашивайте только те данные, которые вам нужны, ничего лишнего, обеспечивая предсказуемые и эффективные результаты.
- Единый запрос для нескольких ресурсов: Извлекайте связанные данные одним запросом, сокращая количество вызовов API.
- Система типов: Организует API по типам и полям, обеспечивая корректность запросов и ясность ошибок.
- Инструменты для разработчиков: Повышайте производительность с помощью инструментов, таких как GraphiQL, используя определения типов для улучшения построения запросов и отладки.
- Эволюция без версий: Добавление или устаревание полей без нарушения существующих запросов, обеспечивая поддержку API.
- Гибкая интеграция данных: Создание единого API над существующими данными и кодом, совместимого с различными хранилищами и языками программирования.
Настройка GraphQL API на Java
Пример из реальной жизни: Пользователи и Заказы
Представьте, что вы создаете API Справочника сотрудников для крупной организации. Цель – позволить клиентам запрашивать детали, такие как имя сотрудника, должность, отдел, а также иерархию руководства.
1. Настройка проекта
Создайте новый проект Spring Boot с помощью Spring Tool Suite или перейдя на Spring Initialiser. Затем добавьте эти зависимости в файл pom.xml
:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-graphql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.graphql</groupId>
<artifactId>spring-graphql-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2. Создайте свои сущности
Создайте сущности на Java (например, User
и Order
), чтобы представить данные, которые будут запрашиваться или изменяться через GraphQL. Например:
public class User {
strategy = GenerationType.IDENTITY) (
private Long userId;
private String name;
private String email;
private String password;
// Getters and setters...
}
public class Order {
strategy = GenerationType.IDENTITY) (
private Long orderId;
private String orderDetails;
private String address;
private int price;
private User user;
// Getters and setters...
}
3. Создайте репозитории
Создайте репозитории для взаимодействия с базой данных:
public interface UserRepository extends JpaRepository<User, Long> {}
public interface OrderRepository extends JpaRepository<Order, Long> {}
4. Создайте классы сервисов
Создайте сервисные классы для обработки бизнес-логики:
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User createUser(User user) {
return userRepository.save(user);
}
public User getUser(Long userId) {
return userRepository.findById(userId).orElseThrow(() -> new RuntimeException("User not found"));
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
public boolean deleteUser(Long userId) {
userRepository.deleteById(userId);
return true;
}
}
5. Создайте контроллеры GraphQL
Определите контроллеры GraphQL для обработки запросов и мутаций:
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
public List<User> getUsers() {
return userService.getAllUsers();
}
public User getUser( Long userId) {
return userService.getUser(userId);
}
public User createUser( String name, String email, String password) {
User user = new User();
user.setName(name);
user.setEmail(email);
user.setPassword(password);
return userService.createUser(user);
}
public boolean deleteUser( Long userId) {
return userService.deleteUser(userId);
}
}
6. Определите вашу схему GraphQL
Создайте файл schema.graphqls
в директории src/main/resources
:
type User {
userId: ID!
name: String
email: String
password: String
}
type Query {
getUsers: [User]
getUser(userId: ID!): User
}
type Mutation {
createUser(name: String, email: String, password: String): User
deleteUser(userId: ID!): Boolean
}
7. Настройте GraphQL в application.properties
При желании настройте параметры GraphQL в scr/main/resources/application.properties
:
spring.graphql.graphiql.enabled=true
8. Запустите ваше приложение
Запустите приложение SpringBoot с помощью mvn spring-boot:run
или из вашей IDE. После запуска вы можете получить доступ к конечной точке GraphQL по адресу /graphiql
.
9. Тестируйте с помощью запросов GraphQL
Тестируйте API GraphQL с помощью инструмента, такого как GraphiQL или Postman.
Для мутации:
mutation {
createUser(
name:"swetha",
email:"[email protected]",
password:"23sde4dfg43"
){
name,
userId
}
}
Вывод:
{
"data": {
"createUser": {
"name": "swetha",
"userId": "3"
}
}
}
Для запроса:
query{
getUsers{
name
}
}
Вывод:
{
"data": {
"getUsers": [
{
"name": "Medha"
},
{
"name": "Riya"
},
{
"name": "swetha"
}
]
}
}
Расширенные функции GraphQL
1. Повышение повторного использования с помощью фрагментов
Фрагмент – это, по сути, повторно используемый набор полей, определенный для конкретного типа. Это функция, которая помогает улучшить структуру и повторное использование вашего кода GraphQL.
2. Параметризация полей с помощью аргументов
В GraphQL поля могут принимать аргументы, чтобы сделать запросы более динамичными и гибкими. Эти аргументы позволяют фильтровать или настраивать данные, возвращаемые API.
3. Постраничная навигация и сортировка с помощью GraphQL
Постраничная навигация
Постраничная навигация является сложной темой в проектировании API. На высоком уровне существуют два основных подхода к ее решению.
- Ограничение-смещение: Запрос конкретного фрагмента списка путем указания индексов элементов, которые требуется извлечь (фактически вы указываете начальный индекс (смещение) а также количество элементов для извлечения (ограничение)).
- На основе курсора: Эта модель постраничной навигации немного более продвинута. Каждый элемент в списке ассоциирован с уникальным идентификатором (курсором). Клиенты, выполняющие постраничную навигацию по списку, предоставляют курсор начального элемента а также количество элементов для извлечения.
Сортировка
С помощью проектирования API GraphQL возможно возвращать списки элементов, отсортированных (упорядоченных) согласно определенным критериям.
Проблемы и соображения при использовании GraphQL
- Сложность: Управление схемами GraphQL и запросами может быть вызовом для простых моделей данных или неопытных команд.
- Проблемы производительности: Глубоко вложенные запросы могут нагружать ресурсы бэкенда, если они не оптимизированы.
- Проблемы с кэшированием: Стандартные стратегии кэширования на основе REST не подходят и требуют специальных решений.
- Проблемы безопасности: Избыточные запросы и зловредные запросы требуют ограничения запросов и других мер безопасности.
- Гибридное использование: Лучше всего подходит для сложных потребностей в данных, часто сочетается с REST для более простых операций.
Заключение
GraphQL предлагает гибкий и эффективный подход к созданию современных API на Java, что делает его идеальным выбором для динамичных и данных-интенсивных приложений. Его архитектура с одним конечным точком и сильная типизация упрощают проектирование API, обеспечивая при этом надежную производительность. Независимо от того, создаете ли вы простой справочник сотрудников или сложную аналитическую платформу, GraphQL дает разработчикам возможность предоставить масштабируемые решения с легкостью. Начните изучать GraphQL уже сегодня с помощью инструментов, таких как Spring Boot и graphql-java
, чтобы разблокировать его полный потенциал в вашем следующем проекте.
Исходный код
Вы можете найти полный исходный код этого учебника на Github.
Source:
https://dzone.com/articles/design-scalable-java-apis-with-graphql