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étodo | Descrição | Uso típico |
|---|---|---|
GET | Recupera um recurso sem modificar seu estado | Leitura de uma página web, obtenção de dados |
POST | Envia dados para criar um novo recurso | Envio de formulário, adição de um novo registro |
PUT | Atualiza um recurso enviando a versão completa | Substituição ou criação de um recurso |
PATCH | Atualiza parcialmente um recurso | Modificação parcial de um recurso existente |
DELETE | Remove um recurso específico | Exclusão de um registro, de um arquivo |
HEAD | Recupera os headers de um recurso, similar ao GET, sem o corpo | Verificação da última modificação |
OPTIONS | Consulta o servidor sobre os métodos disponíveis | Preparaçã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:
- @GET: Esta anotação indica que o método responderá a uma requisição HTTP GET
- @Path("/testGet"): Define a URL relativa para este método
- 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:
- @POST: Esta anotação indica que o método responderá a uma requisição HTTP POST
- @Consumes(MediaType.APPLICATION_JSON): Indica que o método espera dados no formato JSON
- 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:
- @PUT: Esta anotação indica que o método responderá a uma requisição HTTP PUT
- @PathParam("id"): Extrai o identificador do recurso a partir da URL
- 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:
- @DELETE: Esta anotação indica que o método responderá a uma requisição HTTP DELETE
- 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.