Introdução
Estou aprendendo Spring há dois meses. Durante esse tempo, me deparei com uma série de siglas, nomes e conceitos totalmente novos. Eu tinha elaborado dois artigos com as anotações de um treinamento que fiz de Spring Boot, mas, desde então, tenho feito novos cursos relacionados ao Spring e pude aprender diversos outros assuntos relacionados a este universo, além de me aprofundar um pouco mais sobre os assuntos que tive contato no primeiro curso.
Como me organizo melhor escrevendo minhas ideias e anotações dos cursos, decidi criar um Guia do Spring para usar como ferramenta de consulta durante o meu aprendizado e compartilha-lo com toda a comunidade. Conforme for aprendendo novos assuntos e for me aprofundando nos temas que já citei, irei atualizando este artigo.
Entendendo o universo Java e Spring
Spring é um framework Java que foi criado com o objetivo de facilitar o desenvolvimento de aplicações, utilizando os conceitos de Inversão de Controle e Injeção de Dependências. Dentro dele, há o Spring MVC e o Core Technologies (é a base do Spring, dentro dele há o pacote de injeção de dependências).
Spring Boot é uma ferramenta que visa facilitar o processo de configuração e publicação de aplicações que usam o Spring, de maneira pé-configurada. Com esta ferramenta (presente no Spring Tools Service), você pode dizer ao Spring quantos módulos você quer usar (Spring MVC, Spring Data, Spring Cloud, Spring Security, Lombok, banco de dados, etc) e obterá uma configuração rápida para eles.
Spring Tools (STS) é um plugin para as IDE (ambiente de desenvolvimento) do Eclipse, Visual Studio Code e Theia, que possibilita trabalhar com as funcionalidades do Spring de maneira mais fácil. Mas o STS não é pré-requisito para criação de projetos com Spring Boot, é possível usar qualquer outra ferramenta que suporta Java ou Maven. Para quem quiser criar o projeto de forma mais fácil, é possível utilizar também o site http://start.spring.io, que ajuda na criação de projetos com Spring Boot da mesma forma que o STS, de maneira intuitiva e fácil.
Spring MVC é uma estrutura MVC completa orientada a HTTP (Web), gerenciada pela Spring Framework e baseada em Servlets. Os elementos mais populares nele são as classes anotadas @Controller, nas quais você implementa métodos que podem ser acessados usando diferentes solicitações HTTP. Tem um equivalente @RestController para implementar APIs baseadas em REST.
API (Application Programming Interface) é um conjunto de rotinas, protocolos e ferramentas para construir aplicações que permite que dois sistemas se comuniquem entre si. Essencialmente, ela fornece a linguagem e o contrato para os dois sistemas interagirem entre si. Cada API tem documentação e especificação que determina como a informação pode ser transferida. Por exemplo, as possibilidades disponibilizadas pelo uso das APIs proporcionam para os desenvolvedores de softwares e aplicativos a possibilidade de conectar tecnologias heterogêneas, como diferentes bancos de dados. Utilizando o protocolo HTTP, nós temos o exemplo do SOAP ou REST, SOAP depende exclusivamente de XML para fornecer serviços de mensagens, enquanto REST oferece um método mais leve, usando URLs na maioria dos casos para receber ou enviar informações, utilizando os quatro verbos HTTP (GET, POST, PUT/PATCH e DELETE). Podemos utilizar as APIs com qualquer outra interface, como um CLI, utilizando o protocolo WebSocket ou, até mesmo, com uma biblioteca que facilita a extensão do seu código (como o caso da JPA).
Constraints são regras que devem ser seguidas em conformidade com o REST.
REST API é uma API que segue as regras especificadas pelas constraints.
Spring REST é um termo que simboliza que temos uma REST API desenvolvida com o ecossistema Spring.
Quando uma API interage com outro sistema, o ponto de contato desta comunicação é chamado de endpoint, que pode incluir uma URL de um servidor ou serviço. O endpoint é o local de onde as APIs podem acessar os recursos que precisam para realizar suas funções.
Spring Security é uma estrutura Java com foco em tornar a parte de autenticação e autorização algo mais simples de se fazer. Ele possui uma grande variedade de opções e é muito extensível. Com algumas poucas configurações, já podemos ter uma autenticação via banco de dados, LDAP ou até por memória. Além das integrações que ele suporta, há a possibilidade de criar suas próprias. Com o Security, também é possível protegermos as requisições web, através das permissões que atribuímos aos usuários autenticados.
Um grande problema que os desenvolvedores passam é em fazer com que todo o time construa o software da mesma maneira, com as bibliotecas e configurações iguais. Para solucionar este problema, uma das maneiras mais comuns é se utilizar alguma ferramenta que compreenda alguma linguagem de script e copie as dependências e configurações para os lugares corretos, gerando um pacote com a aplicação. O Maven é uma ferramenta desenvolvida pela Apache para gerenciar as dependências, controlar versão de artefatos, gerar relatórios de produtividade, manter o nível da qualidade do código e automatizar seus builds. Com o Maven, podemos isolar as bibliotecas utilizadas no projeto em um repositório compartilhado pela equipe (ou por toda a internet, como o caso do repositório central do Maven), evitando com que tenhamos que nos preocupar com duplicidade de dependências entre módulos do projeto e nem em disponibilidade das mesmas no repositório de código. Os arquivos de build do Maven usam arquivos XML para a sua configuração.
Gradle é um sistema avançado de automatização de builds, que une o melhor da flexibilidade do Ant com o gerenciamento de dependências e as convenções do Maven. Os seus arquivos de build são scripts escritos na linguagem Groovy. Ele possui um sistema de plugins, que adicionam novas funcionalidades ao seu core.
Boilerplate code se refere a seções de códigos que devem ser incluídas em muitos lugares, com pouca ou nenhuma alteração. No Spring, utilizamos as anotações (annotations) para reduzir a quantidade de linhas de códigos desnecessárias.
Lombok é uma biblioteca utilizada para gerar todos os getters, setters, constructors, equals and hashCode, toString, etc de uma determinada classe Model através de anotações, reduzindo consideravelmente a quantidade de código boilerplate. Para ativá-lo, é necessário colocar as dependências da biblioteca no arquivo de configuração Pom.xml. As anotações mais utilizadas são @Getter (gera os métodos get), @setter (gera os métodos set),
@EqualsAndHashCode, @ToString (gera o método toString), @NoArgsContructor (gera um construtor sem argumentos), @AllArgsConstructor (gera um construtor com argumentos), @builder (cria os builders de forma mais fácil) e a anotação @data (substitui as anotações Getter, Setter, ToString, EqualsAndHashCode, NoArgsConstructor, AllArgsConstructor).
Hibernate é um framework objeto relacional que simplifica a interação entre a aplicação e o banco de dados. Ele nasceu da necessidade de se facilitar a tarefa de criar uma aplicação Java que ajude a lidar com o banco de dados e de escrever muito SQL. Ele ajuda a representar tabelas de banco relacional através de classes e consegue gerar, em tempo de execução, o SQL necessário para interagir com o banco de dado. Além disso, ele possui um dialeto diferente para cada banco de dados (Oracle, PostgreSQL, Mongo, etc), permitindo que troquemos de banco de dados sem precisar alterar o código-fonte. A ideia do mapeamento objeto relacional do Hibernate funcionou tão bem que ele serviu de inspiração para a criação de uma especificação Java para persistência, que foi chamada de Java Persistence API (JPA).
Java Persistance API (JPA) é uma especificação do Java EE para tratar o acesso e operações a base de dados que tem um Mapeamento Objeto Relacional (ORM). Ele evita a criação de SQL nativo misturado com código Java e permite a abstração da camada do banco de dados, evitando que se crie conexão manualmente, crie os updates e inserts manuais, etc. Ele também provê formas simples de realizar as operações na base de dados através da aplicação Java, além de permitir a migração para outros SGBD's, sem alterar quase nada.
Mapeamento Objeto Relacional (ORM) é a representação de uma tabela de um banco de dados relacional através de classes Java. Enquanto temos tabelas, colunas e registros no banco de dados, nas linguagens orientada a objetos temos o equivalente com classe, atributos e objetos. Temos também as anotações que adicionarão metadados às classes e permitirão os frameworks ORMS, como o Hibernate, entrar em ação. Algumas das anotações que são muito utilizadas são: @Entity, @Table, @id, @Column. Veja o exemplo da representação banco de dados e da linguagem orientada a objetos:
Spring Data tem por objetivo facilitar nosso trabalho com a persistência de dados de uma forma geral, agrupando diversos outros projetos relacionados a acesso aos dados. Dentro dele, há o Spring Data JPA, que permite implementar projetos JPA de forma simples, além de diversos outros projetos, como o Spring Data Commons, Spring Data MongoDB, Spring Data KeyValue, Spring Data REST, Spring Data Redis, Spring Data for Apache Cassandra, entre outros.
O Spring Data JPA é um framework que nasceu para facilitar a criação dos nossos repositórios, liberando-nos da necessidade de implementar nossas interfaces referentes aos nossos repositórios ou DAOs, além de deixar pré-implementado algumas funcionalidades (como ordenação das consultas e de paginação de registros).
Spring Session fornece uma API e implementações para gerenciar as informações da sessão de um usuário, ao mesmo tempo que torna trivial o suporte a sessões em cluster sem estar vinculado a uma solução específica de contêiner de aplicativo. Ele também fornece integração transparente com o HttpSession, WebSocket e WebSession.
Spring REST Docs é utilizada para documentar APIs mais facilmente, é similar ao Swagger. Uma das vantagens de se utilizá-la, é de desenvolver APIs e incluir o teste de comportamento e a geração de documentação no mesmo processo.
Spring HATEOAS é uma biblioteca de APIs que podemos usar para criar facilmente representações REST que seguem o princípio do HATEOAS (Hypertext as the Engine of Application State). De um modo geral, o princípio implica que a API deve guiar o cliente através da aplicação, retornando informações relevantes sobre as próximas etapas possíveis, junto com cada resposta.
Spring Batch foi desenvolvido para a criação e implementação de jobs (máquina de estados com sequência de etapas que possuem uma lógica própria). Para entender a sua utilização, vamos supor que um banco precise processar diversas transações financeiras diariamente, esse processamento precisa ser rápido e confiável. Além disso, isso deve ser feito periodicamente e sem interrupções. Um job (tarefa) é uma aplicação que processa uma quantidade finita de dados sem interação ou interrupção.
Spring Roo é uma ferramenta para o desenvolvimento rápido e fácil de aplicações Java, gerando parte do código fonte de uma aplicação com apenas algumas configurações e comandos iniciais feitos em linha de comando. Ele é capaz de gerar código de alguns dos principais frameworks Java, como o Spring, Hibernate, JSF e o GWT, utilizando o Maven. Além disso, a ferramenta também gera testes funcionais automatizados (com Selenium) e testes unitários (com JUnit).
Spring Shell é uma ferramenta para criar um aplicativo de linha de comando (shell) completo para aplicativos Java. Com ele, podemos escrever nossos próprios comandos, como por exemplo, comandos para interagir com a API REST do seu projeto com conteúdo de arquivo local.
Spring Web Services (Spring-WS) é um framework focado em facilitar a criação de serviços Web orientados a documentos, facilitando o desenvolvimento de serviços SOAP com contrato inicial (contract-first). O framework é capaz de gerar um WSDL baseando-se em um XSD e, então, mapear as mensagens para endpoints. Ele também oferece abstrações sobre APIs de parsing XML, suporte ao WS-Security e diferentes protocolos de transporte.
Spring Web Flow é um framework que foi criado pelo Spring para facilitar o gerenciamento do fluxo de navegação em websites. Com o Web Flow, o fluxo de navegação é construído por meio da definição dos estados pelos quais o usuário passa e para chegar em cada um dos estados, o usuário dispara eventos. Por sua vez, entre os eventos que fazem as passagens de um estado para outro temos as transições de estado. Todo esse mecanismo citado é especificado em regras dentro de um arquivo XML, permitindo o seu reuso e diminuindo a escrita de código.
Spring Webflux é um módulo que possibilita que aplicações web com Spring do lado servidor trabalhem de forma reativa. Quando o Spring MVC é utilizado para construir aplicações web, o processamento é feito de mono síncrono e bloqueante. Com o Spring Webflux, podemos construir aplicações que sejam assíncronas e não bloqueantes (trabalham com várias requisições simultaneamente). Ele é baseado no projeto Reactor, que é uma biblioteca de programação reativa sem bloqueio para a JVM. Tanto o Webflux quando o Reactor possuem dois tipos: Flux (consiste em um fluxo de 0 a n elementos) e Mono (consiste em um fluxo de 0 ou 1 elemento).
Swagger é um framework para descrição, consumo e visualização de serviços RESTful. Seu objetivo é permitir que a documentação possa evoluir no mesmo ritmo da implementação, já que pode ser gerada automaticamente com base em anotações do código.
Microserviços são uma abordagem de arquitetura do desenvolvimento de software para a criação de aplicações, onde o software consiste em pequenos serviços independentes que se comunicam usando APIs bem definidas. A diferença entre a arquitetura de microserviços e as abordagens monolíticas tradicionais é como ela decompõe a aplicação por funções básicas. Cada uma das funções é chamada de serviço e pode ser criada e implementada de maneira independente, ou seja, cada serviço individual pode funcionar ou falhar sem comprometer os demais.
Spring Cloud fornece ferramentas para os desenvolvedor criarem alguns dos padrões em sistemas distribuídos de forma mais clara (ex: gerenciamento de configuração, tokens únicos, bloqueios globais, eleição de liderança, estado do cluster, etc). A coordenação de sistemas distribuídos leva a padrões padronizados e, usando o Spring Cloud, os desenvolvedores podem criar rapidamente serviços e aplicativos que implementam esses padrões.
Data Transfer Object (DTO) é um padrão de projetos utilizado para o transporte de dados entre diferentes componentes de um sistema, diferentes instâncias ou processos de um sistema distribuído ou diferentes sistemas via serialização. A ideia consiste em agrupar um conjunto de atributos numa classe simples de forma a otimizar a comunicação. Com o DTO, é possível retornar apenas os argumentos desejados de uma determinada entidade, deixando a aplicação maias segura.
Apache Camel é um framework de integração de código-fonte aberto, que torna a integração de sistemas bastante simples. Essencialmente, ele é um roteador (routing engine), roteando os dados entre dois endpoints. O desenvolvedor define a origem dos dados, o destino, e a forma a qual ele será processado. O Camel não determina o tipo de dado que precisa ser transacionado, o que facilita a interação com vários sistemas, pois aproveita-se a mesma API, independentemente do protocolo ou tipo de dado de dado utilizado.
Tomcat é um servidor de internet desenvolvido pela Apache Software Foundation. Ele é, basicamente, um servidor HTTP. A diferença é que ele executa aplicações em Java, ao invés de site estáticos em HTML. Ele roda várias especificações diferentes do Java, como o Java EE, Java Servlet, JavaServer Pages e WebSocket.
Quanto uma aplicação for construída, há dois tipos de requisitos que devem ser implementados: requisitos funcionais da aplicação (regras de negócio) e requisitos não funcionais (parte da infraestrutura que vão controlar ações como transações, web services, conexões HTTP, etc). O Java EE (Java Enterprise Edition) consiste em uma série de especificações bem detalhadas, dando uma receita de como deve ser implementado um software que faz cada um desses serviços de infraestrutura e, com isso, o desenvolvedor não precisa se preocupar em implementar os requisitos não funcionais. Mas, é necessário utilizar softwares que implementem as especificações Java EE para serem utilizadas em outras aplicações, que são chamadas de servidores de aplicação. Existem também, softwares que implementam apenas uma parte das especificações Java EE, que são chamados de servlet container. Um dos mais utilizados é o Apache Tomcat.
Servlets são uma classe Java usada para estender as funcionalidades de um servidor, sendo uma das formas para se criar páginas dinâmicas utilizando o Java. Apesar de eles poderem responder a quaisquer tipos de requisições, normalmente são usados para estender as aplicações hospedadas por servidores web. O nome servlet vem da ideia de um pequeno servidor que tem objetivo de receber chamada HTTP, processá-las e devolver uma resposta ao cliente. Cada uma das servlet é responsável por uma página, sendo que ela lê os dados da requisição do cliente (request) e responde com dados do outro lado (response). A API Java Servlet proporciona ao desenvolvedor a possibilidade de adicionar conteúdo dinâmico em um servidor web, usando a plataforma Java.
JavaServer Pages (JSP) é uma tecnologia onde podemos usar o HTML de forma direta, juntamente com a utilização do Java. Os servlets permitem que possamos escrever conteúdo dinâmico. Mas, se tivermos que cria-los toda hora para fazer este trabalho, teríamos muitos problemas em nossas páginas e na legibilidade do nosso código, já que sempre apareceria código Java misturado com HTML. Para resolver este problema, foi criada o JSP.
Tomcat é um servidor de web Java desenvolvido pela Apache Software Foundation, é um servlet container. Ele implementa as tecnologias Java Servlet e JavaServer Pages (JSP), dentre algumas de menor relevância, e ele não é um container Enterprise JavaBeans (EJB). O Tomcat é distribuído como software livre e cobre parte da especificação Java EE com tecnologias como servlet e JSP, e tecnologias de apoio relacionadas como Realms e segurança, JNDI Resources e JDBC DataSources. Ele tem a capacidade de atuar também como servidor web ou pode funcionar integrado a um servidor web dedicado como o Apache ou o IIS (Internet Information Services - servidor web criado pela Microsoft para seus sistemas operacionais para servidores). Quando ele foi criado, foi endossado pela Sun Microsystem, oficialmente, como a implementação de referência para as tecnologias Java Servlet e JavaServerPages. Porém, atualmente, a implementação de referência é o GlassFish.
JDBC DataSources é um conjunto de funcionalidades que padroniza e define como pode ser realizado o acesso ao banco de dados de forma transparente aos diversos fabricantes e tecnologias utilizadas para esse acesso.
Sun GlassFish Enterprise Server é um servidor de aplicações rápido e fácil de usar, baseada na Plataforma Java e tecnologia Java EE para o desenvolvimento e entrega de aplicações e serviços web. É um servidor de aplicações de código aberto de nível corporativo que oferece produtividade, confiabilidade, desempenho, facilidade de uso e custando bem menos que os servidores de aplicações proprietárias.
Enterprise JavaBeans (EJB) é um componente da plataforma Java EE que roda container de um servidor de aplicação e é usado para o desenvolvimento de aplicações distribuídas baseadas em componentes que são escaláveis, transacionais e seguros. Normalmente, ele contém a lógica de negócio que atua sobre os dados de negócio.
Java Naming and Directory Interface (JDNI) é uma API que fornece funcionalidade de nomeação e diretório para aplicativos gravados utilizando o Java. Ele é independente de qualquer implementação de serviço de diretório específico e, assim, uma variedade de diretórios podem ser acessados de forma comum.
Java Server Faces (JSF) é um framework onde é efetuada a elaboração de interfaces de usuários para sistema web, colocando componentes em um formulário e ligando-os a objetos Java, fazendo a separação entre a lógica e regras de negócio, a navegação e conexões com serviços externos, de acordo com o modelo MVC. Sua grande vantagem é a possibilidade de possuir um grande número de componentes e um design bastante flexível.
Selenium é um conjunto de ferramentas de código aberto multiplataforma utilizado para testar aplicações web pelo browser de forma automatizada. Ele executa testes de funcionalidade da aplicação web e testes de compatibilidade entre browsers e plataformas diferentes.
JUnit é um framework que facilita o desenvolvimento e execução de testes unitários em código Java. Ele fornece uma API completa para construir os testes e aplicações gráficas, além de um modo console para executar os testes criados. As vantagens de se utilizá-lo são: é orientado a objetos; facilita a criação, execução automática de testes e apresentação dos resultados; é grátis; pode verificar se cada unidade de código funciona da forma esperada.
Thymeleaf é um mecanismo moderno, que serve para criar modelos Java em aplicações Web e independente do lado do servidor, sendo capaz de processar HTML, XML, Javascript, CSS e texto sem formatação. A ideia consiste em dinamizar páginas HTML e exibir o navegador, mas pode ser utilizado também com as páginas estáticas, segundo o conceito de Modelos Naturais para colocar a lógico nos modelos, sem usar o modelo como protótipo de design.
Padrão MVC (Model-View-Controller)
MVC é um padrão de arquitetura de software que separa sua aplicação em 3 camadas. A camada de interação do usuário (View), a camada de manipulação dos dados (Model) e a camada de controle (Controller). O View faz apenas a exibição dos dados (html/xml), o Model é o responsável pela leitura e escrita de dados (além de suas validações). E o Controller é o responsável por receber todas as requisições do usuário e, os seus métodos, chamados de actions, são responsáveis por uma página, controlando qual Model usar e qual View será mostrado ao usuário.
A sequência de criação das classes e pacotes do projeto são: Model (Entity), Repository, Service, Controller.
O Model é onde fica os modelos da aplicação. O Repository é onde fica a classe que fará transações com o banco de dados, ou seja, é um Design Pattern onde os dados são obtidos do banco de dados e é onde ocorre também a regra de negócio e este, retorna objetos de domínio que seriam as Entidades (classes anotadas com @Entity). Ele é a subcamada responsável pela persistência de dados (recuperar, atualizar, inserir e apagar). O Service é outro Design Pattern onde há somente a regra de negócio , ele não tem acesso direto ao banco de dados. É a subcamada responsável pela regra de negócio (valida dados, executa regras de negócios, usa a Repository e a Entity para ter acesso ao banco de dados e persistir os dados). Já o Controller, é utilizado para lidar com a ligação da View com as outras partes do sistema, que são as regras de negócios e o banco de dados.
DAO (Data Access Object) é um padrão para persistência de dados, onde seu principal objetivo é separar as regras de negócio de regras de acesso a banco de dados. Ou seja, é a subcamada responsável pela regra de negócio. Ele é muito utilizado com a arquitetura MVC, onde toda separação de conexões, SQLs e funções diretas ao banco são tratadas no DAO.
COMEÇANDO UM PROJETO COM SPRING INITALIZR
Para criar um projeto do zero Spring, é possível fazer isso de diversas maneiras possíveis, como utilizando o Spring Tools Service ou o site Spring Initalzr. Como essa segunda forma é mais fácil e intuitiva, vamos utilizá-la para criar o nosso projeto. Para começar, acesse o site https://start.spring.io/. Em Novembro de 2020, a interface do sistema estava assim:
Em Project, você pode escolher entre criar o projeto com Maven ou Gradle. Em Language, você seleciona a linguagem do seu projeto. Em Spring Boot, você escolhe a versão do Spring, a que vem marcada como padrão é sempre a última versão estável dele. Em Project Metadata, temos as configurações do projeto, como o grupo, nome, descrição, pacote (Jar ou War) e versão da linguagem escolhida. Em Dependencies, vamos adicionar todas as dependências iniciais que utilizaremos em nosso projeto Spring, no decorrer do projeto, é possível adicionar novas dependências no arquivo Pom.xml. Por fim, em Generate, vamos gerar o nosso projeto inicial em formato ZIP. Algumas dependências disponíveis no Spring e que são muito utilizadas são:
• DataJPA: Para utilizar o Spring Data e outros recursos da JPA e Hibernate.
• Web: Para criar um web service.
• DevTools: Ajuda com questões de restart e live reloading.
• Rest Repositories: Para utilizar o Spring Data Rest em nossos CRUD’s.
• HSQLDB: Para utilizar esse banco de dados em memória.
• Security: permite utilizar as funcionalidade do Spring Security
• Oracle Driver: adiciona os drivers para se utilizar o banco de dados Oracle.
• Data MongoDB: adiciona as dependências do banco MongoDB;
• Lombok: permite utilizar as anotações do Lombok.
Selecionei algumas opções e configurações do projeto, conforme mostrado na imagem a seguir:
Clique em Generate e será baixado o seu projeto em formato ZIP. Descompacte ele na pasta do seu projeto e abre o STS (Spring Tools Service). Dentro do STS, clique em File - > Import... - > Existing Maven Projects - > em Root Directory selecione o caminho do seu projeto - > clique em Finish. Agora, o STS vai baixar todas as dependências necessárias para o projeto funcionar. No arquivo application.properties, é necessário adicionar as configurações do banco de dados (utilizei o banco de dados Oracle) e adicionar as dependências do Oracle no arquivo pom.xml. O arquivo application.properties vai ficar mais ou menos assim:
spring.datasource.url= jdbc:oracle:thin:@localhost:1521:xe
spring.datasource.username=System
spring.datasource.password= suasenha
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.batch.job.enabled=false
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql=true
O campo username e senha são os dados de acesso do banco, em ddl-auto se colocar como “update” o banco será atualizado após cada salvamento de arquivo, se colocar como “create-drop” o banco inteiro será apagado e criado após cada modificação no código e com o “create”, o banco é criado uma vez só. A url é a referência de onde está o banco (pode estar em um site externo).
Pom.xml (Project Object Model) é um arquivo que contém configurações do projeto usados pelo Maven para fazer buid (construir o projeto). Neste arquivo, são adicionadas as dependências de outras bibliotecas que utilizamos no projeto.
Agora, para rodar nosso projeto, basta clicar com o botão direito em cima da pasta do projeto (em Project Explorer) -> Run As... -> Spring Boot App. Com isso, nossa configuração inicial de um projeto Spring terminou. Para ver o resultado, basta abrir o seu navegador e acessar a URL http://localhost:8080 e ver a mensagem de “Ok” que aparece na página!
JPA (Java Persistance API)
Fiz uma pequena apresentação do JPA no início deste artigo, agora irei falar mais um pouco sobre ele. O arquivo Persistence.xml possui todos os arquivos com todas as configurações de acesso de dados (do JPA) e é, através deste arquivo, que o JPA cria o EntityManagerFactory, que é uma fábrica de gerenciamento de entidades (por exemplo, se temos duas bases de dados diferentes, teremos um EntityManagerFactory para cada uma delas). Com o objeto EntityManagerFactory, é possível adquirir diversas EntityManager, ou seja, toda vez que for necessário fazer uma operação, é feito uma requisição de instância de EntityManager e ele é o objeto que vai fazer as operações (persistir, alterar, deletar e consultar) na base de dados. Para fazer as requisições, o JPA utiliza a interface JPA Repository, que contém as operações básicas das entidades e o EntityManager é quem irá fazer essas operações. A classe Repository é declarada como uma Interface que estende o JpaRepository e é ele quem vai realizar todas as operações referentes a uma única entidade. Neste exemplo, ele está referenciando a entidade User com atributo de identificação id do tipo Long. O primeiro parâmetro (User) é a classe que vamos querer que se comunique com o banco de dados. O segundo parâmetro (Long), é a classe Wrapper do ID da classe/tabela, que o banco está fazendo a referência.
O JpaRepository possui alguns métodos próprios para realizar as operações de CRUD e buscas por parâmetros com as nossas classes do Model e que são muito utilizados no dia a dia. Alguns destes métodos são:
o findAll() - retorna uma lista com todos os elementos da classe;
o findAllById() – busca um elemento através do seu id e o retorna;
o save – salva um elemento na tabela (cria um novo elemento);
o saveAll() – salva todos os elementos na tabela (para casos de array ou objetos compostos);
o get() – pegar os elementos para realizar operações, podendo ser combinado com o byId ou o All;
No Service, são criados todos os métodos que farão as operações de CRUD no banco de dados (busca todos, busca por id, salvar dados, atualizar dados, excluir, busca avançada, etc).
O Controller é quem faz o meio de campo entre o back-end e o banco de dados. É nele onde fica todos os métodos com os verbos HTTP de comunicação e é ele quem chamará os métodos de operações que estão nas classes Service.
Containers, Injeção de Dependência e Inversão de Controle
O Spring container é o núcleo do Framework Spring. O container irá cria os objetos, conectá-los, configurá-los e gerencia o seu ciclo de vida completo, da sua criação até a destruição. O container usa injeção de dependência (DI) para gerenciar os componentes que compõe uma aplicação e estes objetos são chamados de Spring Beans. O container obtém suas instruções sobre quais objetos instanciar, configurar e montar lendo os metadados de configuração fornecidos, que são representados por XML, anotação Java ou código Java. O Spring vem com diversas implementações de contêineres, que podem ser categorizados em dois tipos diferentes:
• Bean factories: são tipos simples de container, fornecendo suporte básico para a injeção de dependência);
• ApplicationContext: baseiam-se na noção de bean factories, mas adiciona algumas funcionalidades extraa em comparação com sua classe pai. O Spring vem com diferentes sabores de ApplicationContext, as mais utilizadas são:
o AnnotationConfigApplicationContext: Carrega um contexto de aplicação Spring de uma ou mais classes de configuração baseadas em Java;
o ClassPathXmlApplicationContext: Carrega uma definição de contexto de um ou mais arquivos XML localizados no classpath;
o FileSystemXmlApplicationContext: Carrega uma definição de contexto de um ou mais arquivos XML localizados no sistema de arquivos;
o AnnotationConfigWebApplicationContext: Carrega um contexto de aplicação Web Spring de uma ou mais classes de configuração baseadas em Java.
Bean é uma classe onde o programador declara que o Spring container é quem vai gerenciar as instâncias desta classe, é o Spring quem vai criar gerenciar e destruir todas as instâncias dela. Quando uma classe é marcada com a anotação @Component, @Service, @Resository ou @Controller, o Spring vai saber que essa classe é um Bean e, com isso, essas classes agora podem sofrer pontos de injeção (injeção de dependência).
Inversão de controle é um princípio de engenharia de software pelo qual o controle de objetos ou partes de um programa é transferido para um container ou estrutura e é usado, frequentemente, no contexto da programação orientada a objetos. Em contraste com a programação tradicional, onde nosso código faz chamadas para uma biblioteca, a inversão de controle permite que uma estrutura assuma o controle do fluxo de um programa e faça chamadas para nosso código. Algumas vantagens desta arquitetura são: maior facilidade em testar um programa, isolando um componente ou simulando suas dependências e permitindo que os componentes se comuniquem por meio de contratos; dissociar a execução de uma tarefa de sua implementação; maior modularidade de um programa; entre outros. A inversão de controle pode ser alcançada por meio de vários mecanismos, como por exemplo: padrão de design de estratégia, padrão de localizador de serviço, padrão factory e injeção de dependência.
Injeção de dependências (DI – Dependency Injection) é um tipo de inversão de controle (IoC – Inversion of Control) que dá o nome ao processo de prover instâncias de classes que um objeto precisa para funcionar. Para ativar a injeção de dependência, basta colocar a anotação @Autowired em uma propriedade, método ou construtor. Utilizando o DI em uma propriedade, a classe ficaria assim:
public class ClienteServico {
@Autowired
private ClienteRepositorio repositorio;
//continuação...
}
Guia das Anotações (Annotations) Java e Spring
As anotações foram introduzidas no Java 5 e são utilizadas para anotar métodos, campos e classes, de forma que essas marcações possam ser tratadas pelo compilador, ferramentas de desenvolvimento e bibliotecas. Uma anotação muito utilizada no Java é o @override, que sobrescreve métodos. As anotações são colocadas em cima do atributo/classe/métodos que se deseja referenciar e as mais utilizadas no Spring são:
• @Enumerated = diz que o atributo/método é uma enumeração. A propriedade (value = EnumType.STRING) diz que vamos gravar este ENUM como texto e a propriedade (value = EnumType.ORDINAL) diz que vamos guardá-la como número;
• @SpringBootAplication = habilita diversos recursos, como a configuração do Spring baseado em Java, verificação de componentes e configuração automática do Spring Boot.
• @builder = cria automaticamente o código necessário para instanciar uma classe. Exemplo: Person builder().name(“Adam Savage”).city(“San Fransciso”).build();
• @notblank = indica que este campo não poderá ser nulo (campo obrigatório);
• @lob = permite receber textos grandes e sempre converte a sua variável para bytes no banco de dados (seja para um texto longo ou simplesmente uma sequência de bytes, como no caso de salvar uma imagem);
• @JsonFormat = é utilizada para formatação de data, através da propriedade (shape=JsonFormat.Shape.STRING, pattern="dd-MM-yyyy");
• @Autowired = faz a injeção de dependência;
• @Component = é um dos estereótipos que define para o Spring que a classe será um bean gerenciado por ele. Existe outros estereótipos que são mais recomendados de se utilizar, devido a sua especificidade, como @Service (indica que a classe é um service), @Controller (indica que a classe é um controller), @Repository (indica que a classe é um repository). A @Component é a mais genérica dessas anotações;
• @PostConstructor = é utilizada em métodos que precisam ser executados após a sua classe ser instanciada.
ANOTAÇÕES DE CRUD
• @RequestMapping = determina qual método HTTP será utilizado e qual será sua URL. Por exemplo, em @RequestMapping(value = "/posts", method = RequestMethod.GET) nós temos a URL “/posts” e o método HTTP será o GET (vai buscar informações do banco de dados e retorna-las). Algumas anotações possuem parâmetros para manipular um dado por vez (como o byId) ou todos ao mesmo tempo (como o All). A partir do Spring Framework 4.3, surgiram novas anotações que expressam de forma mais clara o que cada método está fazendo:
o @GetMapping utiliza o verbo GET, buscando informações do banco de dados;
o @PostMapping utiliza o verbo POST, para inserir novos dados no banco de dados;
o @PatchMapping utiliza o verbo PATCH, fazendo alterações em campos do banco de dados;
o @PutMapping utiliza o verbo PUT, fazendo alterações em campos do banco de dados;
o @DeleteMapping utiliza o verbo DELETE, excluindo dados do banco de dados.
• @PathVariable = é utilizado quando o valor da variável é passada diretamente na URL como parte dela, e não como um parâmetro passado após o sinal de interrogação (?);
• @RequestParam = é utilizado quando temos vários parâmetros passados por uma URL (como nome e e-mail);
• @RequestBody = é usada para requisitar um corpo de argumentos em métodos HTTP;
• @Value = indica um valor padrão inicial para um campo (permite configurar uma label);
ANOTAÇÕES DO LOMBOK
• @data = gera, automaticamente, os getters, settters, toString, equalsAndHashCode (mas não cria o construtor) de uma classe. Também é possível colocar o @Getter e o @setter em cada um dos atributos (caso não queira gera-los com o @data);
• @AllArgsConstructor = cria um construtor com todos os atributos;
• @NoArgsConstructor = cria um construtor sem atributos;
• @Getter = gera todos os getters da classe caso seja colocada acima da classe e gera o getter de um atributo, caso seja adiciona acima de um atributo;
• @setter = gera todos os setters da classe caso seja colocada acima da classe e gera o setters de um atributo, caso seja adiciona acima de um atributo;
• @ToString = gera o método toString da classe;
• @EqualsAndHashCode = gera todos os equalsAndHashCode da classe. Usando o parâmetro (exclude= {“firstName”, “lastName”}), é possível ignorar alguns dos campos na geração dos equals/hashCode;
• @builder = cria objetos sem a necessidade de construtores e métodos setter, (caso os objetos sejam imutáveis);
ANOTAÇÕES DE BANCO DE DADOS/JPA
• @Entity = simboliza que uma classe é uma entidade (ela é uma tabela no banco de dados). É a nossa classe principal, onde ficará os atributos dos objetos, construtores, getters e setters. Como é uma tabela, podemos declarar o nome dela usando @Table(name = ”TB_EXEMPLO”);
• @id = declara um atributo como sendo id único da classe;
• @GeneratedValue(strategy = GenerationType.AUTO) = gera um id automaticamente, e embaixo dessa anotação é colocado @SequenceGenerator (name = "useraluno_sequence", sequenceName = "user_seq_id", allocationSize = 1) para criar a sequência dos id de forma automática. Isso é válido caso você esteja utilizando o banco de dados Oracle (que possui tecnologia sequence), caso esteja utilizando o MySQL, você terá que definir o valor inicial direto no banco de dados.
• @OneToMany(mappedBy = “categoria_id”) = informa que o registro de uma entidade está relacionado com vários registros de outra entidade. O parâmetro é usado no lado fraco do relacionamento e faz com que o relacionamento seja bidirecional;
• @ManyToOne = informa um tipo de relacionamento muitos para um (vários registros de uma entidade estão relacionados com um registro de outra entidade);
• @JoinColumn = indica que a classe/atributo na qual você está utilizando é a dona ou o lado forte do relacionamento. Essa anotação adiciona uma chave estrangeira do lado forte;
• @JoinTable = é utilizado para criar uma referência entre duas tabelas. Por exemplo, vamos supor que nós temos as tabelas de Aluno e Faculdade, e que cada faculdade terá vários alunos, mas o aluno vai estudar em apenas uma faculdade. Nesse caso, vamos precisar de uma terceira tabela para fazer o mapeamento dos alunos para a faculdade. Esta tabela intermediária (vamos chamar de Faculdade_Aluno) vai possuir duas chaves estrangeiras (uma de Aluno e outra de Faculdade) para ligar as três tabelas. Para fazermos o mapeamento desta situação, utilizamos a anotação @JoinTable no Spring. Segue um exemplo:
@JoinTable(name="faculdade_aluno",
joinColumns = {@JoinColumn(name = "faculdade_id",
referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "aluno_id",
referencedColumnName = id")})
Requisições HTTP (CRUD)
ResponseEntity é uma função que traduz o retorno de uma requisição, representando toda a resposta HTTP (código de status, cabeçalhos e corpo). Podemos usá-lo para configurar totalmente a resposta HTTP.
Passamos o responseEntity como retorno do método. No retorno, chamamos o ResponseEntity e o método ok(), que representa o status HTTP 200 ok.
Neste método do Controller, que retorna uma busca por id, passamos um optional para buscar o carro. Caso ele encontre o carro pelo id, irá retornar o status 200 OK e os dados do carro, caso contrário, irá retornar o status 404 NOT FOUND.
@ResponseStatus(HttpStatus.CREATED) é uma anotação que retorna um status HTTP toda vez que um método for chamado. O CREATED retorna o status 201 Created, indicando que um novo objeto foi criado com sucesso.
Nas classes SERVICE, vamos criar os métodos de busca e inserção que vamos utilizar em nosso exemplo. Como exemplo, vou utilizar a classe AlunoService:
Nas classes CONTROLLER, vamos utilizar os métodos de busca (que criamos nos SERVICE) para se comunicar com o banco de dados. Como exemplo, vou utilizar a classe AlunoController:
OFF-TOPIC: Vou mostrar um exemplo de como seria esta busca pelo navegador. Vamos ter a URL completa que chama nosso método (http://localhost:8081/produtos/paginador) e passaremos dois parâmetros em nossa busca. Em “pagina=1” estamos dizendo para exibir a página 1 e em “linhas=1” para exibir a busca a partir da primeira linha. A busca pela URL ficará assim: http://localhost:8081/produtos/paginador?pagina=1&linhas=1
Outros aprendizados com Spring
Caso você crie um atributo que contenha data usando o LocalDate, é necessário adicionar em a anotação @Convert(converter = Jsr310JpaConverters.LocalDateConverter.class), para fazer o mapeamento da data de maneira correta.
ComamandLineRunner e populando dados direto no banco
O Spring fornece duas interfaces (CommandLineRunner e ApplicationRunner) para rodar partes específicas de códigos quando a aplicação for totalmente inicializada. Estas interfaces são chamadas um pouco antes do run(), uma vez que a SpringApplication é concluída. Vou utilizar um exemplo para popularmos (inserir) dados no banco de dados sempre que a aplicação iniciar. Explicação do código:
Linhas 3 a 8: injeção de dependência em produtoRepository, categoriaRepository e imagemRepository
Linhas 10 a 12: método principal, que está rodando toda a aplicação do Spring.
Linhas 14 e 15: início do método que está implementando a interface CommandLineRunner.
Linha 16 a 24: Cadastro de um novo item na tabela de Categorias, instanciando um objeto chamado cat1. A classe irá chamar o builder() e chamará os métodos com os campos que serão preenchidos. O Produto e Imagem são duas outras tabelas do nosso banco e a imagem recebeu apenas uma URL como parâmetro.
Linhas 25 a 28: aqui vamos unir o que criamos das tabelas produtos e imagem, e, depois, salvá-las em suas próprias tabelas (JOIN entre as tabelas).
Manipulando Tabelas
No exemplo a seguir, referenciei a ligação das tabelas utilizando as chaves primárias e estrangeiras das mesmas. O fetch=FetchType.EAGER irá carregar todos os produtos que estão relacionado a uma determinada categoria (chamado de Eager Loading, do Hibernate).
O @JsonIgnore é usado no nível de campos, para marcar uma propriedade (ou lista de propriedades) que serão ignoradas (não serão exibidas), conforme o exemplo:
Passando a anotação @Query, nós podemos criar uma busca de dados personalizada. Colocando como parâmetro o nativeQuery como true, é possível passar comandos de busca em SQL puro. O nome do método de busca que estamos criando é o procuraPorNome, como pode ser visto no seguinte exemplo:
REFERENCIAS
https://www.dclick.com.br/2010/09/15/o-que-e-o-maven-e-seus-primeiros-passos-com-a-ferramenta/
https://www.adrianolisboa.com/afinal-de-contas-o-que-e-o-gradle-e-como-usa-lo/
https://blog.algaworks.com/tutorial-jpa/
https://www.tutorialspoint.com/spring/spring_bean_definition.htm
https://medium.com/lifeinhurry/what-is-spring-container-spring-core-9f6755966fe9
https://blog.algaworks.com/injecao-de-dependencias-com-spring/
https://www.baeldung.com/inversion-control-and-dependency-injection-in-spring
https://dicasdejava.com.br/spring-boot-como-criar-a-estrutura-de-uma-aplicacao-web-do-zero-com-spring-initializr/
https://blog.matheuscastiglioni.com.br/criando-meu-primeiro-web-service-com-spring-boot/
Top comments (0)