
Aprende a desarrollar aplicaciones Java de forma ágil y eficiente con Spring Boot, el framework que automatiza configuraciones y acelera tu desarrollo.
Prepara automáticamente los ingredientes (dependencias).
Ajusta el horno a la temperatura justa (configuración automática).
Sirve platos rápidamente (desarrollo ágil).
Y nos da recetas reutilizables (anotaciones y convenciones).
Imaginemos que Spring Boot es como un chef experto que nos guía para preparar platos sofisticados (aplicaciones Java), sin que tengamos que preocuparnos por todos los ingredientes técnicos o técnicas complicadas.
Tres formas de preparar nuestro entorno de cocina Spring Boot:
Acceder a https://start.spring.io y seleccionar:
Descargar el proyecto .zip, descomprimir e importar en el IDE.
curl https://start.spring.io/starter.zip -d dependencies=web,devtools,lombok -d name=demo -d type=maven-project -d language=java -o demo.zipIDE como IntelliJ IDEA o Spring Tool Suite permiten crear proyectos Spring Boot con asistentes.
@Controller
public class HolaMundoController {
@GetMapping("/")
public String saludar(Model model) {
model.addAttribute("mensaje", "¡Hola mundo desde Spring Boot!");
return "hola";
}
}<!DOCTYPE html>
<html>
<head>
<title>Hola</title>
</head>
<body>
<h1 th:text="${mensaje}">Mensaje de prueba</h1>
</body>
</html>Plantilla hola.html en src/main/resources/templates/
Dependencia necesaria en pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>Crear una clase con la anotación @RestController
Usar @GetMapping para especificar la ruta
Spring convertirá automáticamente a JSON
@RestController
public class HolaMundoRestController {
@GetMapping("/api/hola")
public String saludar() {
return "¡Hola mundo desde una API REST!";
}
}@Autowired y para qué sirve?La anotación @Autowired es uno de los ingredientes principales en la cocina de Spring. Permite inyectar automáticamente dependencias en nuestros componentes, es decir, pedirle al chef que nos traiga los objetos que necesitamos sin tener que crearlos manualmente.
Se puede aplicar en:
setterSe debe usar cuando una clase necesita otra clase para funcionar. En lugar de instanciarla con new, dejamos que Spring se encargue de proporcionarla desde el contenedor.
Supongamos que tenemos un servicio que prepara platos:
@Service
public class CocinaService {
public String preparar(String nombre) {
return "Plato preparado para " + nombre;
}
}Y un controlador que necesita ese servicio:
@RestController
public class RestauranteController {
private final CocinaService cocinaService;
@Autowired // Spring inyecta automáticamente la instancia de CocinaService
public RestauranteController(CocinaService cocinaService) {
this.cocinaService = cocinaService;
}
@GetMapping("/api/ordenar/{nombre}")
public String ordenar(@PathVariable String nombre) {
return cocinaService.preparar(nombre);
}
}Spring detecta que RestauranteController necesita una instancia de CocinaService, la busca entre los componentes disponibles (@Service, @Component, @Repository) y la inyecta automáticamente.
Este patrón se conoce como Inyección de Dependencias, y permite un código más limpio, mantenible y fácil de probar.
En versiones modernas de Spring (a partir de Spring 4.3), la anotación @Autowired ya no es necesaria en constructores si la clase tiene un único constructor. Spring la detecta automáticamente.
@Autowired
public HomeController(MensajeService mensajeService) {
this.mensajeService = mensajeService;
}
// Unnecessary `@Autowired` annotationvscode-spring-boot(JAVA_AUTOWIRED_CONSTRUCTOR)
org.springframework.beans.factory.annotation.Autowired@RequestParam permite capturar parámetros de consulta
@RestController
public class ChefRestController {
@GetMapping("/api/saludo")
public String saludar(@RequestParam String nombre) {
return "Hola, " + nombre + "! Bienvenido a la cocina de Spring Boot.";
}
}@PathVariable captura segmentos de la URL
@RestController
public class PlatoDelDiaController {
@GetMapping("/api/plato/{nombre}")
public String platoDelDia(@PathVariable String nombre) {
return "El plato del día para " + nombre + " es: Pasta al pesto.";
}
}Recibe peticiones y devuelve respuestas
Contiene la lógica de negocio
Accede a los datos
Crear un Servicio:
@Service
public class CocinaService {
public String prepararPlato(String nombre) {
return "Plato preparado especialmente para " + nombre;
}
}Inyectar el Servicio en el Controlador:
@RestController
public class CocinaController {
private final CocinaService cocinaService;
@Autowired
public CocinaController(CocinaService cocinaService) {
this.cocinaService = cocinaService;
}
@GetMapping("/api/preparar/{nombre}")
public String preparar(@PathVariable String nombre) {
return cocinaService.prepararPlato(nombre);
}
}@Entity
public class Curso {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nombre;
private String descripcion;
// Getters y setters
}@Repository
public interface CursoRepository extends JpaRepository {
}@Service
public class CursoService {
@Autowired
private CursoRepository repo;
public List listar() {
return repo.findAll();
}
public Curso guardar(Curso curso) {
return repo.save(curso);
}
public Optional buscar(Long id) {
return repo.findById(id);
}
public void eliminar(Long id) {
repo.deleteById(id);
}
}Método GET que devuelve una lista completa
Método POST que recibe un objeto JSON
Método GET con parámetro de ruta
Método DELETE con parámetro de ruta
@RestController
@RequestMapping("/api/cursos")
public class CursoController {
@Autowired
private CursoService servicio;
@GetMapping
public List listar() {
return servicio.listar();
}
@PostMapping
public Curso guardar(@RequestBody Curso curso) {
return servicio.guardar(curso);
}
@GetMapping("/{id}")
public ResponseEntity obtener(@PathVariable Long id) {
return servicio.buscar(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@DeleteMapping("/{id}")
public ResponseEntity eliminar(@PathVariable Long id) {
servicio.eliminar(id);
return ResponseEntity.noContent().build();
}
}H2 es una base de datos relacional escrita en Java. Es muy rápida, de código abierto, y puede funcionar en modo embebido (en memoria) o en modo servidor.
Es perfecta para desarrollo y pruebas porque se inicia rápidamente, no requiere instalación separada, y los datos se resetean al reiniciar la aplicación.
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:cursosdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=updateAcceder a http://localhost:8080/h2-console para consultar la base de datos.
Agregar dependencia:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Usar anotaciones en la entidad:
public class Curso {
@NotBlank
private String nombre;
@Size(min = 10, max = 200)
private String descripcion;
// ...
}Validar en el controlador:
@PostMapping
public Curso guardar(@Valid @RequestBody Curso curso) {
return servicio.guardar(curso);
}Evitar exponer entidades directamente. Crear clases DTO:
public class CursoDTO {
private String nombre;
private String descripcion;
}Convertir desde/hacia entidad:
public CursoDTO toDto(Curso curso) {
CursoDTO dto = new CursoDTO();
dto.setNombre(curso.getNombre());
dto.setDescripcion(curso.getDescripcion());
return dto;
}Agregar dependencia en pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>Los tests deben colocarse en el directorio src/test/java, siguiendo el mismo paquete que la clase que se desea probar. Por ejemplo, si la clase CursoService está en:
src/main/java/com/ejemplo/servicio/CursoService.javaEl test deberá estar en:
src/test/java/com/ejemplo/servicio/CursoServiceTest.javaEjemplo con JUnit:
@SpringBootTest public class CursoServiceTest {
@Autowired
private CursoService servicio;
@Test
public void testGuardarCurso() {
Curso curso = new Curso();
curso.setNombre("Java Básico");
Curso resultado = servicio.guardar(curso);
assertNotNull(resultado.getId());
}
}Desde el IDE (por ejemplo IntelliJ IDEA o Eclipse):
CursoServiceTest.java y seleccionar Run o Run with Coverage.Desde la línea de comandos con Maven:
./mvnw testEsto ejecutará todos los tests definidos en src/test/java y mostrará el resultado en consola.
Agregar dependencia:
Ejemplo: un curso tiene una lista de alumnos.
@Entity
public class Alumno {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nombre;
@ManyToOne
private Curso curso;
}
@Entity
public class Curso {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nombre;
@OneToMany(mappedBy = "curso")
private List<Alumno> alumnos;
}@Service y para qué sirve?La anotación @Service indica que una clase se comporta como un servicio dentro de la lógica de negocio de la aplicación. Spring la detecta automáticamente y la registra como un componente gestionado por el contenedor.
Ejemplo:
@Service
public class CalculadoraService {
public int sumar(int a, int b) {
return a + b;
}
}@Repository y para qué sirve?La anotación @Repository marca una clase como un componente de acceso a datos. Además de registrarla como componente, Spring proporciona capacidades adicionales como el manejo automático de excepciones relacionadas con la persistencia.
JpaRepository, CrudRepository, etc.@Repository
public interface ProductoRepository extends JpaRepository<Producto, Long> { }@Component y para qué sirve?@Component es la anotación genérica para marcar una clase como componente gestionado por Spring. A diferencia de @Service o @Repository, no tiene semántica de dominio asociada.
@Component
public class GestorMensajes {
public void enviar(String texto) {
System.out.println("Mensaje enviado: " + texto);
}
}El cliente envía una solicitud al servidor
Recibe la petición y la dirige al servicio adecuado
Ejecuta la lógica de negocio y utiliza el repositorio
Interactúa con la base de datos y devuelve resultados
Spring Boot facilita este flujo mediante la inyección de dependencias y la configuración automática, permitiendo que los desarrolladores se centren en la lógica de negocio en lugar de en la infraestructura.
Menos código boilerplate comparado con Spring tradicional
Porcentaje de configuraciones que Spring Boot maneja automáticamente
Reducción aproximada en el tiempo de desarrollo de aplicaciones
Spring Boot actúa como un chef experto que nos permite crear aplicaciones Java sofisticadas sin preocuparnos por todos los detalles técnicos, permitiéndonos concentrarnos en lo que realmente importa: la lógica de negocio de nuestra aplicación.
Añade autenticación y autorización a tu aplicación con configuraciones sencillas.
Desarrolla aplicaciones distribuidas y microservicios con facilidad.
Simplifica el acceso a datos con repositorios predefinidos para diferentes bases de datos.
Herramientas para probar cada capa de tu aplicación de forma aislada o integrada.
Una vez que domines los conceptos básicos de Spring Boot, puedes explorar estos módulos adicionales que te permitirán crear aplicaciones más robustas y completas, como un chef que domina técnicas culinarias avanzadas.
Guía de Introducción a Spring Boot: Cocinando Aplicaciones con un Chef Java