Setup: JDK & Project Install the JDK Spring Boot 4 needs Java 17 or newer and supports Java 25. Take the newest LTS:
# macOS
brew install --cask temurin@25
# Linux
sudo apt install openjdk-25-jdk
# Windows
winget install EclipseAdoptium.Temurin.25.JDK
# any platform, several versions side by side
sdk install java 25-tem # sdkman.io java --version # openjdk 25 … No Maven or Gradle install needed — generated projects ship a wrapper.
Generate a project Use start.spring.io in the browser, or the API:
curl https://start.spring.io/starter.zip \
-d bootVersion = 4.0.0 -d javaVersion = 25 -d type = maven-project \
-d groupId = com.example -d artifactId = demo -d name = demo \
-d dependencies = web,data-jpa,h2,actuator,validation \
-o demo.zip && unzip demo.zip -d demo What you get:
demo/
pom.xml
mvnw mvnw.cmd Maven wrapper — no local Maven needed
src/main/java/com/example/demo/DemoApplication.java
src/main/resources/application.properties
src/test/java/com/example/demo/DemoApplicationTests.java The build file <parent>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-starter-parent</artifactId>
<version> 4.0.0</version>
</parent>
<properties>
<java.version> 25</java.version>
</properties>
<dependencies>
<dependency>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-starter-web</artifactId>
</dependency>
</dependencies> A starter is a dependency that pulls in a whole topic. The parent pins every version,
so your dependencies carry no <version> tag.
New in Spring Boot 4The code base is fully modularized: auto-configuration now lives in many small,
focused jars instead of one big spring-boot-autoconfigure. Starters keep working
unchanged — you just ship fewer classes you never use.
Run it cd demo
./mvnw spring-boot:run # http://localhost:8080
./mvnw test
./mvnw package # target/demo-0.0.1-SNAPSHOT.jar
java -jar target/demo-0.0.1-SNAPSHOT.jar Editor IntelliJ IDEA Community — open pom.xml, set the project SDK to 25VS Code — install Extension Pack for Java and Spring Boot Extension Pack
Port already in use?Another process holds 8080. Start with ./mvnw spring-boot:run -Dspring-boot.run.arguments=--server.port=8081.
★ Exercises Install a JDK and print java --version. Generate a project with the web and actuator dependencies. Start it and open http://localhost:8080/actuator/health. Run ./mvnw dependency:tree and find out what spring-boot-starter-web pulled in. Your First Application The entry point 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 );
}
} @SpringBootApplication is three annotations in one:
Annotation Job @SpringBootConfigurationthis class may declare beans @ComponentScanfind components in this package and below @EnableAutoConfigurationconfigure what the classpath suggests
WarningComponent scanning starts at the application class’s package. Keep it at the root —
classes in a sibling package are invisible.
A first endpoint @RestController
public class HelloController {
@GetMapping ( "/hello" )
public String hello ( @RequestParam ( defaultValue = "world" ) String name ) {
return "Hello, " + name + "!" ;
}
} curl "localhost:8080/hello?name=Ann" # Hello, Ann! No web.xml, no servlet registration: spring-boot-starter-web puts Tomcat on the
classpath, and auto-configuration starts it.
Returning JSON Return an object and Jackson serializes it.
public record Greeting ( String message , Instant at ) {}
@GetMapping ( "/greeting" )
public Greeting greeting () {
return new Greeting ( "Hello" , Instant . now ());
} { "message" : "Hello" , "at" : "2026-03-01T10:15:30.00Z" } Configuration src/main/resources/application.properties:
server.port = 8081
spring.application.name = demo
logging.level.com.example = DEBUG Or YAML, in application.yaml:
server :
port : 8081
logging :
level :
com.example : DEBUG What happens on startup SpringApplication.run creates an application context component scan collects your @Component/@Service/@RestController classes auto-configuration adds what the classpath implies (web server, DataSource, …) beans are created and wired the embedded Tomcat starts and binds a port ./mvnw spring-boot:run -Ddebug # prints the auto-configuration report ★ Exercises Add a /time endpoint returning the current time as JSON. Change the port to 9000 in application.properties. Move HelloController into com.example.other — what happens, and why? Run with -Ddebug and find three auto-configurations that matched.