Saltar al contenido principal

Capítulo 2: Estructura de un Proyecto Spring Boot

Introducción​

Un proyecto Spring Boot sigue una estructura estandarizada basada en las convenciones de Maven. Esta organización facilita la navegación en el código y permite a los desarrolladores encontrar rápidamente los archivos necesarios.

Objetivos del Capítulo​

Al finalizar este capítulo, usted será capaz de:

  • Comprender la organización de los directorios de un proyecto Spring Boot
  • Identificar el rol de cada archivo importante
  • Organizar su código según las buenas prácticas
  • Navegar eficazmente en un proyecto Spring Boot

Vista General de la Estructura​

Árbol Completo​

greeting-app/
├── .mvn/ # Maven Wrapper
│ └── wrapper/
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── src/
│ ├── main/
│ │ ├── java/ # Código fuente Java
│ │ │ └── com/example/greeting/
│ │ │ └── GreetingApplication.java
│ │ └── resources/ # Recursos de la aplicación
│ │ ├── static/ # Archivos estáticos (CSS, JS, imágenes)
│ │ ├── templates/ # Plantillas (Thymeleaf, Freemarker)
│ │ ├── application.properties # Configuración principal
│ │ └── application.yml # Configuración YAML (alternativa)
│ └── test/
│ ├── java/ # Tests unitarios y de integración
│ │ └── com/example/greeting/
│ │ └── GreetingApplicationTests.java
│ └── resources/ # Recursos de test
│ └── application-test.properties
├── target/ # Archivos compilados (generado)
├── .gitignore # Archivos a ignorar por Git
├── mvnw # Maven wrapper (Unix/macOS)
├── mvnw.cmd # Maven wrapper (Windows)
├── pom.xml # Configuración Maven
├── HELP.md # Documentación generada
└── README.md # Documentación del proyecto

Directorio Raíz​

1. Archivo pom.xml​

Rol: Archivo de configuración Maven (Project Object Model)

Contenido 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>

<!-- Identifiants du projet -->
<groupId>com.example</groupId>
<artifactId>greeting</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>greeting</name>
<description>Application de salutation</description>

<!-- Propriétés -->
<properties>
<java.version>17</java.version>
</properties>

<!-- Dépendances -->
<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>

Secciones importantes:

SecciónDescripción
<parent>Hereda la configuración de Spring Boot
<groupId>, <artifactId>, <version>Coordenadas Maven del proyecto
<properties>Configuración global (versión de Java, codificación, etc.)
<dependencies>Lista de dependencias del proyecto
<build>Configuración del proceso de build

2. Maven Wrapper (mvnw, mvnw.cmd)​

Rol: Permite ejecutar Maven sin instalarlo globalmente

Ventajas:

  • Versión de Maven garantizada para todos los desarrolladores
  • No es necesario instalar Maven manualmente
  • Scripts incluidos en el proyecto

Uso:

Linux/macOS:

./mvnw clean install
./mvnw spring-boot:run

Windows:

mvnw.cmd clean install
mvnw.cmd spring-boot:run

3. Archivo .gitignore​

Rol: Lista de archivos que no se deben versionar con Git

Contenido típico:

# Fichiers compilés
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

# IDE
.idea/
*.iml
.vscode/
.classpath
.project
.settings/

# Système
.DS_Store
Thumbs.db

# Logs
*.log

# Fichiers temporaires
*.tmp
*.bak

Directorio src/main/java​

Estructura de los Packages​

Convención: Organizar el código en capas funcionales

src/main/java/com/example/greeting/
├── GreetingApplication.java # Clase principal
├── controller/ # Controladores REST/MVC
│ ├── GreetingController.java
│ └── UserController.java
├── service/ # Lógica de negocio
│ ├── GreetingService.java
│ └── UserService.java
├── repository/ # Acceso a datos
│ ├── UserRepository.java
│ └── ProductRepository.java
├── model/ # Entidades y DTOs
│ ├── entity/
│ │ ├── User.java
│ │ └── Product.java
│ └── dto/
│ ├── UserDTO.java
│ └── ProductDTO.java
├── config/ # Configuración de Spring
│ ├── SecurityConfig.java
│ └── DatabaseConfig.java
├── exception/ # Gestión de errores
│ ├── ResourceNotFoundException.java
│ └── GlobalExceptionHandler.java
└── util/ # Clases utilitarias
└── DateUtil.java

Arquitectura en Capas​

Responsabilidades de cada capa:

CapaRolAnotaciones
ControllerGestión de las solicitudes HTTP@RestController, @Controller
ServiceLógica de negocio@Service
RepositoryAcceso a datos@Repository, interfaz JPA
ModelRepresentación de los datos@Entity, POJO

