Pular para o conteúdo principal

Introdução aos Serviços REST

Mensagem Importante para Estudantes​

ATENÇÃO: Este capítulo é uma revisão opcional.

Este capítulo é oferecido como um recurso adicional para quem deseja aprofundar sua compreensão sobre serviços web REST. Embora este conteúdo não seja obrigatório para o curso, pode ser útil para:

  • Estudantes que possuem lacunas nos conceitos de serviços web
  • Aqueles que desejam uma revisão aprofundada antes de iniciar com Spring Boot
  • Pessoas que querem entender os fundamentos teóricos do REST

Se você já está confortável com serviços web REST, pode ir diretamente para o próximo módulo.


Conteúdo do Capítulo​

Esta seção inclui quatro partes:

  • Parte 1: Apresentação do REST - Introdução à arquitetura REST, princípios-chave e conceitos stateless vs stateful
  • Parte 2: Métodos HTTP - Detalhes sobre os métodos HTTP em REST e exemplos de uso com Java
  • Parte 3: Exemplos práticos - Utilização dos métodos GET, POST, PUT e DELETE com código Java
  • Parte 4: Tratamento de erros - Códigos de status HTTP e tratamento de erros em APIs REST

Parte 1: Apresentação do REST​

REST (Representational State Transfer) é uma arquitetura de software projetada para criar serviços web escaláveis e de alto desempenho. Ela foi introduzida em 2000 por Roy T. Fielding, um dos principais criadores do protocolo HTTP. REST é baseada em um conjunto de restrições que tornam sistemas distribuídos mais simples e eficientes.

Princípios-Chave do REST​

1. Uniformidade da Interface​

As interações entre cliente e servidor são padronizadas pelo uso de métodos HTTP, URIs para identificar recursos e formatos de representação padrão como JSON ou XML. Isso permite uma comunicação clara e consistente.

2. Stateless​

O servidor não mantém nenhuma informação sobre o estado das sessões entre as requisições. Cada requisição do cliente deve conter todas as informações necessárias para processar a solicitação. Isso simplifica o gerenciamento de sessões.

3. Cacheable​

As respostas do servidor podem ser armazenadas em cache para melhorar o desempenho. As diretivas de cache são especificadas nos headers HTTP, permitindo reduzir o tempo de resposta e a carga do servidor.

4. Cliente-Servidor​

Há uma separação de responsabilidades entre o cliente (que gerencia a interface do usuário) e o servidor (que gerencia o armazenamento de dados e a lógica de negócio). Isso facilita o desenvolvimento independente da interface do usuário e do backend.

5. Sistema em Camadas (Layered System)​

A arquitetura REST pode ser construída em camadas, o que melhora a flexibilidade e a escalabilidade do sistema. Por exemplo, uma camada pode gerenciar autenticação, enquanto outra pode cuidar do armazenamento de dados.


Stateless vs Stateful​

Arquitetura Stateless​

Em REST, a arquitetura é stateless (sem estado). Isso significa que cada requisição enviada por um cliente ao servidor deve conter todas as informações necessárias para processar a solicitação. O servidor não mantém informações sobre o estado das interações anteriores, o que simplifica o gerenciamento do sistema.

Exemplo:

GET /api/users/123 HTTP/1.1
Host: example.com
Authorization: Bearer <token>

Neste exemplo, o cliente envia todas as informações necessárias para autenticar a requisição (via header Authorization) e identificar o recurso solicitado (/api/users/123).

Arquitetura Stateful​

Por outro lado, em uma arquitetura stateful (com estado), o servidor mantém o estado da sessão entre as requisições. Isso pode complicar o gerenciamento de sessões e tornar o sistema menos flexível e menos escalável.


Métodos HTTP no REST​

Os métodos HTTP são verbos que indicam a ação a ser realizada sobre um recurso identificado por uma URI (Uniform Resource Identifier). Veja os métodos mais comumente utilizados em REST.

Tabela de Métodos HTTP​

+-------------+---------------------+---------------------------------------------------------+
| Método | Descrição | Exemplos de Código |
+-------------+---------------------+---------------------------------------------------------+
| GET | Recuperar um | GET /api/users/123 HTTP/1.1 |
| | recurso | Host: example.com |
+-------------+---------------------+---------------------------------------------------------+
| POST | Criar um | POST /api/users HTTP/1.1 |
| | recurso | Host: example.com |
| | | Content-Type: application/json |
| | | |
| | | { |
| | | "name": "John Doe", |
| | | "email": "john@example.com" |
| | | } |
+-------------+---------------------+---------------------------------------------------------+
| PUT | Substituir um | PUT /api/users/123 HTTP/1.1 |
| | recurso inteiro | Host: example.com |
| | | Content-Type: application/json |
+-------------+---------------------+---------------------------------------------------------+
| PATCH | Modificar | PATCH /api/users/123 HTTP/1.1 |
| | parcialmente | Host: example.com |
| | um recurso | Content-Type: application/json |
+-------------+---------------------+---------------------------------------------------------+
| DELETE | Remover um | DELETE /api/users/123 HTTP/1.1 |
| | recurso | Host: example.com |
+-------------+---------------------+---------------------------------------------------------+

