Como criar uma API REST com Spring
Published: 2021-03-21 20:24:40


Hoje vou demostrar como criar uma API REST que precisará controlar a aplicação de vacinas entre a população brasileira, de forma rápida e fácil.
Para começar o projeto, é necessário criarmos um projeto Spring (pode ser feita com o auxílio do Spring Initalizer, que expliquei como funciona em um dos artigos anteriores) e acrescentei algumas dependências necessárias ao projeto no arquivo Pom.xml (possui as bibliotecas de um projeto Spring, sendo gerenciado pelo Maven).

Para este projeto, utilizei as seguintes dependências: Spring Boot Starter, que oferece diversas bibliotecas bem úteis para se desenvolver um projeto Spring; Lombok para facilitar a anotação das classes e atributos e o banco em memória H2, que acabei escolhendo por ser um banco rápido e simples de configurar e de se utilizar.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4lul1q6vbwjo4k7zaju.jpg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dnetzvi8eqtey9cw64lf.jpg)

Em seguida, vamos criar as entidades (no caso, as duas tabelas do banco de dados) de cadastro de usuários e de aplicação de vacinas. Em ambas as classes, vamos colocar algumas anotações do Lombok, como o @Id para referenciar a chave primária da tabela, o @Column onde coloco o nome da coluna na tabela e a @Entity, para referenciar a classe como uma Entidade (para ser gerenciada de melhor forma pelo Spring). Na chave primária, colocaremos uma anotação para gerar automaticamente a sequência do Id do tipo IDENTITY, através da anotação @GeneratedValue.


Na classe de entidade de cadastro de usuários, declararemos o atributo data de nascimento como Data e inseri a anotação de @JsonFormat para formatar a data recebida para o padrão brasileiro (dd/mm/yyyy). Vamos agora declarar o id do usuário como Long, e o nome, email e CPF como String. Por fim, gerei os Getter, Setter e Construtores com e sem argumentos de forma manual, sem utilizar anotações do Lombok.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3h69v583abjyc8kbf550.jpg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fs7h8c89bixjk0xsdu5i.jpg)


Na classe de entidade de aplicação de vacinas, vamos declarar o atributo data da vacina como Data com a anotação @JsonFormat também. Depois disso, declararemos o id do usuário como Integer, e o nome da vacina e o email do usuário como String, com esses campos sendo do tipo não nulo (ou seja, são campos obrigatórios). Por fim, vamos gerar os Getter, Setter e Construtores com e sem argumento (acabei adicionando a anotação @Data - que gera todos os métodos que citei acima de forma automática - e só acabei percebendo na revisão do texto, tornando redundante a geração dos códigos boilerplate de forma manual).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v4aqfsii55sqqiuieizq.jpg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/prkza52qn5bz9zf8wzxw.jpg)

Terminado as classes de entidade da tabela, vamos criar as classes de Repository referentes as duas tabelas. O repository é onde fica a classe que fará transações com o banco de dados, ou seja, é um Design Pattern onde os dados são obtidos do banco de dados e é onde ocorre também a regra de negócio, e este, retorna objetos de domínio que seriam as Entidades (classes anotadas com @Entity). Esta classe vai estender o JpaRepository, que é a biblioteca que fará o acesso e comunicação com o banco de dados em memória, e que já traz diversos métodos de transações de dados por padrão, que são muito utilizados durante o desenvolvimento de uma API, como os métodos para salvar entidade, buscar por id, buscar tudo, deletar por id, update por id, entre outros.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5udd56u7mf93x9k28ci2.jpg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xfizn8zkq3ay89uv0y2d.jpg)

Após criar as classes de repositório, vamos criar as interfaces das classes Service, para organizar melhor o código. Em ambas as classes, vamos criar um método para salvar os dados da vacina aplicada e do usuário, passando como atributo a própria entidade e retornando-a também.

O Service é outro Design Pattern onde há somente a regra de negócio, ele não tem acesso direto ao banco de dados. É a subcamada responsável pela regra de negócio (valida dados, executa regras de negócios, usa a Repository e a Entity para ter acesso ao banco de dados e persistir os dados).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7plbvzuytgdtge76fuwt.jpg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6o0a681igbrb5se38ww.jpg)