Clase Principal: GreetingApplication.java​

Contenido:

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);
}
}

Anotación @SpringBootApplication:

Esta anotación es un atajo que combina tres anotaciones:

@SpringBootApplication
=
@SpringBootConfiguration // Configuración de Spring
+ @EnableAutoConfiguration // Auto-configuración
+ @ComponentScan // Escaneo de componentes

Rol de cada anotación:


Directorio src/main/resources​

Vista General​

src/main/resources/
├── static/ # Archivos estáticos
│ ├── css/
│ │ └── style.css
│ ├── js/
│ │ └── script.js
│ └── images/
│ └── logo.png
├── templates/ # Plantillas (Thymeleaf)
│ ├── index.html
│ └── user.html
├── application.properties # Configuración principal
├── application-dev.properties # Configuración desarrollo
├── application-prod.properties # Configuración producción
├── application.yml # Configuración YAML (alternativa)
├── banner.txt # Banner personalizado al inicio
└── data.sql # Script SQL de inicialización

1. Directorio static/​

Rol: Contiene los archivos estáticos servidos directamente

Tipos de archivos:

  • CSS (hojas de estilo)
  • JavaScript (scripts del lado del cliente)
  • Imágenes (PNG, JPG, SVG)
  • Fonts (tipografías personalizadas)

Acceso:

http://localhost:8080/css/style.css
http://localhost:8080/js/script.js
http://localhost:8080/images/logo.png

Estructura recomendada:

static/
├── css/
├── js/
├── images/
├── fonts/
└── favicon.ico

2. Directorio templates/​

Rol: Contiene las plantillas de vistas (si utiliza un motor de plantillas)

Motores de plantillas soportados:

  • Thymeleaf (recomendado)
  • Freemarker
  • Mustache
  • Groovy Templates

Ejemplo 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. Archivo application.properties​

Rol: Configuración principal de la aplicación

Formato: clave=valor

Ejemplos de configuraciones:

# Puerto del servidor
server.port=8080

# Nombre de la aplicación
spring.application.name=greeting-app

# Configuración de la base de datos
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 fechas
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=America/Montreal

4. Archivo application.yml (Alternativa)​

Rol: Igual que application.properties pero en formato YAML

Formato: Jerárquico con indentación

Ejemplo 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

Comparación:

FormatoVentajasDesventajas
propertiesSimple, familiarRepetitivo para estructuras complejas
ymlLegible, jerárquicoSensible a la indentación

5. Perfiles de Configuración​

Concepto: Configuraciones diferentes según el entorno

Archivos de perfiles:

application.properties           # Configuración por defecto
application-dev.properties # Desarrollo
application-test.properties # Tests
application-prod.properties # Producción

Activación de un perfil:

Vía application.properties:

spring.profiles.active=dev

Vía línea de comandos:

java -jar app.jar --spring.profiles.active=prod

Vía variable de entorno:

export SPRING_PROFILES_ACTIVE=prod

Ejemplo de configuración por entorno:

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

Directorio src/test/java​

Estructura de los Tests​

src/test/java/com/example/greeting/
├── GreetingApplicationTests.java # Test de arranque
├── controller/
│ └── GreetingControllerTest.java # Tests del controlador
├── service/
│ └── GreetingServiceTest.java # Tests del servicio
└── repository/
└── UserRepositoryTest.java # Tests del repository

Test de Arranque por Defecto​

package com.example.greeting;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class GreetingApplicationTests {

@Test
void contextLoads() {
// Vérifie que le contexte Spring se charge correctement
}
}

Rol: Verificar que la aplicación arranca sin errores


Directorio target/​

Rol: Contiene los archivos compilados y el JAR final

Generado por: Maven durante el build

Contenido:

target/
├── classes/ # Clases compiladas (.class)
├── test-classes/ # Tests compilados
├── generated-sources/ # Fuentes generadas
├── maven-status/ # Estado de Maven
└── greeting-0.0.1-SNAPSHOT.jar # JAR ejecutable final

Importante: Este directorio es ignorado por Git (en .gitignore)

Limpieza:

mvn clean

Organización por Funcionalidad vs por Capa​

Enfoque 1: Por Capa (Recomendado para proyectos pequeños)​

com.example.greeting/
├── controller/
│ ├── UserController.java
│ └── ProductController.java
├── service/
│ ├── UserService.java
│ └── ProductService.java
├── repository/
│ ├── UserRepository.java
│ └── ProductRepository.java
└── model/
├── User.java
└── Product.java

Ventajas:

  • Simple y claro
  • Fácil de entender para principiantes
  • Estándar Spring Boot

Desventajas:

  • Difícil de escalar para proyectos grandes
  • Acoplamiento entre funcionalidades

