Introdução
Neste tutorial, você aprenderá a construir uma API RESTful robusta utilizando Java e o framework Spring Boot. Vamos abordar desde a configuração do ambiente e a estruturação do projeto até a implementação de um banco de dados em memória e a criação de endpoints RESTful. Além disso, discutiremos a importância de testes unitários, que garantirão que sua API funcione conforme o esperado. A combinação do Spring Boot com boas práticas de desenvolvimento permite a criação de aplicações escaláveis e de fácil manutenção, ideal para ambientes de produção. Prepare-se para um guia completo!
Etapas
Configuração do Ambiente de Desenvolvimento
Primeiramente, verifique se você possui o JDK (Java Development Kit) e o Maven instalados em sua máquina. Os comandos `java -version` e `mvn -version` permitirão a você confirmar se as ferramentas estão corretamente configuradas. Se não estiverem instaladas, siga as instruções disponíveis nos sites oficiais das respectivas ferramentas.
commands# Verificar versões instaladas
java -version
mvn -versionCriação do Projeto Spring Boot
Use o Spring Initializr para gerar um novo projeto Spring Boot com as dependências necessárias. Configure o projeto com as opções: **Project**: Maven, **Language**: Java, **Spring Boot**: última versão estável, **Packaging**: Jar, **Java**: 11 ou superior. Adicione as dependências ‘Spring Web’, ‘Spring Data JPA’, e ‘H2 Database’. Após a configuração, baixe e descompacte o projeto em seu ambiente de trabalho.
pom.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>api-restful</artifactId> <version>0.0.1-SNAPSHOT</version> <name>api-restful</name> <description>API RESTful com Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Configuração do Banco de Dados H2
Edite o arquivo `application.properties` para definir as propriedades do banco de dados H2 e habilitar o console web, que permitirá a visualização dos dados armazenados.
application.propertiesspring.h2.console.enabled=true spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=update
Criação da Entidade `Produto`
Implemente a classe modelo `Produto`, que representará os produtos na aplicação. Use as anotações JPA para mapear a classe à tabela do banco de dados.
Produto.javapackage com.example.apirestful.model; import javax.persistence.*; @Entity @Table(name = "produtos") public class Produto { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String nome; @Column(nullable = false) private Double preco; // Getters e Setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public Double getPreco() { return preco; } public void setPreco(Double preco) { this.preco = preco; } }
Criação do Repositório `ProdutoRepository`
Implemente a interface `ProdutoRepository`, que estende `JpaRepository`, para fornecer métodos CRUD. Isso vai permitir interações fáceis com a entidade produto.
ProdutoRepository.javapackage com.example.apirestful.repository; import com.example.apirestful.model.Produto; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface ProdutoRepository extends JpaRepository<Produto, Long> { // Métodos personalizados podem ser definidos aqui }
Implementação do Serviço `ProdutoService`
Crie a classe `ProdutoService`, que conterá a lógica de negócios e irá utilizar o `ProdutoRepository` para interagir com o banco de dados.
ProdutoService.javapackage com.example.apirestful.service; import com.example.apirestful.model.Produto; import com.example.apirestful.repository.ProdutoRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Optional; @Service public class ProdutoService { @Autowired private ProdutoRepository produtoRepository; public List<Produto> findAll() { return produtoRepository.findAll(); } public Optional<Produto> findById(Long id) { return produtoRepository.findById(id); } public Produto save(Produto produto) { return produtoRepository.save(produto); } public Produto update(Long id, Produto produtoDetails) { Produto produto = produtoRepository.findById(id).orElseThrow(() -> new RuntimeException("Produto não encontrado")); produto.setNome(produtoDetails.getNome()); produto.setPreco(produtoDetails.getPreco()); return produtoRepository.save(produto); } public void deleteById(Long id) { produtoRepository.deleteById(id); } }
Implementação do Controlador `ProdutoController`
Crie a classe `ProdutoController` para expor os endpoints da API, permitindo operações CRUD através de requisições HTTP.
ProdutoController.javapackage com.example.apirestful.controller; import com.example.apirestful.model.Produto; import com.example.apirestful.service.ProdutoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/api/produtos") public class ProdutoController { @Autowired private ProdutoService produtoService; @GetMapping public List<Produto> getAllProdutos() { return produtoService.findAll(); } @GetMapping("/{id}") public ResponseEntity<Produto> getProdutoById(@PathVariable Long id) { return produtoService.findById(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } @PostMapping public Produto createProduto(@RequestBody Produto produto) { return produtoService.save(produto); } @PutMapping("/{id}") public ResponseEntity<Produto> updateProduto(@PathVariable Long id, @RequestBody Produto produtoDetails) { return ResponseEntity.ok(produtoService.update(id, produtoDetails)); } @DeleteMapping("/{id}") public ResponseEntity<Void> deleteProduto(@PathVariable Long id) { produtoService.deleteById(id); return ResponseEntity.noContent().build(); } }
Implementação de Testes Unitários
Crie a classe de testes `ProdutoServiceTest` para validar a lógica de negócios e as operações CRUD da aplicação. Utilize mocks para simular o repositório.
ProdutoServiceTest.javapackage com.example.apirestful.service; import com.example.apirestful.model.Produto; import com.example.apirestful.repository.ProdutoRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.Arrays; import java.util.List; import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; public class ProdutoServiceTest { @InjectMocks private ProdutoService produtoService; @Mock private ProdutoRepository produtoRepository; @BeforeEach public void init() { MockitoAnnotations.openMocks(this); } @Test public void testFindAll() { Produto produto1 = new Produto(); produto1.setId(1L); produto1.setNome("Produto 1"); produto1.setPreco(10.0); Produto produto2 = new Produto(); produto2.setId(2L); produto2.setNome("Produto 2"); produto2.setPreco(20.0); when(produtoRepository.findAll()).thenReturn(Arrays.asList(produto1, produto2)); List<Produto> produtos = produtoService.findAll(); assertEquals(2, produtos.size()); verify(produtoRepository, times(1)).findAll(); } // Testes adicionais para os métodos findById, save, update e deleteById }
Executando a Aplicação e Testes
Utilize o Maven para compilar e executar a aplicação. Em seguida, utilize ferramentas como Postman ou cURL para testar os endpoints da sua API e verificar se tudo está funcionando corretamente.
commands# Compilar e executar a aplicação
mvn spring-boot:run
# Executar os testes unitários
mvn testcurl_examples# Listar todos os produtos
curl -X GET http://localhost:8080/api/produtos
# Criar um novo produto
curl -X POST -H "Content-Type: application/json" -d '{"nome":"Novo Produto", "preco":99.99}' http://localhost:8080/api/produtos
Conclusão
Neste tutorial, você aprendeu a desenvolver uma API RESTful completa utilizando Spring Boot, abordando desde a configuração inicial até a implementação de testes unitários. Ao seguir este guia, você adquiriu conhecimento sobre como estruturar uma aplicação de maneira eficiente, integrando os componentes necessários para um funcionamento harmônico. Com esses fundamentos, você está preparado para avançar no desenvolvimento de APIs e explorar novas funcionalidades e melhorias em suas futuras aplicações.