API REST Spring Boot

Curso teórico e prático
Voltar

RESUMO EM CONSTRUÇÃO

Material complementar:


Conceito:

Curso teórico e prático para criação de projeto backend API REST, utilizando Spring Boot com Kotlin (ORM hibernate JPA DAO). Projeto com funcionalidades CRUD (Create, Read/List, Update, Delete). Banco de dados MySQL. Testes via Postman. Deploy em AWS (EC2).


API REST:

Sistema web backend que suporta métodos HTTP REST (GET, POST, PUT, DELETE), transportando dados via header/body em request - response entre dispositivos comunicados em rede, via IPs em protocolo HTTP. Framework Spring Boot possui tecnologias necessárias para implementar padrão REST em projetos Java/Kotlin, usando padrões de código OOP (Programação Orientada a Objetos) e MVC (Model-View-Controller).


Padrão MVC:

  • Model: camada de modelo/negócios responsável por implementar regras de negócio da aplicação, definição das entidades e relacionamentos, implementando comportamento e camada de dados;
  • View: camada de visão, responsável pela implementação e exibição de interface com usuário;
  • Controller: camada de controle, classe OOP responsável pelo intermédio entre Model e View, pois elas nunca comunicam-se diretamente.
    Fluxo de dados:
  1. Controller recebe requisição HTTP;
  2. Controller trata dados da requisição, interagindo com Model (se necessário);
  3. Controller prepara/envia resposta HTTP ao cliente, geralmente invocando View para tal.

Instalação das ferramentas:

Instalação de pré-requisitos em ambiente Windows.

  1. JDK 21: Acesse
    • Baixar e instalar JDK Oracle
    • Win + R, digite "SystemPropertiesAdvanced", acessar Variáveis de Ambiente
    • Aba "Variáveis do sistema", em Novo, criar/editar variáveis:
        Criar:
      • Nome: JAVA_HOME
      • Valor: Caminho da pasta com JDK instalado (Ex: "C:\Program Files\Java\jdk-21")
      • Confirmar criação OK

      • Editar:
      • Nome: Path
      • Clicar em Novo
      • Valor: %JAVA_HOME%\bin
      • Confirmar criação OK
    • Verificar instalação no CMD, com comando "java -version"
  2. Kotlin compiler: Acesse
    • Baixar e instalar Kotlin compiler (.zip) - última versão estável
    • Diretório "C:/", crie pasta "Kotlin", e descompacte o Kotlin dentro dela
    • Win + R, digite "SystemPropertiesAdvanced", acessar Variáveis de Ambiente
    • Aba "Variáveis do sistema", editar variável Path:
      • Nome: Path
      • Clicar em Novo
      • Valor: C:\Kotlin\kotlinc\bin
      • Confirmar criação OK
    • Verificar instalação: Win + R, digitar CMD, e informar comando "kotlinc -version"
  3. Gradle: Acesse:
    • Baixar e instalar Gradle: site oficial Gradle, Install, Install manually, Step 1, baixar Binary-only
    • Diretório "C:/", crie pasta "Gradle", e descompacte o Gradle dentro dela
    • Win + R, digite "SystemPropertiesAdvanced", acessar Variáveis de Ambiente
    • Aba "Variáveis do sistema", editar variável Path:
      • Nome: Path
      • Clicar em Novo
      • Valor: C:\Gradle\gradle-VERSAO\bin
      • Confirmar criação OK
    • Verificar instalação: Win + R, digitar CMD, e informar comando "gradle -v"
  4. IntelliJ IDEA (Community Edition): Acesse
  5. XAMPP: Acesse
  6. Postman Agent: Acesse
  7. Cadastro no Postman

