Spring Boot — Introduction
Get started with Spring Boot — what it is, how it differs from Spring Framework, project setup with Spring Initializr, and your first REST endpoint.
Spring Boot is the standard way to build Java backend applications today. It removes the boilerplate configuration of plain Spring Framework and lets you go from zero to a running HTTP server in minutes. The key idea is convention over configuration — Spring Boot makes sensible choices for you based on what’s on the classpath, and you only override the things that need to differ.
Creating a Project
The fastest way is start.spring.io. It generates a complete, buildable project with your chosen dependencies wired up:
- Project: Maven | Language: Java | Spring Boot: 3.x (latest)
- Group:
com.example| Artifact:demo - Java: 21
- Dependencies: Spring Web, Spring Data JPA, MySQL Driver, Validation
- Click Generate — download and unzip
Or use IntelliJ IDEA: File → New Project → Spring Initializr.
Project Structure
Spring Boot follows a standard layout. Understanding where things live helps you know where to put your own code:
demo/
├── src/
│ ├── main/
│ │ ├── java/com/example/demo/
│ │ │ └── DemoApplication.java ← entry point (@SpringBootApplication)
│ │ └── resources/
│ │ ├── application.properties ← all configuration lives here
│ │ └── static/ ← static files (CSS, JS, images)
│ └── test/
│ └── java/com/example/demo/
│ └── DemoApplicationTests.java ← Spring context integration tests
├── pom.xml ← dependencies and build config
└── mvnw ← Maven wrapper (no local Maven needed)
Entry Point
The main class is the only required piece of boilerplate. @SpringBootApplication triggers component scanning, auto-configuration, and marks the class as a configuration source — all three in one annotation. SpringApplication.run bootstraps the entire framework and starts the embedded server.
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args); // starts Tomcat on port 8080
}
}
Your First REST Endpoint
@RestController tells Spring that this class handles HTTP requests and that the return values should be written directly to the response body (as JSON, or plain text for strings). @RequestMapping sets the base path for all methods in the class.
package com.example.demo;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class HelloController {
// Handles GET /api/hello — no path variable, always returns the same greeting
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
// Handles GET /api/hello/{name} — Spring extracts the name from the URL
@GetMapping("/hello/{name}")
public String helloName(@PathVariable String name) {
return "Hello, " + name + "!";
}
}
Run with:
./mvnw spring-boot:run
# or build first, then run the JAR
./mvnw package && java -jar target/demo-0.0.1-SNAPSHOT.jar
Test:
curl http://localhost:8080/api/hello
# Hello, Spring Boot!
curl http://localhost:8080/api/hello/Alice
# Hello, Alice!
application.properties
All configuration — database URLs, logging levels, server port — lives in application.properties. Spring Boot reads this file automatically at startup. You can override any value at runtime with an environment variable or command-line argument without touching the file.
# Server
server.port=8080
# Database (if using JPA)
spring.datasource.url=jdbc:mysql://localhost:3306/demodb
spring.datasource.username=root
spring.datasource.password=${DB_PASSWORD} # reads from DB_PASSWORD env variable
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# JPA
spring.jpa.hibernate.ddl-auto=update # auto-create/update tables in dev
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
# Logging
logging.level.com.example=DEBUG
logging.level.org.springframework.web=INFO
Use application.yml for a cleaner format (same effect):
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/demodb
username: root
password: ${DB_PASSWORD}
jpa:
hibernate:
ddl-auto: update
show-sql: false
logging:
level:
com.example: DEBUG
Spring Boot Starters
Starters are curated dependency bundles. Adding one starter pulls in everything you need for that feature — the right libraries, at compatible versions, with auto-configuration wired up. This is one of Spring Boot’s biggest quality-of-life improvements over plain Spring.
| Starter | What it includes |
|---|---|
spring-boot-starter-web | Spring MVC, embedded Tomcat, Jackson JSON |
spring-boot-starter-data-jpa | JPA, Hibernate, Spring Data |
spring-boot-starter-security | Spring Security |
spring-boot-starter-validation | Bean Validation (Hibernate Validator) |
spring-boot-starter-test | JUnit 5, Mockito, Spring Test |
spring-boot-starter-actuator | Health checks, metrics endpoints |
spring-boot-starter-mail | JavaMail for sending email |
Running and Building
# Run in dev mode (hot restart on code changes when devtools is on the classpath)
./mvnw spring-boot:run
# Build a self-contained executable JAR
./mvnw clean package
# Run the JAR directly — no Maven needed on the target machine
java -jar target/demo-0.0.1-SNAPSHOT.jar
# Activate a specific profile (e.g. prod settings)
java -jar target/demo.jar --spring.profiles.active=prod
# Override any property at runtime without rebuilding
java -jar target/demo.jar --server.port=9090
Spring Boot DevTools
DevTools watches your classpath for changes and restarts the application automatically. This cuts the inner dev loop from “stop, rebuild, restart” to “save file, wait 1 second.” Add it as an optional runtime dependency so it never ends up in production builds.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional> <!-- excluded from final JAR automatically -->
</dependency>
Profiles
Profiles let you maintain different configuration for different environments — a common pattern is dev with a local database and verbose logging, and prod with a managed database and minimal logging. The shared defaults live in application.properties; profile-specific files add or override only what differs.
src/main/resources/
├── application.properties ← shared defaults (applies in all profiles)
├── application-dev.properties ← development overrides
└── application-prod.properties ← production overrides
application-prod.properties:
spring.jpa.hibernate.ddl-auto=validate # never auto-migrate schema in production
logging.level.com.example=WARN # less noise in production logs
Activate:
java -jar app.jar --spring.profiles.active=prod
# or set the environment variable
export SPRING_PROFILES_ACTIVE=prod
Actuator — Health and Metrics
Actuator exposes built-in HTTP endpoints for monitoring your application’s health, configuration, and JVM metrics. It’s essential for production deployments — load balancers and orchestrators like Kubernetes use the /health endpoint to decide whether to send traffic to an instance.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
# Expose only the endpoints you need — never expose all in production
management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=when-authorized
curl http://localhost:8080/actuator/health
# {"status":"UP","components":{"db":{"status":"UP"},"diskSpace":{"status":"UP"}}}
curl http://localhost:8080/actuator/metrics/jvm.memory.used
This is the foundation everything else builds on. Next: Dependency Injection — how Spring manages your objects.