Dicas úteis para iniciantes em desenvolvimento com Spring
- #Spring
- #Java
Pré-requisitos
- Lógica de programação
- Programação orientada a objetos
- Java
- Conceitos de banco de dados
- Queries básicas de SQL
Acelera o aprendizado
- Conhecer Maven ou Gradle
- SOLID
- Conceitos de design patterns
- Arquitetura MVC
Como funciona o framework Spring?
O Spring tem um guia para iniciantes no site oficial e uma ferramenta que gera o projeto Spring dependendo das opções que você seleciona, é onde se coloca a versão, nome do pacote, as dependências e o tipo de gerenciador dessas dependências que pode ser o Maven ou o Gradle.
Fonte da imagem: spring.io
O que é Maven e Gradle?
Maven e Gradle são ferramentas de automação de compilação e gerenciamento de dependências utilizada principalmente em projetos Java.
O Maven utiliza um arquivo pom.xml para configurar as dependências do projeto e o Gradle usa o script build.gradle.
Eles tem a mesma função, portanto é uma opção do initialzr a se escolher antes de criar um projeto.
Spring e design patterns
Inversão de Controle (IoC): é um princípio fundamental onde o controle do fluxo da aplicação e a criação de objetos são transferidos do código para o container do Spring. O container gerencia o ciclo de vida dos objetos e suas dependências.
O Spring suporta vários tipos de injeção de dependências, um deles usando anotações, como @Autowired, diretamente nos campos da classe.
Annotations
São como um rótulo das classes que adiciona funcionalidades, por exemplo, @Controller, é arquivo que faz parte da camada controller.
Existem dois tipos principais de anotações em Java, as anotações predefinidas fornecidas pela biblioteca padrão Java, como @Override, @Deprecated, @SuppressWarnings e @Autowired e as anotações personalizadas.
Arquitetura
O Spring usa o padrão MVC:
Model - podem ser as entities, uma classe que gera uma tabela com JPA.
View - se for uma aplicação web são páginas HTML, JSP (JavaServer Pages), Thymeleaf ou outro tipo de template.
Controller - classes Java que lidam com as requisições do cliente, executando a lógica de aplicação
Exemplo de uma estrutura de projeto:
- StarWarsService é uma interface de serviço que define o contrato para buscar informações sobre personagens.
- StarWarsServiceImpl é a implementação da interface que utiliza um RestTemplate para consumir a API do Star Wars.
- StarWarsController é um controlador REST que expõe uma endpoint para buscar informações de personagens pelo ID.
- RestTemplate é injetado no StarWarsServiceImpl usando a injeção de dependência do Spring.
com.example.starwarsapi
- StarWarsApiApplication.java
- controller
- StarWarsController.java
- service
- StarWarsService.java
- StarWarsServiceImpl.java
- model
- Character.java
model/Character.java
package com.example.starwarsapi.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Character {
private String name;
private String height;
private String birth_year;
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public String getBirth_year() {
return birth_year;
}
public void setBirth_year(String birth_year) {
this.birth_year = birth_year;
}
}
service/StarWarsService.java
package com.example.starwarsapi.service;
import com.example.starwarsapi.model.Character;
public interface StarWarsService {
Character getCharacterById(String id);
}
service/StarWarsServiceImpl.java
package com.example.starwarsapi.service;
import com.example.starwarsapi.model.Character;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class StarWarsServiceImpl implements StarWarsService {
private final RestTemplate restTemplate;
@Autowired
public StarWarsServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public Character getCharacterById(String id) {
String url = "https://swapi.dev/api/people/" + id + "/";
return restTemplate.getForObject(url, Character.class);
}
}
controller/StarWarsController.java
package com.example.starwarsapi.controller;
import com.example.starwarsapi.model.Character;
import com.example.starwarsapi.service.StarWarsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class StarWarsController {
private final StarWarsService starWarsService;
@Autowired
public StarWarsController(StarWarsService starWarsService) {
this.starWarsService = starWarsService;
}
@GetMapping("/character/{id}")
public Character getCharacter(@PathVariable String id) {
return starWarsService.getCharacterById(id);
}
}
Persistência com Spring
Para utilizar um banco de dados é necessário configurar as dependências e o arquivo application properties, dependendo do banco de dados escolhido. Na maioria das vezes para aprender se usa o h2 que é um banco em memória. É necessário também adiciona o Spring Data JPA.
pom.xml
Spring Data JPA
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
h2
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-h2</artifactId>
</dependency>
Mysql
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
src/main/resources/application.properties
# Configuração H2
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
# Configuração MySQL
spring.datasource.url=jdbc:mysql://localhost:3306/starwarsdb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
O Spring utiliza um outro padrão para o acesso aos dados, o repository, o Spring Data JPA implementa esse tipo de padrão.
Repositório JPA
repository/CharacterRepository.java
package com.example.starwarsapi.repository;
import com.example.starwarsapi.model.Character;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CharacterRepository extends JpaRepository<Character, Long> {
}
Outro exemplo com os métodos padrões do JPA implementados:
@Entity
class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
// getters and setters omitted for brevity
}
interface PersonRepository extends Repository<Person, Long> {
Person save(Person person);
Optional<Person> findById(long id);
}
O JPA tem queries padrões implementadas nas classes e nesse exemplo não tem uma query SQL, mas existe o JPQL (Java Persistence Query Language) que é uma linguagem de consulta orientada a objetos definida pela especificação JPA.
Por exemplo se eu quiser adicionar uma funcionalidade que faça uma busca de personagens por nome.
package com.example.starwarsapi.repository;
import com.example.starwarsapi.model.Character;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CharacterRepository extends JpaRepository<Character, Long> {
// Consulta JPQL para buscar personagens pelo nome
@Query("SELECT c FROM Character c WHERE c.name = ?1")
List<Character> findByName(String name);
}
Na documentação tem mais exemplos e outras formas de implementar consultas de banco de dados, por exemplo o JPA Query Methods:
//select distinct … where x.lastname = ?1 and x.firstname = ?2
findDistinctByLastnameAndFirstname
Conclusão
Essas foram algumas das muitas funcionalidades que o Spring apresenta, um outro muito importante é o Spring Security que também deve ser adicionado como o JPA e é serve para criar autenticação e autorização de usuários dentre outras funções de segurança.
Aprender Java, orientação a objetos é fundamental para aplicar essas funcionalidades na criação de uma aplicação web e a documentação apresenta diversos exemplos de como aplicar.
Esse framework vem sendo muito utilizado nos últimos anos e facilita muito no desenvolvimento web.
Referências e links úteis
Algaworks
https://www.youtube.com/watch?v=ODXvvEzXlQY&t=1644s
Documentação
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.core-concepts
Baeldung
https://www.baeldung.com/spring-data-derived-queries
Loiane Groner
https://www.youtube.com/watch?v=qJnjz8FIs6Q&list=PLGxZ4Rq3BOBpwaVgAPxTxhdX_TfSVlTcY
Nélio Alves
https://www.youtube.com/watch?v=nQr_X62vq-k&list=PLCoqDTAuppHN87Cvx8QHBet1xQA4oY_BO
https://www.youtube.com/watch?v=e0ItyfvbhMw&list=PL4VsmfTZJAc6lR4OGoaR0fZBAA2UdULkY&index=23&t=23s
#Java