Enfoque 2: Por Funcionalidad (Recomendado para proyectos 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

Ventajas:

  • Alta cohesión
  • Bajo acoplamiento
  • Facilita la transición a una arquitectura de microservicios

Desventajas:

  • Menos estándar
  • Puede ser confuso al principio

Convenciones de Nomenclatura​

Packages​

Convención: Todo en minúsculas, palabras separadas por puntos

com.example.greeting           // ✅ Bien
com.example.greeting.service // ✅ Bien
com.Example.Greeting // ❌ Mal (mayúsculas)
com.example.greeting_service // ❌ Mal (underscore)

Clases​

Convención: PascalCase (primera letra de cada palabra en mayúscula)

UserController        // ✅ Bien
GreetingService // ✅ Bien
userController // ❌ Mal (comienza con minúscula)
user_controller // ❌ Mal (underscore)

Sufijos recomendados:

TipoSufijoEjemplo
ControladorControllerUserController
ServicioServiceUserService
RepositoryRepositoryUserRepository
EntidadNingunoUser, Product
DTODTOUserDTO, CreateUserDTO
ExcepciónExceptionResourceNotFoundException
ConfiguraciónConfigSecurityConfig

Métodos​

Convención: camelCase (primera letra minúscula)

getUserById()         // ✅ Bien
findAllUsers() // ✅ Bien
GetUserById() // ❌ Mal (comienza con mayúscula)
get_user_by_id() // ❌ Mal (underscore)

Variables y Atributos​

Convención: camelCase

String userName;      // ✅ Bien
int userId; // ✅ Bien
String UserName; // ❌ Mal (comienza con mayúscula)
String user_name; // ❌ Mal (underscore)

Constantes​

Convención: SCREAMING_SNAKE_CASE (todo en mayúsculas, underscores)

public static final int MAX_USERS = 100;              // ✅ Bien
public static final String API_BASE_URL = "/api/v1"; // ✅ Bien
public static final int maxUsers = 100; // ❌ Mal (camelCase)

Ejercicios Prácticos​

Ejercicio 1: Explorar la Estructura​

Objetivo: Familiarizarse con la estructura de un proyecto

Instrucciones:

  1. Cree un proyecto con Spring Initializr (solo Spring Web)
  2. Importe el proyecto en VS Code
  3. Identifique:
    • El archivo pom.xml
    • La clase principal
    • El archivo application.properties
    • El directorio de tests
  4. Dibuje el árbol de directorios en papel

Ejercicio 2: Crear una Estructura de Packages​

Objetivo: Organizar el código en capas

Instrucciones:

  1. En el proyecto anterior, cree la estructura:
    com.example.demo/
    ├── controller/
    ├── service/
    ├── repository/
    └── model/
  2. Cree clases vacías en cada package
  3. Verifique la compilación

Ejercicio 3: Configurar Perfiles​

Objetivo: Crear configuraciones por entorno

Instrucciones:

  1. Cree application-dev.properties:
    server.port=8080
    logging.level.root=DEBUG
  2. Cree application-prod.properties:
    server.port=80
    logging.level.root=WARN
  3. Pruebe la activación de cada perfil

Preguntas de Repaso​

  1. ¿Qué archivo contiene las dependencias de Maven?

  2. ¿Para qué sirve el directorio target/?

  3. ¿Cuál es la diferencia entre static/ y templates/?

  4. ¿Qué contiene la anotación @SpringBootApplication?

  5. ¿Cómo nombrar un archivo de configuración para el entorno de desarrollo?

  6. ¿Cuál es la convención de nomenclatura para las clases de controlador?

  7. ¿Dónde coloca los archivos CSS y JavaScript?

  8. ¿Cuál es la diferencia entre application.properties y application.yml?


Resumen del Capítulo​

Puntos Clave​

  • La estructura Spring Boot sigue las convenciones de Maven
  • El código fuente está en src/main/java
  • Los recursos están en src/main/resources
  • Organización en capas: Controller → Service → Repository
  • Los tests están en src/test/java
  • Los archivos de configuración utilizan perfiles

Buenas Prácticas​

  • Respetar las convenciones de nomenclatura de Java
  • Organizar el código en packages lógicos
  • Separar las configuraciones por entorno
  • Utilizar sufijos descriptivos para las clases
  • Comentar el código complejo
  • Mantener una estructura clara y coherente

Próximos Pasos​

En el siguiente capítulo profundizaremos en:

Capítulo 3: Configuración con application.properties

  • Propiedades disponibles de Spring Boot
  • Configuración de la base de datos
  • Configuración de logs
  • Propiedades personalizadas

Volver al Módulo 2