Spring

Primeiro Projeto

Criando um projeto cadastro de Usuários com Spring Boot e Maven.

Vamos explorar todos os recursos de Spring Framework e Spring Boot desenvolvendo um controle de acesso essencial em qualquer aplicação.

Teremos um usuário (User) com os atributos: Id, Name, Username, Password e suas Permissões (roles) conforme diagrama abaixo:

Spring Initializr

Site que oferece os recursos para criação de um projeto Spring Boot com uso Maven ou Gradle.

Preenchimento

  • Group: Nome do grupo organizacional
  • Artifact: Identificação do projeto
  • Name: Nome do Projeto (igual ao artifact)
  • Description: Descrição do Projeto
  • Package Name: Nome do pacote raíz da sua aplicação
  • Packaging: Tipo de Build da sua aplicação, pode manter .jar
  • Java: Versão do Java JDK e JRE que está utilizando

Clique no botão GENERATE para realizar o download, extraia o aquivo .zip e em seguida importe na IDE de sua preferência.

NOTA: Ainda não incluímos nenhuma dependência de acesso a dados, web e segurança

Abaixo segue uma demonstração da estrutura do projeto gerado pelo Spring Initializr.

Camada de Modelo

Camada de Modelo consiste na parte estrutural e lógica da aplicação, gerenciando o comportamento dos dados através de regras de negócios permitindo os dados serem coletados, gravados e exibidos.

Em uma arquitetura orientada a serviços web podemos inserir na camada de modelo as nossas Entidades, Pojos e Recursos Utéis da aplicação.

Como ainda não estamos na fase de integração a dados, iremos iniciar somente com as classes de Domínio como os pojos, entidades e serviços.

Criando a classe User, dentro do pacote principal da sua aplicação crie um pacote chamado model e dentro de model a classe User.java

import java.util.List;
import java.util.Objects;

public class User {
    private String name;
    private String username;
    private String password;
    private List<String> roles;

    public User() {

    }

    public User(String username) {
        this.username = username;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<String> getRoles() {
        return roles;
    }

    public void setRoles(List<String> roles) {
        this.roles = roles;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(username, user.username);
    }

    @Override
    public int hashCode() {
        return Objects.hash(username);
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", roles=" + roles +
                '}';
    }
}

Camada de Negócio

Parte da aplicação responsável por centralizar toda a lógica baseada na proposta da aplicação.

Em uma arquitetura orientada a serviços web podemos inserir na camada de negócio os Serviços contendo toda regra de negócio da aplicação.

UserService é uma classe que contém regra de negócio baseada na classe User.java. Dentro do pacote principal da sua aplicação crie um pacote chamado service e dentro de service a classe UserService.java.

import java.util.List;

public class UserService {
    public void gravar(User user){
        System.out.println("Gravando usuário");
    }
    public void alterar(User user){
        System.out.println("Alterando usuário");
    }
    public User buscarPorUsername(String username){
        System.out.println("Buscando usuário pelo login");
        return null;
    }
    public List<User> listar(){
        System.out.println("Listando todos os usuários");
        return null;
    }
}
Vamos imaginar que o nosso serviço possua a funcionalidade de armazenar os usuários em uma coleção simulando um banco de dados.

Primeira refatoração da classe UserService.java

import java.util.ArrayList;
import java.util.List;

public class UserService {

    //simulando um banco de dados com a tabela user
    private List<User> database = new ArrayList<>();

    public void gravar(User user){
        database.add(user);
    }
    public void alterar(User user){
        int index = database.indexOf(user);
        database.set(index,user);
    }
    public User buscarPorUsername(String username){
        int index = database.indexOf(new User(username));
        User selectUser = database.get(index);
        return selectUser;
    }
    public List<User> listar(){
        return database;
    }
}
✔️ Hora de integrar os conceitos de Inversão de Controle e Injeção de Dependências com o Spring Boot

Adicione a anotação @Service na classes UserService.java, neste momento agora o Spring cuidará da existência dos objetos criados através da classe UserService.

import izacontent.accessontrol.model.User;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserService {
    
    //... implementação já existente
}

Testando a Aplicação

Vamos iniciar nossa aplicação para testar os recursos de inversão de controle e injeção de dependências do Spring Boot.

Quando é criado um projeto com Spring Boot o mesmo contém uma classe de inicialização da aplicação com um método main, conforme código abaixo:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AccessControlApplication {
    public static void main(String[] args) {
        SpringApplication.run(AccessControlApplication.class, args);
    }
}
Cuidado
Com o Spring não devemos executar nenhum comando abaixo da linha 7 ou instanciar os objetos manualmente usando new.

Para podermos executar nossa aplicação com alguma funcionalidade inicial é necessário criar um CommandLineRunner conforme abaixo:

Crie uma classe chamada StartApplication.java que implementará a interface CommandLineRunner e em seguida implemente o método run.

import izacontent.accessontrol.model.User;
import izacontent.accessontrol.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class StartApplication implements CommandLineRunner {
    @Autowired
    private UserService service;
    @Override
    public void run(String... args) throws Exception {
        for(int x=1; x<=5;x++){
            service.gravar(new User("user"+x));
        }
        User user2 = service.buscarPorUsername("user2");
        user2.setName("MASTER");
        service.alterar(user2);

        for(User user: service.listar()){
            System.out.println(user);
        }
    }
}

Vamos agora entender um pouco sobre anotações, IoC e DI.

  • O Spring usa um conjunto de anotações @ para identificar as classes que terão a instância dos objetos gerenciados pelo container.
  • @Component: Tudo no Spring são componentes, logo quando iniciamos a aplicação será criado um objeto baseado na classe StartApplication.java.
  • @Autowired: Esta anotação determina que o objeto baseado na classe UserService.java será atribuído a variável service conforme linha 11.
  • Estamos simulando a inclusão de 05 usuários com username: user1, user2 e etc, conforme linhas 15 a 17.
  • Na linha 18 estamos simulando buscar um usuário pelo seu username, no caso o User com username = user2.
  • Após localizar o User mudamos o seu name para MASTER conforme linha 19
  • Na linha 16 simulamos a alteração de User no nosso "banco de dados".
  • E por último, imprimimos todos os usuários para avaliar sua estrutura conforme linhas 22 até 24.
Em um contexto Spring NÃO utilizamos new para instanciação de objetos componentes serviços e repositórios, usamos @Autowired.

Por último execute a classe principal da aplicação, aquela que tem a anotação @SpringBootApplication e analise o console. AccessControlApplication.java

Ao final desta etapa, a estrutura do projeto estará dessa forma:

Hora de iniciar a nossa integração com o banco de dados