Generate a project with Spring Initializr, understand starters and autoconfiguration, run the embedded server, and write your first REST endpoint.
Why: Spring Initializr wires up the build file, the main class, and a runnable project so you start from working code, not an empty folder. When the website: visit start.spring.io, pick Maven + Java, add the "Spring Web" dependency, and download. Note: the curl below does the same thing from the terminal.
Generate, unzip, and enter the project:
curl https://start.spring.io/starter.zip \
-d type=maven-project -d language=java -d javaVersion=17 \
-d dependencies=web \
-d groupId=com.example -d artifactId=bookstore \
-d packageName=com.example.bookstore \
-o bookstore.zipunzip bookstore.zip -d bookstorecd bookstoreWhy: @SpringBootApplication is three annotations in one — it enables autoconfiguration, component scanning of this package, and marks the config class. Where: src/main/java/com/example/bookstore. SpringApplication.run() boots the whole container and starts the server.
package com.example.bookstore;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BookstoreApplication {
public static void main(String[] args) {
SpringApplication.run(BookstoreApplication.class, args);
}
}Where: your code lives under src/main/java, configuration under src/main/resources (application.properties), and tests under src/test/java. The Maven wrapper (mvnw) lets anyone build without installing Maven first.
bookstore/
├── mvnw, mvnw.cmd # Maven wrapper — no global install needed
├── pom.xml # dependencies & build config
└── src/
├── main/
│ ├── java/com/example/bookstore/
│ │ └── BookstoreApplication.java
│ └── resources/
│ └── application.properties
└── test/
└── java/com/example/bookstore/Why: a "starter" is a curated bundle of dependencies for one job — spring-boot-starter-web pulls in Spring MVC, Jackson (JSON), and an embedded Tomcat in a single line, with versions already aligned. Note: the parent POM manages every version so you rarely write one yourself.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>Why: autoconfiguration looks at what is on the classpath and configures sensible defaults — because starter-web is present, Spring Boot starts an embedded Tomcat on port 8080 with no XML. When you override: set properties, or exclude an autoconfiguration you do not want.
# src/main/resources/application.properties
server.port=8080
spring.application.name=bookstore// exclude an autoconfiguration you don't want
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class BookstoreApplication { }Why: a @RestController whose methods return objects becomes a JSON (or text) HTTP API. Note: spring-boot:run compiles and launches the app; the embedded server auto-restarts if you add spring-boot-devtools. Hit the URL with curl or a browser.
package com.example.bookstore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello from Spring Boot!";
}
}./mvnw spring-boot:run
# in another terminal:
curl http://localhost:8080/hello