Em seguida, vamos implementar os métodos da interface de Service. Para isso, vamos criar ambas as respectivas classes, anotá-las com @Service (para serem melhor gerenciadas pelo Spring) e implementar as respectivas interfaces. Com isso, é possível gerar os métodos de forma mais fácil, utilizando apenas a sobrescrita (marcadas pela anotação @Override).

Para implementar a lógica do serviço de fato, vamos coneçar fazendo a injeção de dependência (com a anotação @Autowired), para conseguir utilizar o Repository e os métodos que estão sendo estendidos da JpaRepository. Dentro dos métodos de salvar que sobrescrevi, precisamos apenas retornar a instância que foi injetada do Repository e chamar o método save (do JpaRepository), passando como parâmetro os dados do usuário e da aplicação da vacina, respectivamente. O método save vai pegar a entidade (que será passada em formato JSON), fazer a comunicação com o banco de dados, enviar os dados para o banco, e retornar o status da operação (se foi bem sucedida ou ocorreu algum erro durante a transação de dados).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9geqpe4xit145d5fkp3x.jpg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jnl3haqm4eztm1dm3v87.jpg)

Por fim, vamos criar as classes Controller da aplicação. Essas classes são utilizadas para lidar com a ligação da View com as outras partes do sistema, que são as regras de negócios e o banco de dados. Anotei essas classes com @RestController (para serem gerenciadas pelo Spring) e com @RequestMapping, indicado para o Spring qual é a rota dos endpoints que ele deve redirecionar as requisições. No Controller do Usuário, vamos utilizar a rota "/usuário", e no controller de Aplicação Vacina utilizei a rota "/vacinas".

Para desenvolver a lógica das classes de controle, primeiramente precisamos fazer a injeção de dependências da implementação do Service. Em seguida, criaremos o método para fazer a persistência dos dados. Vamos anotar ambas as classes com @PostMapping, para indicar ao Spring que trata-se de uma requisição do tipo POST (ou seja, que está fazendo uma persistência de dados diretamente no banco de dados) e a anotação @ReponseStatus, que vai retornar o status HTTP 201 Created, caso a operação seja bem sucedida.

Dentro dos métodos, vamos passar por parâmetro uma entidade de usuário e de aplicação de vacinas, respectivamente, utilizando a anotação @RequestBody (utilizada para requisitar um corpo de argumentos em métodos HTTP). Por fim, retornaremos a instância que foi injetada do Service e chamo o método que criei (salvarUsuário e salvarAplicaçãoVacina, respectivamente).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pvh6t3vqrkvxxwgmbw0b.jpg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mcsds0p9b2w3bewzdmk8.jpg)

Para testar se a aplicação está funcionando corretamente (salvando o usuário e a aplicação de vacina e retornando o status correto), utilizei a ferramenta Postman, para simular a persistência dos dados através de um JSON, conforme pode ser visto a seguir:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e2xwc9v0f5iig4x9m2cx.jpg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x1x1dn0wf5numharw3p5.jpg)

Passei um JSON com os dados referentes ao cadastro de um Usuário e de uma Aplicação da Vacina, e em ambos os casos, o Postman retornou o status HTTP 201 Created, indicando que os dados foram persistidos no banco em memória H2 com sucesso.

Também vamos simular uma requisição com dados errados, tentando passar o email do usuário como sendo um número (ao invés de texto). Quando fiz isso, o Postman retornou o status HTTP 400 Bad Request, indicando que nós passamos os dados em um formato inválido (como esperado). Além disso, podemos ver o stacktrace de erro gerado pelo software, que mostra com mais detalhes por que o erro aconteceu e quais locais da aplicação o método passou até estourar o erro.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rrsa9uoa7krizsld8dvj.jpg)

Compartilho aqui também a estrutura de pacotes e classes que utilizei na construção do projeto, que fiz com base no padrão de arquitetura MVC. Para desenvolvimento, utilizei a ferramenta Spring Tools Suite. E também mostro o Console Log gerado durante a aplicação do projeto Spring, rodando diretamente pela IDE.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8nxcxfvpmhdr5wb44w05.jpg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eetcgzrjmsxer1qbqw2r.jpg)