Métodos Menos Utilizados​

+-------------+---------------------+---------------------------------------------------------+
| OPTIONS | Determinar os | OPTIONS /api/users HTTP/1.1 |
| | métodos que o | Host: example.com |
| | servidor pode | |
| | tratar | Resposta: |
| | | HTTP/1.1 200 OK |
| | | Allow: GET, POST, OPTIONS |
+-------------+---------------------+---------------------------------------------------------+
| HEAD | Recuperar os | HEAD /api/users/123 HTTP/1.1 |
| | headers de um | Host: example.com |
| | recurso sem corpo | |
| | de resposta | Resposta: |
| | | HTTP/1.1 200 OK |
| | | Content-Type: application/json |
+-------------+---------------------+---------------------------------------------------------+

Headers HTTP​

Os headers HTTP são elementos importantes que fornecem informações adicionais sobre os dados transmitidos durante as requisições e respostas HTTP.

Tabela de Headers HTTP​

+-------------------+----------------------------------+------------------------------------------------+
| Header | Descrição | Exemplo de Código |
+-------------------+----------------------------------+------------------------------------------------+
| Content-Type | Especifica o tipo de conteúdo | Content-Type: application/json |
| | do recurso | |
+-------------------+----------------------------------+------------------------------------------------+
| Accept | Indica os tipos de conteúdo | Accept: application/json |
| | que o cliente aceita | |
+-------------------+----------------------------------+------------------------------------------------+
| Authorization | Fornece informações de | Authorization: Bearer <token> |
| | autenticação | |
+-------------------+----------------------------------+------------------------------------------------+
| Cache-Control | Define diretivas de cache | Cache-Control: no-cache |
| | | |
+-------------------+----------------------------------+------------------------------------------------+
| Content-Length | Especifica o tamanho do corpo | Content-Length: 348 |
| | da resposta | |
+-------------------+----------------------------------+------------------------------------------------+
| Location | Indica o local de um recurso | Location: http://example.com/api/users/123 |
| | criado | |
+-------------------+----------------------------------+------------------------------------------------+

Gerenciamento de Códigos HTTP​

Os códigos de status HTTP são usados para indicar o resultado de uma requisição HTTP.

Tabela de Códigos de Status HTTP​

+-------------------+----------------------------------+------------------------------------------------+
| Código HTTP | Significado | Exemplo de Cenário |
+-------------------+----------------------------------+------------------------------------------------+
| 200 OK | A requisição foi bem-sucedida | Resposta a uma requisição GET para recuperar um |
| | | recurso |
+-------------------+----------------------------------+------------------------------------------------+
| 201 Created | Um novo recurso foi criado | Resposta a uma requisição POST para criar um |
| | | novo usuário |
+-------------------+----------------------------------+------------------------------------------------+
| 204 No Content | A requisição foi bem-sucedida, | Resposta a uma requisição DELETE após remoção |
| | mas não há conteúdo a retornar | de um recurso |
+-------------------+----------------------------------+------------------------------------------------+
| 400 Bad Request | A requisição está malformada ou | O cliente envia uma requisição com dados |
| | contém erros | inválidos |
+-------------------+----------------------------------+------------------------------------------------+
| 401 Unauthorized | Autenticação requerida | O cliente tenta acessar um recurso sem fornecer |
| | | um token de autenticação |
+-------------------+----------------------------------+------------------------------------------------+
| 403 Forbidden | Acesso proibido | O cliente não tem permissão necessária para |
| | | acessar o recurso |
+-------------------+----------------------------------+------------------------------------------------+
| 404 Not Found | O recurso não foi encontrado | O cliente tenta acessar um recurso que não |
| | | existe |
+-------------------+----------------------------------+------------------------------------------------+
| 500 Internal | Um erro interno do servidor | Uma exceção inesperada ocorre no servidor ao |
| Server Error | ocorreu | processar a requisição |
+-------------------+----------------------------------+------------------------------------------------+

Parte 2: Métodos HTTP em Detalhes​

Em uma arquitetura REST, os métodos HTTP definem a ação que o cliente deseja realizar sobre um recurso.

Tabela Resumo​

MétodoDescriçãoUso típico
GETRecupera um recurso sem modificar seu estadoLeitura de uma página web, obtenção de dados
POSTEnvia dados para criar um novo recursoEnvio de formulário, adição de um novo registro
PUTAtualiza um recurso enviando a versão completaSubstituição ou criação de um recurso
PATCHAtualiza parcialmente um recursoModificação parcial de um recurso existente
DELETERemove um recurso específicoExclusão de um registro, de um arquivo
HEADRecupera os headers de um recurso, similar ao GET, sem o corpoVerificação da última modificação
OPTIONSConsulta o servidor sobre os métodos disponíveisPreparação de uma requisição, descoberta de métodos

Parte 3: Exemplos Práticos com Java​

Exemplo GET: Recuperar um Recurso​

