Você já se perguntou se existe uma maneira melhor de buscar dados para suas aplicações do que as APIs REST? No desenvolvimento de back-end, GraphQL surgiu como uma alternativa poderosa, oferecendo uma abordagem mais flexível e eficiente para a busca de dados. Para desenvolvedores familiarizados com Java, integrar GraphQL em um back-end moderno abre as portas para APIs escaláveis e de alto desempenho, adaptadas a uma ampla gama de casos de uso.
Este blog irá explorar as principais diferenças entre GraphQL e REST, destacar os benefícios únicos de usar GraphQL para busca de dados e guiá-lo na implementação de uma API GraphQL em Java com um exemplo do mundo real.
O que é GraphQL?
GraphQL é uma linguagem de consulta para APIs e um tempo de execução para executar essas consultas. Ao contrário do REST, onde endpoints fixos retornam dados pré-definidos, o GraphQL permite que os clientes solicitem exatamente os dados de que precisam. Essa granularidade torna o GraphQL altamente eficiente, particularmente para aplicações complexas ou intensivas em dados.
Vantagens da abordagem GraphQL:
- Busca de Dados Granular: O cliente pode consultar apenas nome e cargo sem recuperar campos desnecessários, como departamento.
- Consultas Aninhadas: Busque os detalhes do gerente junto com as informações do funcionário em uma única consulta.
- Desenvolvimento Orientado a Esquema: O esquema atua como um contrato, facilitando a evolução da API.
O que é API REST?
O Representational State Transfer (REST) é um estilo arquitetural para construir APIs. Ele utiliza métodos HTTP padrão como GET, POST, PUT e DELETE para realizar operações CRUD. O REST é conhecido por sua simplicidade e ampla adoção.
Limitações do REST:
- Sobrebusca ou sub-busca de dados.
- Requer múltiplos pontos de extremidade e versionamento para acomodar alterações.
- Sem capacidades embutidas em tempo real.
GraphQL vs. REST API: Qual a Diferença?
O GraphQL e o REST são duas abordagens populares para construir APIs, cada uma com suas fortalezas. Enquanto o REST foi o padrão por anos, o GraphQL oferece mais flexibilidade e eficiência, especialmente na recuperação de dados e na colaboração entre equipes front-end e back-end.
Diferenças Chave
- Ao contrário do REST, que usa múltiplos pontos de extremidade e requer versionamento para alterações, o GraphQL consolida a recuperação de dados em uma única consulta e reduz a necessidade de versionamento, já que os clientes especificam os requisitos de dados.
- Enquanto o REST usa códigos de status HTTP para indicar sucesso ou erros, o GraphQL sempre retorna um status 200 OK e comunica erros no corpo da resposta.
- O GraphQL também suporta atualizações em tempo real por meio de assinaturas, ao contrário do REST, que não possui suporte embutido em tempo real.
- Embora o REST esteja amplamente estabelecido com muitas ferramentas, o ambiente do GraphQL cresceu rapidamente, oferecendo ferramentas poderosas como o GraphiQL para um desenvolvimento mais fácil.
- Por último, enquanto o REST usa cabeçalhos para cache, o GraphQL requer técnicas mais avançadas devido a consultas dinâmicas, mas oferece opções como consultas persistentes para um cache eficiente.
Conceitos Fundamentais do GraphQL
1. Linguagem de Definição de Esquema (SDL)
O GraphQL tem seu próprio sistema de tipos que é usado para definir o esquema de uma API. A sintaxe para escrever esquemas é chamada de Linguagem de Definição de Esquema (SDL).
2. Consultas vs. Mutations vs. Subscrições
- Consultas são usadas para buscar dados do servidor. Diferente do REST, que usa múltiplos pontos finais fixos, o GraphQL utiliza um único ponto final, e o cliente especifica os dados necessários na consulta, oferecendo flexibilidade.
- Mutations são usadas para modificar dados no servidor, como criar, atualizar ou deletar dados. Elas permitem que os clientes enviem alterações para o backend e são essenciais para aplicações que precisam escrever dados.
- Subscrições possibilitam atualizações em tempo real mantendo uma conexão estável entre o cliente e o servidor. Quando um evento subscrito ocorre, o servidor envia atualizações para o cliente, proporcionando fluxos de dados contínuos, ao contrário de consultas e mutações, que seguem um ciclo de solicitação-resposta.
3. Esquema do GraphQL
Ele define a estrutura de dados que pode ser consultada ou alterada, atuando como um contrato entre o servidor e o cliente. Especifica os tipos, campos e relacionamentos disponíveis para os clientes acessarem. O esquema normalmente inclui tipos de raiz especiais: Query para recuperação de dados, Mutation para modificar dados e Subscription para atualizações em tempo real. Esses tipos definem coletivamente as capacidades da API e como os clientes podem interagir com ela.
4. Resolvedores: Mapeando Consultas GraphQL para Dados
Resolvedores são funções que lidam com a lógica para buscar dados em um servidor GraphQL. Cada campo em um esquema está vinculado a um resolvedor, que determina como recuperar ou calcular os dados para esse campo. Quando uma consulta é executada, o servidor invoca os resolvedores apropriados para os campos solicitados. Resolvedores podem retornar escalares ou objetos, com a execução continuando para campos filhos se um objeto for retornado e completando se um escalar for retornado. Se null for retornado, a execução para. Resolvedores são essenciais para mapear consultas GraphQL para as fontes de dados reais.
Benefícios de Usar GraphQL em Java
- Busca Exata de Dados: Consulte apenas os dados necessários, nada mais, garantindo resultados previsíveis e eficientes.
- Única Solicitação para Múltiplos Recursos: Busque dados relacionados em uma única consulta, reduzindo várias chamadas de API.
- Sistema de Tipos: Organiza APIs por tipos e campos, garantindo que as consultas sejam válidas e os erros sejam claros.
- Ferramentas para Desenvolvedores: Aumente a produtividade com ferramentas como GraphiQL, usando definições de tipo para uma melhor construção e depuração de consultas.
- Evolução sem versão: Adicione ou deprecie campos sem quebrar as consultas existentes, mantendo as APIs mantidas.
- Integração de Dados Flexível: Crie uma API unificada sobre dados e código existentes que seja compatível com vários mecanismos de armazenamento e linguagens.
Configurando uma API GraphQL em Java
Exemplo do Mundo Real: Usuários e Pedidos
Imagine que você esteja construindo uma API de Diretório de Funcionários para uma grande organização. O objetivo é permitir que os clientes consultem detalhes como nome do funcionário, cargo, departamento e até mesmo sua hierarquia de reporte.
1. Configurar o Projeto
Crie um novo projeto Spring Boot usando o Spring Tool Suite ou acessando o Spring Initialiser. Em seguida, adicione essas dependências ao arquivo 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. Crie Suas Entidades
Crie entidades Java (por exemplo, Usuário
e Pedido
) para representar os dados que serão consultados ou modificados via GraphQL. Por exemplo:
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. Crie Repositórios
Crie repositórios para interagir com o banco de dados:
public interface UserRepository extends JpaRepository<User, Long> {}
public interface OrderRepository extends JpaRepository<Order, Long> {}
4. Crie Classes de Serviço
Crie classes de serviço para lidar com a lógica de negócios:
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. Crie Controladores GraphQL
Defina controladores GraphQL para lidar com consultas e mutações:
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. Defina seu Esquema GraphQL
Crie um arquivo schema.graphqls
no diretório 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. Configure o GraphQL no application.properties
Opcionalmente, configure as configurações do GraphQL em scr/main/resources/application.properties
:
spring.graphql.graphiql.enabled=true
8. Execute sua Aplicação
Execute a aplicação SpringBoot usando mvn spring-boot:run
ou a partir do seu IDE. Uma vez em execução, você pode acessar o endpoint GraphAL em /graphiql
.
9. Teste com Consultas GraphQL
Teste a API GraphQL usando uma ferramenta como GraphiQL ou Postman.
Para Mutação:
mutation {
createUser(
name:"swetha",
email:"[email protected]",
password:"23sde4dfg43"
){
name,
userId
}
}
Saída:
{
"data": {
"createUser": {
"name": "swetha",
"userId": "3"
}
}
}
Para Consulta:
query{
getUsers{
name
}
}
Saída:
{
"data": {
"getUsers": [
{
"name": "Medha"
},
{
"name": "Riya"
},
{
"name": "swetha"
}
]
}
}
Recursos Avançados do GraphQL
1. Aumentando a Reutilização com Fragmentos
Um fragmento é basicamente um conjunto reutilizável de campos definidos para um tipo específico. É um recurso que ajuda a melhorar a estrutura e a reutilização do seu código GraphQL.
2. Parametrizando Campos com Argumentos
No GraphQL, os campos podem aceitar argumentos para tornar as consultas mais dinâmicas e flexíveis. Esses argumentos permitem filtrar ou personalizar os dados retornados pela API.
3. Paginando e Classificando com GraphQL
Paginção
A paginação é um tópico complicado no design de APIs. Em um nível alto, existem duas abordagens principais sobre como isso pode ser tratado.
- Limite-deslocamento: Solicitar um pedaço específico da lista fornecendo os índices dos itens a serem recuperados (na verdade, você está principalmente fornecendo o índice inicial (deslocamento) e uma contagem dos itens a serem recuperados (limite)).
- Baseado em cursor: Este modelo de paginação é um pouco mais avançado. Cada elemento na lista está associado a um ID único (o cursor). Clientes que paginam pela lista fornecem então o cursor do elemento inicial, bem como uma contagem dos itens a serem recuperados.
Classificação
Com o Design de API GraphQL, é possível retornar listas de elementos que estão ordenados (classificados) de acordo com critérios específicos.
Desafios e Considerações ao Usar GraphQL
- Complexidade: Gerenciar esquemas e consultas GraphQL pode ser desafiador para modelos de dados simples ou equipes inexperientes.
- Problemas de Desempenho: Consultas profundamente aninhadas podem sobrecarregar os recursos do backend se não forem otimizadas.
- Desafios de Cache: Estratégias de cache padrão baseadas em REST não se aplicam e requerem soluções personalizadas.
- Preocupações de Segurança: O excesso de consultas e consultas maliciosas exigem limites de consulta e outras salvaguardas.
- Uso Híbrido: Funciona melhor para necessidades de dados complexas, muitas vezes combinado com REST para operações mais simples.
Conclusão
GraphQL oferece uma abordagem flexível e eficiente para a construção de APIs modernas em Java, tornando-se uma escolha ideal para aplicações dinâmicas e intensivas em dados. Sua arquitetura de único ponto de extremidade e tipagem forte simplificam o design da API, garantindo ao mesmo tempo um desempenho robusto. Seja criando um diretório simples de funcionários ou uma plataforma complexa de análise, o GraphQL capacita os desenvolvedores a entregar soluções escaláveis com facilidade. Comece a explorar o GraphQL hoje com ferramentas como Spring Boot e graphql-java
para desbloquear todo o seu potencial em seu próximo projeto.
Código Fonte
Você pode encontrar o código fonte completo para este tutorial no Github.
Source:
https://dzone.com/articles/design-scalable-java-apis-with-graphql