Capítulo 2: Estrutura de um Projeto Spring Boot
Introdução
Um projeto Spring Boot segue uma estrutura padronizada baseada nas convenções do Maven. Essa organização facilita a navegação no código e permite que os desenvolvedores encontrem rapidamente os arquivos necessários.
Objetivos do Capítulo
Ao final deste capítulo, você será capaz de:
- Entender a organização dos diretórios de um projeto Spring Boot
- Identificar o papel de cada arquivo importante
- Organizar seu código de acordo com as boas práticas
- Navegar de forma eficiente em um projeto Spring Boot
Visão Geral da Estrutura
Estrutura Completa
greeting-app/
├── .mvn/ # Maven Wrapper
│ └── wrapper/
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── src/
│ ├── main/
│ │ ├── java/ # Código-fonte Java
│ │ │ └── com/example/greeting/
│ │ │ └── GreetingApplication.java
│ │ └── resources/ # Recursos da aplicação
│ │ ├── static/ # Arquivos estáticos (CSS, JS, imagens)
│ │ ├── templates/ # Templates (Thymeleaf, Freemarker)
│ │ ├── application.properties # Configuração principal
│ │ └── application.yml # Configuração YAML (alternativa)
│ └── test/
│ ├── java/ # Testes unitários e de integração
│ │ └── com/example/greeting/
│ │ └── GreetingApplicationTests.java
│ └── resources/ # Recursos de teste
│ └── application-test.properties
├── target/ # Arquivos compilados (gerado)
├── .gitignore # Arquivos ignorados pelo Git
├── mvnw # Maven wrapper (Unix/macOS)
├── mvnw.cmd # Maven wrapper (Windows)
├── pom.xml # Configuração Maven
├── HELP.md # Documentação gerada
└── README.md # Documentação do projeto
Diretório Raiz
1. Arquivo pom.xml
Papel: Arquivo de configuração do Maven (Project Object Model)
Conteúdo principal:
<?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>
<!-- Parent Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/>
</parent>
<!-- Identificadores do projeto -->
<groupId>com.example</groupId>
<artifactId>greeting</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>greeting</name>
<description>Application de salutation</description>
<!-- Propriedades -->
<properties>
<java.version>17</java.version>
</properties>
<!-- Dependências -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- Plugin de build -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Seções importantes:
| Seção | Descrição |
|---|---|
<parent> | Herda a configuração do Spring Boot |
<groupId>, <artifactId>, <version> | Coordenadas Maven do projeto |
<properties> | Configuração global (versão Java, encoding, etc.) |
<dependencies> | Lista de dependências do projeto |
<build> | Configuração do processo de build |
2. Maven Wrapper (mvnw, mvnw.cmd)
Papel: Permite executar o Maven sem instalá-lo globalmente
Vantagens:
- Garante a versão do Maven para todos os desenvolvedores
- Não é necessário instalar o Maven manualmente
- Scripts incluídos no projeto
Uso:
Linux/macOS:
./mvnw clean install
./mvnw spring-boot:run
Windows:
mvnw.cmd clean install
mvnw.cmd spring-boot:run
3. Arquivo .gitignore
Papel: Lista de arquivos que não devem ser versionados com o Git
Conteúdo típico:
# Arquivos compilados
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
# IDE
.idea/
*.iml
.vscode/
.classpath
.project
.settings/
# Sistema
.DS_Store
Thumbs.db
# Logs
*.log
# Arquivos temporários
*.tmp
*.bak
Diretório src/main/java
Estrutura dos Pacotes
Convenção: Organizar o código em camadas funcionais
src/main/java/com/example/greeting/
├── GreetingApplication.java # Classe principal
├── controller/ # Controllers REST/MVC
│ ├── GreetingController.java
│ └── UserController.java
├── service/ # Lógica de negócio
│ ├── GreetingService.java
│ └── UserService.java
├── repository/ # Acesso a dados
│ ├── UserRepository.java
│ └── ProductRepository.java
├── model/ # Entidades e DTOs
│ ├── entity/
│ │ ├── User.java
│ │ └── Product.java
│ └── dto/
│ ├── UserDTO.java
│ └── ProductDTO.java
├── config/ # Configuração Spring
│ ├── SecurityConfig.java
│ └── DatabaseConfig.java
├── exception/ # Tratamento de erros
│ ├── ResourceNotFoundException.java
│ └── GlobalExceptionHandler.java
└── util/ # Classes utilitárias
└── DateUtil.java
Arquitetura em Camadas
Responsabilidades de cada camada:
| Camada | Papel | Anotações |
|---|---|---|
| Controller | Gerencia as requisições HTTP | @RestController, @Controller |
| Service | Lógica de negócio | @Service |
| Repository | Acesso a dados | @Repository, interface JPA |
| Model | Representação dos dados | @Entity, POJO |
Classe Principal: GreetingApplication.java
Conteúdo:
package com.example.greeting;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GreetingApplication {
public static void main(String[] args) {
SpringApplication.run(GreetingApplication.class, args);
}
}
Anotação @SpringBootApplication:
Esta anotação é um atalho que combina três anotações:
@SpringBootApplication
=
@SpringBootConfiguration // Configuração Spring
+ @EnableAutoConfiguration // Auto-configuração
+ @ComponentScan // Scan de componentes
Papel de cada anotação:
Diretório src/main/resources
Visão Geral
src/main/resources/
├── static/ # Arquivos estáticos
│ ├── css/
│ │ └── style.css
│ ├── js/
│ │ └── script.js
│ └── images/
│ └── logo.png
├── templates/ # Templates (Thymeleaf)
│ ├── index.html
│ └── user.html
├── application.properties # Configuração principal
├── application-dev.properties # Configuração desenvolvimento
├── application-prod.properties # Configuração produção
├── application.yml # Configuração YAML (alternativa)
├── banner.txt # Banner personalizado na inicialização
└── data.sql # Script SQL de inicialização
1. Diretório static/
Papel: Contém arquivos estáticos servidos diretamente
Tipos de arquivos:
- CSS (folhas de estilo)
- JavaScript (scripts client-side)
- Imagens (PNG, JPG, SVG)
- Fonts (fontes personalizadas)
Acesso:
http://localhost:8080/css/style.css
http://localhost:8080/js/script.js
http://localhost:8080/images/logo.png
Estrutura recomendada:
static/
├── css/
├── js/
├── images/
├── fonts/
└── favicon.ico
2. Diretório templates/
Papel: Contém os templates de views (caso utilize um template engine)
Motores de template suportados:
- Thymeleaf (recomendado)
- Freemarker
- Mustache
- Groovy Templates
Exemplo Thymeleaf:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Greeting</title>
</head>
<body>
<h1 th:text="${message}">Default message</h1>
</body>
</html>
3. Arquivo application.properties
Papel: Configuração principal da aplicação
Formato: chave=valor
Exemplos de configurações:
# Porta do servidor
server.port=8080
# Nome da aplicação
spring.application.name=greeting-app
# Configuração do banco de dados
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=postgres
spring.datasource.password=secret
# JPA/Hibernate
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
# Logs
logging.level.root=INFO
logging.level.com.example=DEBUG
# Formato de datas
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=America/Montreal
4. Arquivo application.yml (Alternativa)
Papel: Mesmo que application.properties, mas em formato YAML
Formato: Hierárquico com indentação
Exemplo equivalente:
server:
port: 8080
spring:
application:
name: greeting-app
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: postgres
password: secret
jpa:
hibernate:
ddl-auto: update
show-sql: true
logging:
level:
root: INFO
com.example: DEBUG
Comparação:
| Formato | Vantagens | Desvantagens |
|---|---|---|
| properties | Simples, familiar | Repetitivo para estruturas complexas |
| yml | Legível, hierárquico | Sensível à indentação |
5. Profiles de Configuração
Conceito: Configurações diferentes conforme o ambiente
Arquivos de profiles:
application.properties # Configuração padrão
application-dev.properties # Desenvolvimento
application-test.properties # Testes
application-prod.properties # Produção
Ativação de um profile:
Via application.properties:
spring.profiles.active=dev
Via linha de comando:
java -jar app.jar --spring.profiles.active=prod
Via variável de ambiente:
export SPRING_PROFILES_ACTIVE=prod
Exemplo de configuração por ambiente:
application-dev.properties:
server.port=8080
spring.datasource.url=jdbc:h2:mem:testdb
logging.level.root=DEBUG
application-prod.properties:
server.port=80
spring.datasource.url=jdbc:postgresql://prod-server:5432/mydb
logging.level.root=WARN
Diretório src/test/java
Estrutura dos Testes
src/test/java/com/example/greeting/
├── GreetingApplicationTests.java # Teste de inicialização
├── controller/
│ └── GreetingControllerTest.java # Testes do controller
├── service/
│ └── GreetingServiceTest.java # Testes do service
└── repository/
└── UserRepositoryTest.java # Testes do repository
Teste de Inicialização Padrão
package com.example.greeting;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class GreetingApplicationTests {
@Test
void contextLoads() {
// Verifica se o contexto Spring carrega corretamente
}
}
Papel: Verificar se a aplicação inicia sem erros
Diretório target/
Papel: Contém os arquivos compilados e o JAR final
Gerado por: Maven durante o build
Conteúdo:
target/
├── classes/ # Classes compiladas (.class)
├── test-classes/ # Testes compilados
├── generated-sources/ # Fontes geradas
├── maven-status/ # Status do Maven
└── greeting-0.0.1-SNAPSHOT.jar # JAR executável final
Importante: Este diretório é ignorado pelo Git (no .gitignore)
Limpeza:
mvn clean
Organização por Funcionalidade vs por Camada
Abordagem 1: Por Camada (Recomendada para projetos pequenos)
com.example.greeting/
├── controller/
│ ├── UserController.java
│ └── ProductController.java
├── service/
│ ├── UserService.java
│ └── ProductService.java
├── repository/
│ ├── UserRepository.java
│ └── ProductRepository.java
└── model/
├── User.java
└── Product.java
Vantagens:
- Simples e clara
- Fácil de entender para iniciantes
- Padrão do Spring Boot
Desvantagens:
- Difícil de escalar para projetos grandes
- Acoplamento entre funcionalidades
Abordagem 2: Por Funcionalidade (Recomendada para projetos grandes)
com.example.greeting/
├── user/
│ ├── UserController.java
│ ├── UserService.java
│ ├── UserRepository.java
│ └── User.java
├── product/
│ ├── ProductController.java
│ ├── ProductService.java
│ ├── ProductRepository.java
│ └── Product.java
└── order/
├── OrderController.java
├── OrderService.java
├── OrderRepository.java
└── Order.java
Vantagens:
- Alta coesão
- Baixo acoplamento
- Facilita a migração para arquitetura de microservices
Desvantagens:
- Menos padrão
- Pode ser confuso no início
Convenções de Nomenclatura
Pacotes
Convenção: Tudo em minúsculas, palavras separadas por pontos
com.example.greeting // ✅ Correto
com.example.greeting.service // ✅ Correto
com.Example.Greeting // ❌ Errado (maiúsculas)
com.example.greeting_service // ❌ Errado (underscore)
Classes
Convenção: PascalCase (primeira letra de cada palavra em maiúscula)
UserController // ✅ Correto
GreetingService // ✅ Correto
userController // ❌ Errado (começa com minúscula)
user_controller // ❌ Errado (underscore)
Sufixos recomendados:
| Tipo | Sufixo | Exemplo |
|---|---|---|
| Controller | Controller | UserController |
| Service | Service | UserService |
| Repository | Repository | UserRepository |
| Entity | Nenhum | User, Product |
| DTO | DTO | UserDTO, CreateUserDTO |
| Exception | Exception | ResourceNotFoundException |
| Configuração | Config | SecurityConfig |
Métodos
Convenção: camelCase (primeira letra minúscula)
getUserById() // ✅ Correto
findAllUsers() // ✅ Correto
GetUserById() // ❌ Errado (começa com maiúscula)
get_user_by_id() // ❌ Errado (underscore)
Variáveis e Atributos
Convenção: camelCase
String userName; // ✅ Correto
int userId; // ✅ Correto
String UserName; // ❌ Errado (começa com maiúscula)
String user_name; // ❌ Errado (underscore)
Constantes
Convenção: SCREAMING_SNAKE_CASE (tudo em maiúsculas, underscores)
public static final int MAX_USERS = 100; // ✅ Correto
public static final String API_BASE_URL = "/api/v1"; // ✅ Correto
public static final int maxUsers = 100; // ❌ Errado (camelCase)
Exercícios Práticos
Exercício 1: Explorar a Estrutura
Objetivo: Familiarizar-se com a estrutura de um projeto
Instruções:
- Crie um projeto com o Spring Initializr (apenas Spring Web)
- Importe-o no VS Code
- Identifique:
- O arquivo pom.xml
- A classe principal
- O arquivo application.properties
- O diretório de testes
- Desenhe a estrutura em papel
Exercício 2: Criar uma Estrutura de Pacotes
Objetivo: Organizar o código em camadas
Instruções:
- No projeto anterior, crie a estrutura:
com.example.demo/
├── controller/
├── service/
├── repository/
└── model/ - Crie classes vazias em cada pacote
- Verifique a compilação
Exercício 3: Configurar Profiles
Objetivo: Criar configurações por ambiente
Instruções:
- Crie
application-dev.properties:server.port=8080
logging.level.root=DEBUG - Crie
application-prod.properties:server.port=80
logging.level.root=WARN - Teste a ativação de cada profile
Perguntas de Revisão
-
Qual arquivo contém as dependências do Maven?
-
Para que serve o diretório
target/? -
Qual a diferença entre
static/etemplates/? -
O que contém a anotação
@SpringBootApplication? -
Como nomear um arquivo de configuração para o ambiente de desenvolvimento?
-
Qual é a convenção de nomenclatura para classes controller?
-
Onde você coloca os arquivos CSS e JavaScript?
-
Qual a diferença entre
application.propertieseapplication.yml?
Resumo do Capítulo
Pontos-Chave
- A estrutura do Spring Boot segue as convenções do Maven
- O código-fonte está em
src/main/java - Os recursos estão em
src/main/resources - Organização em camadas: Controller → Service → Repository
- Os testes ficam em
src/test/java - Os arquivos de configuração utilizam profiles
Boas Práticas
- Respeitar as convenções de nomenclatura Java
- Organizar o código em pacotes lógicos
- Separar as configurações por ambiente
- Utilizar sufixos descritivos para as classes
- Comentar códigos complexos
- Manter uma estrutura clara e coerente
Próximos Passos
No próximo capítulo, vamos aprofundar em:
Capítulo 3: Configuração com application.properties
- Propriedades disponíveis do Spring Boot
- Configuração de banco de dados
- Configuração de logs
- Propriedades customizadas