@GET
@Path("/testGet")
public Response getTestResource() {
// Lógica para recuperar o recurso
return Response.ok("Recurso recuperado com sucesso").build();
}

Detalhes:

  1. @GET: Esta anotação indica que o método responderá a uma requisição HTTP GET
  2. @Path("/testGet"): Define a URL relativa para este método
  3. Response.ok(): Cria uma resposta HTTP com código 200 (OK)

Uso típico: Exibir informações ao usuário (detalhes de um usuário, produto, etc.)


Exemplo POST: Criar um Novo Recurso​

@POST
@Path("/testPost")
@Consumes(MediaType.APPLICATION_JSON)
public Response createTestResource(String json) {
// Lógica para criar um recurso a partir do JSON recebido
return Response.status(Response.Status.CREATED).entity("Recurso criado").build();
}

Detalhes:

  1. @POST: Esta anotação indica que o método responderá a uma requisição HTTP POST
  2. @Consumes(MediaType.APPLICATION_JSON): Indica que o método espera dados no formato JSON
  3. Response.Status.CREATED: Código 201 indicando que um novo recurso foi criado

Uso típico: Cadastro de um novo usuário, criação de um novo produto


Exemplo PUT: Atualizar um Recurso​

@PUT
@Path("/testPut/{id}")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateTestResource(@PathParam("id") String id, String json) {
// Lógica para atualizar o recurso identificado por id
return Response.ok("Recurso atualizado").build();
}

Detalhes:

  1. @PUT: Esta anotação indica que o método responderá a uma requisição HTTP PUT
  2. @PathParam("id"): Extrai o identificador do recurso a partir da URL
  3. Response.ok(): Código 200 para indicar que a atualização foi bem-sucedida

Uso típico: Alterar detalhes de um produto, atualizar um perfil de usuário


Exemplo DELETE: Remover um Recurso​

@DELETE
@Path("/testDelete/{id}")
public Response deleteTestResource(@PathParam("id") String id) {
// Lógica para remover o recurso identificado por id
return Response.status(Response.Status.NO_CONTENT).build();
}

Detalhes:

  1. @DELETE: Esta anotação indica que o método responderá a uma requisição HTTP DELETE
  2. Response.Status.NO_CONTENT: Código 204 indicando que um recurso foi removido sem conteúdo a retornar

Uso típico: Exclusão de um usuário, produto, comentário


Parte 4: Tratamento de Erros​

O tratamento adequado de erros é essencial em APIs REST. Veja como retornar os códigos de status mais utilizados.

Código 200 OK​

O código 200 OK indica que a requisição foi processada com sucesso.

@GET
@Path("/testGet")
public Response getTestResource() {
return Response.ok("Recurso recuperado com sucesso").build();
}

Código 301 Moved Permanently​

O código 301 Moved Permanently indica que o recurso foi movido de forma permanente.

@GET
@Path("/oldPath")
public Response redirectResource() {
return Response.status(Response.Status.MOVED_PERMANENTLY)
.location(URI.create("/newPath"))
.build();
}

Código 400 Bad Request​

O código 400 Bad Request indica que o servidor não pode processar a requisição devido a um erro do cliente.

@POST
@Path("/testPost")
@Consumes(MediaType.APPLICATION_JSON)
public Response createTestResource(String json) {
if (json == null || json.isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Dados inválidos: o corpo da requisição está vazio.")
.build();
}
return Response.status(Response.Status.CREATED)
.entity("Recurso criado")
.build();
}

Código 404 Not Found​

O código 404 Not Found é retornado quando o recurso solicitado não existe.

@GET
@Path("/testGet/{id}")
public Response getTestResource(@PathParam("id") String id) {
boolean resourceExists = false;

if (!resourceExists) {
return Response.status(Response.Status.NOT_FOUND)
.entity("Recurso não encontrado para o ID: " + id)
.build();
}
return Response.ok("Recurso encontrado").build();
}

Código 500 Internal Server Error​

O código 500 Internal Server Error indica que ocorreu um erro inesperado no servidor.

@GET
@Path("/testGet/{id}")
public Response getTestResource(@PathParam("id") String id) {
try {
String resource = retrieveResource(id);
return Response.ok(resource).build();
} catch (Exception e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erro interno do servidor: " + e.getMessage())
.build();
}
}

Recomendações para o Tratamento de Erros​

  • Utilize os códigos HTTP apropriados: Cada código tem um significado específico e permite ao cliente entender o resultado da requisição
  • Forneça mensagens de erro claras: Inclua uma mensagem explicativa no corpo da resposta
  • Considere a segurança: Não divulgue muitos detalhes técnicos para evitar fornecer informações exploráveis

Conclusão​

Este capítulo fornece uma base sólida para compreender e interagir com APIs RESTful. Esses conceitos são fundamentais para trabalhar com Spring Boot, que simplifica consideravelmente a criação de APIs REST por meio de suas anotações e auto-configuração.

Nos próximos módulos, você verá como o Spring Boot facilita a implementação desses conceitos REST de forma elegante e eficiente.