O termo REST é um acrônimo e significa Representational State Transfer. Rest é um paradigma arquitetônico usado no desenvolvimento de web services. Criado por Roy Fielding em 2000 em sua tese de doutorado defendida no ano de 2000 na Universidade da Califórnia, Irvine.
Também conhecido como um web service RESTful. Web service construído em conformidade com o estilo de arquitetura REST e usa métodos HTTP.
API é um conjunto de definições e protocolos usado no desenvolvimento e na integração de software de aplicações. API é um acrônimo em inglês que significa interface de programação de aplicações. As APIs costumam ser vistas como contratos, com documentações que representam um acordo entre as partes interessadas (referência). Como exemplo podemos citar a API java (referência).
Um endpoint de um web service é a URL onde seu serviço pode ser acessado por uma aplicação cliente (referência).
Aplicações que fornecem web services precisam de clientes que têm a capacidade de realizar requisições HTTP usando todos os tipos de métodos e, portanto, precisaremos de um cliente especial para testar nossas aplicações. Vamos usar uma extensão do VSCode chamada REST Client para testar nossos serviços.
Ctrl+Alt+R
. As respostas podem ser visualizadas em um painel separado ou como um documento sem título.A seguir mostramos exemplos de uso para cada um dos principais métodos de requisição HTTP:
1. GET
GET /posts/1 HTTP/1.1
Host: jsonplaceholder.typicode.com
Neste exemplo, estamos buscando o post com ID 123 na API.
2. POST
POST /posts HTTP/1.1
Host: jsonplaceholder.typicode.com
Content-Type: application/json
{
"title": "foo",
"body": "bar",
"userId": 1
}
Aqui, estamos adicionando um novo usuário através de um modal de inscrição.
3. PUT
PUT /posts/1 HTTP/1.1
Host: jsonplaceholder.typicode.com
Content-Type: application/json
{
"id": 1,
"title": "foo",
"body": "bar",
"userId": 1
}
Neste caso, estamos atualizando o post com ID 123.
4. DELETE :
DELETE /posts/1 HTTP/1.1
Host: jsonplaceholder.typicode.com
Aqui, estamos excluindo o post com ID 123.
5. PATCH
PATCH /posts/1 HTTP/1.1
Host: jsonplaceholder.typicode.com
Content-Type: application/json
{
"title": "foo"
}
Neste exemplo, estamos alterando apenas a senha do usuário com ID 456.
Referências
Um método HTTP é idempotente se uma requisição idêntica pode ser feita uma ou mais vezes em sequência com o mesmo efeito enquanto deixa o servidor no mesmo estado. Em outras palavras, um método idempotente não deveria possuir nenhum efeito colateral (exceto para manter estatísticas). Implementados corretamente, o GET, HEAD, PUT, e DELETE são métodos idempotentes, mas não o método POST.
Servem para informar ao cliente o status de suas requisições. O servidor retorna códigos de status genéricos. As categorias de código são:
Em REST, a representação de dados primária é chamada de recurso. Como boa prática de nomenclatura de recursos REST vamos seguir as seguintes diretivas.
POST | Criar dados |
GET | Buscar dados |
PUT | Atualizar dados |
DELETE | Excluir dados |
Não faça assim
| Para buscar todos os registros |
| Para buscar registros específicos |
Faça assim
| Para buscar todos os registros |
| Para buscar registros específicos |
Não faça assim
| Para criar um novo registro |
Faça assim
| Para criar um novo registro |
Não faça assim
| Para atualizar um registro |
| Para atualizar um registro |
Faça assim
| Para atualizar um registro |
Não faça assim
| Para excluir um registro |
| Para excluir um registro |
Faça assim
| Para excluir um registro |
Podemos identificar o recurso de coleção "clientes" usando o URI "/clientes
". Podemos identificar um único recurso "cliente" usando o URI "/clientes/{id do cliente}
".
Um recurso também pode conter recursos de subcoleção. Por exemplo, o recurso de subcoleção "contas" de um "cliente" específico pode ser identificado usando o URI "/clientes/{id do cliente}/contas
" (em um domínio bancário). Da mesma forma, um recurso singleton "conta" dentro do recurso de subcoleção "contas" pode ser identificado da seguinte forma: "/clientes/{id do cliente}/contas/{id da conta}
".
Ctrl + Shift + P
e digite spring init e escolha a opção mostrada abaixo:C:\Spring\pessoa-api>
package br.iftm.edu.pessoaapi.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Pessoa {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String nome;
public Pessoa() {
}
public Pessoa(String nome) {
this.nome = nome;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return this.nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
package br.iftm.edu.pessoaapi.repository;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import br.iftm.edu.pessoaapi.domain.Pessoa;
public interface PessoaRepository extends CrudRepository<Pessoa, Integer> {
@Override
List<Pessoa> findAll();
}
package br.iftm.edu.pessoaapi.service;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import br.iftm.edu.pessoaapi.domain.Pessoa;
import br.iftm.edu.pessoaapi.repository.PessoaRepository;
@Service
public class PessoaService {
@Autowired
PessoaRepository repository;
public List<Pessoa> todos() {
return repository.findAll();
}
public Pessoa novo(Pessoa pessoa) {
return repository.save(pessoa);
}
public Optional<Pessoa> busca(Integer id) {
return repository.findById(id);
}
public Pessoa atualiza(Pessoa pessoa, Integer id) {
pessoa.setId(id);
return repository.save(pessoa);
}
public void exclui(@PathVariable Integer id) {
repository.deleteById(id);
}
}
package br.iftm.edu.pessoaapi.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import br.iftm.edu.pessoaapi.domain.Pessoa;
import br.iftm.edu.pessoaapi.service.PessoaService;
@RestController
@RequestMapping("/pessoa")
class PessoaController {
@Autowired
private PessoaService service;
@GetMapping
public List<Pessoa> recuperaTodosRegistros() {
return service.todos();
}
@PostMapping
public Pessoa criaNovoRegistro(@RequestBody Pessoa pessoa) {
return service.novo(pessoa);
}
@GetMapping("/{id}")
public Pessoa buscaUmRegistro(@PathVariable Integer id) {
return service.busca(id).orElseThrow(() -> new PessoaNaoEncontradaException(id));
}
@PutMapping("/{id}")
public Pessoa atualizaRegistro(@RequestBody Pessoa pessoa, @PathVariable Integer id) {
return service.atualiza(pessoa, id);
}
@DeleteMapping("/{id}")
void excluiRegistro(@PathVariable Integer id) {
service.exclui(id);
}
}
package br.iftm.edu.pessoaapi.controller;
public class PessoaNaoEncontradaException extends RuntimeException {
PessoaNaoEncontradaException(Integer id) {
super("Não encontrei pessoa " + id);
}
}
package br.iftm.edu.pessoaapi.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class PessoaNaoEncontradaAdvice {
@ExceptionHandler
ResponseEntity<String> employeeNotFoundHandler(PessoaNaoEncontradaException ex) {
return new ResponseEntity<String>(ex.getMessage(), HttpStatus.NOT_FOUND);
}
}
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/teste
spring.datasource.username=root
spring.datasource.password=
spring.jpa.show-sql=true
logging.level.org.springframework.web=trace