Introdução

Com o crescimento exponencial de aplicações complexas, a arquitetura de microserviços se tornou uma abordagem popular para o desenvolvimento de software. Este tutorial oferece um guia passo a passo sobre como desenvolver aplicações de microserviços utilizando Janus Gateway, Spring Boot e Docker. Vamos explorar como estruturar sua aplicação, gerenciar o tráfego de serviços, e garantir que cada componente funcione de maneira otimizada e integrada. O uso do Janus como gateway de API permite uma gestão eficiente das requisições e respostas, ao mesmo tempo que oferece funcionalidades avançadas como load balancing. Neste guia, você irá aprender a implementar tudo isso em um ambiente de desenvolvimento adequado, com a capacidade de escalar sua aplicação conforme necessário.

Etapas

  1. Configuração do Ambiente de Desenvolvimento

    Comece instalando o Java JDK e o Maven em sua máquina se ainda não estiverem instalados. Além disso, você precisará ter o Docker instalado para contêinerizar a sua aplicação posteriormente. Verifique as versões instaladas usando os comandos `java -version`, `mvn -version` e `docker –version`. Caso não tenha instalado, siga as instruções do site oficial para cada uma dessas ferramentas.

    commands
    # Verificar versões instaladas
    java -version
    mvn -version
    docker --version

  2. Criação do Projeto Spring Boot

    Utilize o Spring Initializr para gerar um novo projeto Spring Boot com as dependências necessárias. Configure o projeto com as seguintes 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 Boot DevTools’, ‘Spring Data JPA’ e ‘H2 Database’. Baixe e descompacte o projeto em sua máquina.

    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>microservices-janus</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <name>microservices-janus</name>
      <description>Aplicações de Microserviços com Janus e 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>

  3. Configuração do Banco de Dados H2

    Edite o arquivo `application.properties` para definir as propriedades do banco de dados H2, permitindo que a aplicação armazene dados em memória e habilite o console web para visualização.

    application.properties
    spring.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

  4. Criação da Entidade `Servico`

    Implemente a classe modelo `Servico` que representará os microserviços na aplicação. Use anotações JPA para mapear a classe à tabela do banco de dados.

    Servico.java
    package com.example.microservicesjanus.model;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name = "servicos")
    public class Servico {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(nullable = false)
        private String nome;
    
        @Column(nullable = false)
        private String descricao;
    
        // 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 String getDescricao() {
            return descricao;
        }
    
        public void setDescricao(String descricao) {
            this.descricao = descricao;
        }
    }

  5. Criação do Repositório `ServicoRepository`

    Implemente a interface `ServicoRepository`, que estende `JpaRepository` e fornece métodos CRUD para manipulação da entidade Servico.

    ServicoRepository.java
    package com.example.microservicesjanus.repository;
    
    import com.example.microservicesjanus.model.Servico;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface ServicoRepository extends JpaRepository<Servico, Long> {
        // Métodos personalizados podem ser definidos aqui
    }

  6. Implementação do Serviço `ServicoService`

    Crie a classe `ServicoService`, que contém a lógica de negócios e utiliza o `ServicoRepository` para interagir com o banco de dados de microserviços.

    ServicoService.java
    package com.example.microservicesjanus.service;
    
    import com.example.microservicesjanus.model.Servico;
    import com.example.microservicesjanus.repository.ServicoRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    import java.util.Optional;
    
    @Service
    public class ServicoService {
        @Autowired
        private ServicoRepository servicoRepository;
    
        public List<Servico> findAll() {
            return servicoRepository.findAll();
        }
    
        public Optional<Servico> findById(Long id) {
            return servicoRepository.findById(id);
        }
    
        public Servico save(Servico servico) {
            return servicoRepository.save(servico);
        }
    
        public Servico update(Long id, Servico servicoDetails) {
            Servico servico = servicoRepository.findById(id).orElseThrow(() -> new RuntimeException("Servico não encontrado"));
            servico.setNome(servicoDetails.getNome());
            servico.setDescricao(servicoDetails.getDescricao());
            return servicoRepository.save(servico);
        }
    
        public void deleteById(Long id) {
            servicoRepository.deleteById(id);
        }
    }

  7. Implementação do Controlador `ServicoController`

    Crie a classe `ServicoController` para expor os endpoints da API, permitindo operações CRUD em microserviços.

    ServicoController.java
    package com.example.microservicesjanus.controller;
    
    import com.example.microservicesjanus.model.Servico;
    import com.example.microservicesjanus.service.ServicoService;
    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/servicos")
    public class ServicoController {
        @Autowired
        private ServicoService servicoService;
    
        @GetMapping
        public List<Servico> getAllServicos() {
            return servicoService.findAll();
        }
    
        @GetMapping("/{id}")
        public ResponseEntity<Servico> getServicoById(@PathVariable Long id) {
            return servicoService.findById(id)
                    .map(ResponseEntity::ok)
                    .orElse(ResponseEntity.notFound().build());
        }
    
        @PostMapping
        public Servico createServico(@RequestBody Servico servico) {
            return servicoService.save(servico);
        }
    
        @PutMapping("/{id}")
        public ResponseEntity<Servico> updateServico(@PathVariable Long id, @RequestBody Servico servicoDetails) {
            return ResponseEntity.ok(servicoService.update(id, servicoDetails));
        }
    
        @DeleteMapping("/{id}")
        public ResponseEntity<Void> deleteServico(@PathVariable Long id) {
            servicoService.deleteById(id);
            return ResponseEntity.noContent().build();
        }
    }

  8. Implementação de Testes Unitários

    Crie a classe de testes `ServicoServiceTest` para validar a lógica de negócios e operações CRUD da aplicação de microserviços.

    ServicoServiceTest.java
    package com.example.microservicesjanus.service;
    
    import com.example.microservicesjanus.model.Servico;
    import com.example.microservicesjanus.repository.ServicoRepository;
    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 ServicoServiceTest {
        @InjectMocks
        private ServicoService servicoService;
    
        @Mock
        private ServicoRepository servicoRepository;
    
        @BeforeEach
        public void init() {
            MockitoAnnotations.openMocks(this);
        }
    
        @Test
        public void testFindAll() {
            Servico servico1 = new Servico();
            servico1.setId(1L);
            servico1.setNome("Servico 1");
            servico1.setDescricao("Descricao 1");
    
            Servico servico2 = new Servico();
            servico2.setId(2L);
            servico2.setNome("Servico 2");
            servico2.setDescricao("Descricao 2");
    
            when(servicoRepository.findAll()).thenReturn(Arrays.asList(servico1, servico2));
    
            List<Servico> servicos = servicoService.findAll();
            assertEquals(2, servicos.size());
            verify(servicoRepository, times(1)).findAll();
        }
    
        // Testes adicionais para os métodos findById, save, update e deleteById
    }

  9. Executando a Aplicação e Testes

    Utilize o Maven para compilar e executar a aplicação. Execute os testes unitários para garantir que todos os componentes funcionem como esperado. Utilize ferramentas como Postman ou cURL para testar os endpoints da API.

    commands
    # Compilar e executar a aplicação
    mvn spring-boot:run
    # Executar os testes unitários
    mvn test

    curl_examples
    # Listar todos os serviços
    curl -X GET http://localhost:8080/api/servicos
    # Criar um novo serviço
    curl -X POST -H "Content-Type: application/json" -d '{"nome":"Novo Serviço", "descricao":"Descrição do Novo Serviço"}' http://localhost:8080/api/servicos

Conclusão

Neste tutorial, você aprendeu como desenvolver aplicações de microserviços usando Janus Gateway, Spring Boot e Docker. Cobriu desde a configuração inicial do ambiente de desenvolvimento, passando pela criação de entidades JPA e exposições de APIs, até a implementação de testes unitários para garantir a qualidade da aplicação. Com esse conhecimento, você está preparado para levar suas habilidades de desenvolvimento de software a um nível mais elevado, explorando mais sobre microserviços e arquiteturas escaláveis, promovendo o crescimento e robustez de suas aplicações.

Hashtags

#Microserviços #Janus #SpringBoot #Docker #DesenvolvimentoDeSoftware #APIs