Criação do projeto:

  1. Em Spring Initializr, selecione as dependências:
    • Project: Gradle - Kotlin
    • Language: Kotlin
    • Project Metadata:
      • Group: ubsocial.com
      • Artifact: bookstore
      • Name: bookstore (igual no Artifact)
      • Package name: ubsocial.com.bookstore
      • Java: versão do JDK instalado na máquina (21)
    • Dependencies:
      • Spring Web
      • Spring Data JPA
    • Generate (projeto será gerado, abra-o no IntelliJ)
  2. Criar banco de dados MySQL: CREATE DATABASE bookstore;
  3. 'build.gradle.kts', em 'dependencies', adicionar dependencies:
    
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.springframework.boot:spring-boot-starter-validation")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
    runtimeOnly("com.mysql:mysql-connector-j")
    
  4. 'src/main/resources/application.properties':
    
    spring.application.name=bookstore
    spring.jpa.hibernate.ddl-auto=update
    spring.datasource.url=jdbc:mysql://localhost:3306/bookstore
    spring.datasource.username=root
    spring.datasource.password=
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.jackson.serialization.fail-on-empty-beans=false
    server.error.include-message=always
    server.error.include-binding-errors=always
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.format_sql=true
    server.port=8080
    
  5. Dentro do pacote principal do projeto (ubsocial.com.bookstore), criar pacote "config": ficará ubsocial.com.bookstore.config
  6. Dentro do pacote "config", criar classe WebConfig.kt para conexão com frontend Vue.js:
    
    package ubsocial.com.bookstore.config
    import org.springframework.context.annotation.Bean
    import org.springframework.context.annotation.Configuration
    import org.springframework.web.servlet.config.annotation.CorsRegistry
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
    
    @Configuration
    class WebConfig {
    
        @Bean
        fun corsConfigurer(): WebMvcConfigurer {
            return object : WebMvcConfigurer {
                override fun addCorsMappings(registry: CorsRegistry) {
                    registry.addMapping("/**")
                        .allowedOrigins("http://localhost:8081")
                        .allowedMethods("GET","POST","PUT","DELETE","OPTIONS")
                }
            }
        }
    }
    
  7. Dentro do pacote principal do projeto (ubsocial.com.bookstore), criar pacote "model": ficará ubsocial.com.bookstore.model
  8. Dentro do pacote "model", criar pacote de entidades "entity": ficará model.entity
  9. Dentro do pacote "model.entity", criar Model (entidade) Book.kt:
    
    package ubsocial.com.bookstore.model.entity
    import com.fasterxml.jackson.annotation.JsonFormat
    import jakarta.persistence.*
    import jakarta.validation.constraints.NotBlank
    import jakarta.validation.constraints.NotNull
    import jakarta.validation.constraints.Size
    import java.time.LocalDate
    
    @Entity
    data class Book(
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        val id: Long? = null,
    
        @field:NotBlank
        @field:Size(min = 1, max = 255, message = "Título precisa ter entre 1 e 255 caracteres")
        @Column(length = 255)
        val title: String = "",
    
        @field:NotBlank
        @field:Size(min = 1, max = 255, message = "Autor precisa ter entre 1 e 255 caracteres")
        @Column(length = 255)
        val author: String = "",
    
        @field:NotNull
        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
        @Column(name = "published_date")
        val published_date: LocalDate = LocalDate.now(),
    
        @field:NotBlank
        @field:Size(min = 13, max = 13, message = "ISBN precisa ter 13 caracteres")
        @Column(unique = true)
        val isbn: String = "",
    
        val pages: Int = 0,
    
        @field:Size(min = 1, max = 255, message = "Capa/Gênero precisa ter entre 1 e 255 caracteres")
        @Column(length = 255)
        val cover: String? = null,
    
        @field:NotBlank
        @field:Size(min = 1, max = 255, message = "Idioma precisa ter entre 1 e 255 caracteres")
        @Column(length = 255)
        val language: String = ""
    )
    
  10. No pacote "model", criar pacote "repositories": ficará model.repositories
  11. No pacote "repositories", criar interface BookRepository.kt:
    
    package ubsocial.com.bookstore.model.repositories
    import org.springframework.data.jpa.repository.JpaRepository
    import ubsocial.com.bookstore.model.entity.Book
    
    interface BookRepository : JpaRepository<Book, Long>
    
  12. Pacote principal "ubsocial.com.bookstore, criar pacote "controller"
  13. Pacote "controller", criar classe BookResource.kt:
    
    package ubsocial.com.bookstore.controller
    import jakarta.validation.Valid
    import org.springframework.http.HttpStatus
    import org.springframework.http.ResponseEntity
    import org.springframework.web.bind.annotation.*
    import ubsocial.com.bookstore.model.entity.Book
    import ubsocial.com.bookstore.model.repositories.BookRepository
    
    @RestController
    @RequestMapping("/books")
    class BookResource(private val bookRepository: BookRepository) {
    
        @GetMapping
        fun getAll(): List<Book> = bookRepository.findAll()
        
        @GetMapping("/{id}")
        fun getById(@PathVariable id: Long): ResponseEntity<Book> {
            val book = bookRepository.findById(id)
            return if (book.isPresent) ResponseEntity.ok(book.get())
            else ResponseEntity.notFound().build()
        }
    
        @PostMapping
        fun create(@RequestBody @Valid book: Book): Book = bookRepository.save(book)
    
        @PutMapping("/{id}")
        fun update(@PathVariable id: Long, @RequestBody @Valid book: Book): ResponseEntity<Book> {
            val optional = bookRepository.findById(id)
            if (optional.isEmpty) return ResponseEntity.notFound().build()
    
            val updated = optional.get().copy(
                title = book.title,
                author = book.author,
                published_date = book.published_date,
                isbn = book.isbn,
                pages = book.pages,
                cover = book.cover,
                language = book.language
            )
            return ResponseEntity.ok(bookRepository.save(updated))
        }
    
        @DeleteMapping("/{id}")
        fun delete(@PathVariable id: Long): ResponseEntity<Void> {
            return if (bookRepository.existsById(id)) {
                bookRepository.deleteById(id)
                ResponseEntity.noContent().build()
            } else {
                ResponseEntity.notFound().build()
            }
        }
    }
    
  14. Na mesma pasta de "gradlew", executar projeto: ".\gradlew bootRun"

Testes no Postman:

AQUI

  1. Teste Postman (create):
    • URL: http://localhost:8080/books
    • Método: POST
    • Body raw (JSON):
      
      {
          "title": "O Senhor dos Anéis",
          "author": "J.R.R. Tolkien",
          "published_date": "1954-07-29",
          "isbn": "9780261102385",
          "pages": 1178,
          "cover": "Ficção",
          "language": "Português"
      }
      
    • Enviar (Send)
  2. Teste Postman (get):
  3. Teste Postman (get específico):
  4. Teste Postman (update):
    • URL: http://localhost:8080/books/1
    • Método: PUT
    • Body raw (JSON):
      
      {
          "title": "O Senhor dos Anéis - Edição Atualizada",
          "author": "J.R.R. Tolkien",
          "published_date": "1954-07-29",
          "isbn": "9780261102385",
          "pages": 1178,
          "cover": "Ficção",
          "language": "Português"
      }
      
    • Enviar (Send)
  5. Teste Postman (delete):

Deploy na AWS:

AQUI

Elaborado por Mateus Schwede
ubsocial.github.io