Introdução
Neste tutorial, iremos explorar a construção de microserviços utilizando Kotlin, Ktor e Exposed. O microserviço é uma arquitetura que permite desenvolver aplicações de forma modular, facilitando a escalabilidade e a manutenção. Vamos abordar desde a configuração do ambiente até a implementação de um serviço RESTful completo, incluindo o acesso a banco de dados e testes unitários. Este guia é ideal para desenvolvedores que desejam aproveitar o poder do Kotlin e a simplicidade do Ktor para construir aplicações modernas e eficientes. Você aprenderá a criar serviços que podem ser facilmente integrados e que respondem rapidamente às demandas do usuário em um ambiente de produção.
Etapas
Configuração do Ambiente de Desenvolvimento
Para começar, você precisará ter o JDK 11 ou superior e o IntelliJ IDEA instalado na sua máquina. Verifique se você possui o JDK com o comando `java -version`. Além disso, instale o Ktor e o Exposed como dependências no IntelliJ.
commands# Verifique a versão do JDK
java -versionCriação do Projeto Ktor
Utilize o Ktor para criar um novo projeto. Abra o IntelliJ IDEA, e selecione ‘New Project’. Escolha Ktor e configure seu projeto básico com o plugin Ktor. Inclua as dependências ‘Ktor Server Core’, ‘Ktor Server Netty’, ‘Ktor Serialization’, e ‘Exposed’.
build.gradle.ktsplugins { application kotlin("plugin.serialization") version "1.5.31" } application { mainClass.set("io.ktor.server.netty.EngineMain") } repositories { mavenCentral() } dependencies { implementation("io.ktor:ktor-server-core-jvm:1.6.7") implementation("io.ktor:ktor-server-netty-jvm:1.6.7") implementation("io.ktor:ktor-serialization:1.6.7") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") implementation("org.jetbrains.exposed:exposed-core:0.37.2") implementation("org.jetbrains.exposed:exposed-dao:0.37.2") implementation("org.jetbrains.exposed:exposed-jdbc:0.37.2") implementation("com.h2database:h2:1.4.200") testImplementation("io.ktor:ktor-server-tests-jvm:1.6.7") }
Configuração do Banco de Dados com Exposed
Crie uma nova classe para configurar a conexão com o banco de dados H2 utilizando Exposed. Esta classe habilitará a configuração do banco de dados em memória para testes rápidos.
DatabaseFactory.ktimport org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.transaction object DatabaseFactory { fun init() { Database.connect( url = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;" driver = "org.h2.Driver", user = "root", password = "" ) transaction { SchemaUtils.create(Produtos) } } }
Criação da Tabela `Produtos`
Implemente a tabela `Produtos` utilizando Exposed. Esta tabela armazenará os dados dos produtos que seu microserviço irá manipular.
Produto.ktimport org.jetbrains.exposed.sql.Table object Produtos : Table() { val id = long("id").autoIncrement().primaryKey() val nome = varchar("nome", 50) val preco = decimal("preco", 10, 2) }
Implementação do Service `ProdutoService`
Crie a classe `ProdutoService` que contém a lógica de negócios para gerenciar os produtos. Use Exposed para interagir com a tabela Produtos no banco de dados.
ProdutoService.ktimport org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.transaction data class Produto(val id: Long, val nome: String, val preco: Double) class ProdutoService { fun findAll(): List<Produto> = transaction { Produtos.selectAll().map { Produto(it[Produtos.id], it[Produtos.nome], it[Produtos.preco].toDouble()) } } fun create(nome: String, preco: Double): Produto = transaction { val id = Produtos.insertAndGetId { it[this.nome] = nome it[this.preco] = preco.toBigDecimal() } Produto(id.value, nome, preco) } }
Implementação do Controlador `ProdutoController`
Implemente o controlador `ProdutoController` para expor os endpoints RESTful que permitirão operações CRUD.
ProdutoController.ktimport io.ktor.application.* import io.ktor.response.* import io.ktor.routing.* import io.ktor.http.* import io.ktor.request.* fun Route.produtoRoutes(produtoService: ProdutoService) { route("/produtos") { get { call.respond(produtoService.findAll()) } post { val produto = call.receive<Produto>() call.respond(produtoService.create(produto.nome, produto.preco)) } } }
Configuração do Ktor Application
No arquivo `Application.kt`, configure as rotas do Ktor e inicie a aplicação Ktor.
Application.ktimport io.ktor.application.* import io.ktor.features.* import io.ktor.serialization.* import io.ktor.server.engine.* import io.ktor.server.netty.* fun main() { embeddedServer(Netty, port = 8080, host = "0.0.0.0") { install(ContentNegotiation) { json() } DatabaseFactory.init() routing { produtoRoutes(ProdutoService()) } }.start(wait = true) }
Implementação de Testes Unitários
Utilize as bibliotecas de teste do Ktor para criar testes unitários para seu `ProdutoService` e garanta que a lógica esté funcionando corretamente.
ProdutoServiceTest.ktimport io.ktor.server.testing.* import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue class ProdutoServiceTest { @Test fun `test criar produto`() { withTestApplication({}) { val produtoService = ProdutoService() val produto = produtoService.create("Produto Teste", 10.0) assertTrue(produto.id > 0) } } }
Executando a Aplicação e Testes
Compile e inicie a aplicação utilizando o Gradle. Use ferramentas como Postman ou cURL para testar os endpoints da API que você criou.
commands# Compilar e executar a aplicação
gradle run
# Testar a criação de um produto
curl -X POST -H 'Content-Type: application/json' -d '{"nome":"Produto Novo","preco":29.99}' http://localhost:8080/produtos
Conclusão
Neste guia, você aprendeu a implementar um microserviço utilizando Kotlin, Ktor e Exposed. Desde a configuração do ambiente até a criação de um serviço RESTful abrangente, cobrimos todos os aspectos importantes. A arquitetura de microserviços permite que você desenvolva aplicações escaláveis e manuteníveis. Agora, você está preparado para criar suas próprias aplicações com Kotlin e explorar suas ricas bibliotecas e frameworks. Lembre-se de que a prática contínua é fundamental para aprimorar suas habilidades em desenvolvimento de software.