Spring Boot cheat sheet

A scannable Spring Boot reference: 19 short snippets across 13 topics, each linking back to the lesson it came from.

At a glance

TopicWhat it covers
Project setup and your first controllerSpring Initializr produces the skeleton with a build file, a wrapper and a test already wired up. Choose thelesson
REST controllers and dependency injectionThe HTTP annotations you will use daily, DTOs at the boundary, and constructor injection done properlylesson
Configuration, JPA data access and profilesLayered properties, environment-specific profiles, and a repository layer with the traps called outlesson
Request validation and global error handlingAnnotation-based validation runs on the object that arrives from the network, not on your entities. Put the rules on alesson
JPA relationships, queries and paginationA Page serialises to content, totalElements, totalPages and number. The count query is a real second query - for largelesson
Schema migrations with Flyway and seed dataSet spring.jpa.hibernate.ddl-auto to validate and let Flyway own the schema. Hibernate then fails fast when the entitylesson
Transactions, locking and concurrencyThe retry must re-read the row inside the transaction, otherwise it retries with the same stale version and failslesson
Securing the API with Spring SecurityRole checks alone are not authorization. Check ownership too: hasRole('USER') says the caller is logged in, not thatlesson
Testing Spring Boot applicationsFull-context versus slice tests, MockMvc, @DataJpaTest, Testcontainers against a real database, and when to mocklesson
Observability with Actuator, logging and metricsTag meters with low-cardinality dimensions such as status code or endpoint template. Never tag with a user id, an orderlesson
Caching, async processing and schedulingEvery instance of your service runs its own scheduler. Without a distributed lock, a nightly job runs once per replicalesson
Packaging and deploying a Spring Boot serviceLayered jars, Dockerfiles and buildpacks, externalised configuration, container-aware memory settings and safe rollinglesson
Next steps: WebFlux, messaging and native imagesChoosing reactive or servlet, using WebClient correctly, integrating Kafka, building a GraalVM native image, and wherelesson

Quick snippets

Project setup and your first controller

Generating the project

# download from start.spring.io, or use your IDE wizard
unzip demo.zip -d demo
cd demo

./mvnw spring-boot:run       # starts the app on http://localhost:8080
./mvnw test                  # runs the generated context test
./mvnw package               # builds target/demo-0.0.1-SNAPSHOT.jar
java -jar target/demo-0.0.1-SNAPSHOT.jar

Full lesson: Project setup and your first controller →

REST controllers and dependency injection

REST controllers

record CreateUser(@NotBlank String name, @Email String email) {}

record UserDto(long id, String name, String email) {
    static UserDto from(User u) {
        return new UserDto(u.getId(), u.getName(), u.getEmail());
    }
}

Full lesson: REST controllers and dependency injection →

Configuration, JPA data access and profiles

Configuration and profiles

# src/main/resources/application.properties
spring.application.name=demo
server.port=8080
spring.jpa.open-in-view=false
app.greeting=Hello

Configuration and profiles

# src/main/resources/application.yml
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/demo
    username: demo
    password: ${DB_PASSWORD}     # read from the environment, never committed
  jpa:
    hibernate:
      ddl-auto: validate

Configuration and profiles

@Component
@ConfigurationProperties(prefix = "app")
class AppProperties {
    private String greeting = "";
    // getters and setters
}

@Configuration
@Profile("prod")
class ProdCacheConfig {
    // only active when the prod profile is on
}

Full lesson: Configuration, JPA data access and profiles →

Request validation and global error handling

Validating the boundary

public record CreateBookRequest(
    @NotBlank String title,
    @NotBlank @Size(max = 64) String author,
    @ISBN String isbn,
    @PositiveOrZero Integer copies,
    @Email String contactEmail,
    @Valid AddressRequest address) {}

@PostMapping("/books")
public ResponseEntity<BookResponse> create(@Valid @RequestBody CreateBookRequest req) {
    return ResponseEntity.status(HttpStatus.CREATED).body(service.create(req));
}

Full lesson: Request validation and global error handling →

JPA relationships, queries and pagination

Pagination and sorting from the controller

@GetMapping("/books")
Page<BookSummary> list(@PageableDefault(size = 20, sort = "title") Pageable pageable) {
  return repo.findSummaries(pageable);
}

// GET /books?page=0&size=20&sort=publishedAt,desc

Full lesson: JPA relationships, queries and pagination →

Schema migrations with Flyway and seed data

Reference data and test seeding

-- R__seed_countries.sql  (repeatable: re-runs when the file changes)
insert into country (code, name)
values ('DE', 'Germany'), ('FR', 'France'), ('GB', 'United Kingdom')
on conflict (code) do update set name = excluded.name;

Full lesson: Schema migrations with Flyway and seed data →

Transactions, locking and concurrency

Optimistic and pessimistic locking

@Retryable(retryFor = OptimisticLockingFailureException.class,
           maxAttempts = 3, backoff = @Backoff(delay = 50, multiplier = 2))
@Transactional
public void adjust(Long id, BigDecimal delta) { /* re-read inside the retry */ }

Full lesson: Transactions, locking and concurrency →

Securing the API with Spring Security

Method security and ownership checks

@PreAuthorize("hasRole('ADMIN') or #ownerId == authentication.name")
public Order getOrder(String ownerId, Long orderId) { ... }

@PostAuthorize("returnObject.owner == authentication.name")
public Order load(Long id) { ... }

@PreAuthorize("@perm.canEdit(authentication, #id)")
public void update(Long id, UpdateDto dto) { ... }

Full lesson: Securing the API with Spring Security →

Testing Spring Boot applications

Integration tests against a real database

// transaction boundary check in a @SpringBootTest
@Test
void rollbackOnFailure() {
  assertThatThrownBy(() -> service.transferWithoutFunds(1L, 2L, HUNDRED))
      .isInstanceOf(IllegalStateException.class);
  assertThat(accounts.balanceOf(1L)).isEqualByComparingTo(TEN);
}

What to assert and what to mock

@TestConfiguration
class TestClock {
  @Bean Clock clock() { return Clock.fixed(Instant.parse("2026-01-01T00:00:00Z"), ZoneOffset.UTC); }
}

Full lesson: Testing Spring Boot applications →

Observability with Actuator, logging and metrics

Logging that survives production

logging:
  level:
    root: INFO
    com.example.orders: DEBUG
    org.hibernate.SQL: WARN
  pattern:
    console: '{"ts":"%d{yyyy-MM-dd''T''HH:mm:ss.SSSXXX}","level":"%p","logger":"%c{1.}","msg":"%m"}%n'

Full lesson: Observability with Actuator, logging and metrics →

Caching, async processing and scheduling

Async work with a real executor

@Async("mailExecutor")
public CompletableFuture<Void> sendReceipt(Order order) {
  mailer.send(order);
  return CompletableFuture.completedFuture(null);
}

Scheduling in a multi-instance world

@Scheduled(cron = "0 */15 * * * *", zone = "UTC")
@SchedulerLock(name = "refreshCatalog")   // ShedLock: one node at a time
public void refreshCatalog() { catalog.reload(); }

@Scheduled(fixedDelayString = "${jobs.reconcile.delay:PT5M}")
public void reconcile() { ... }

Full lesson: Caching, async processing and scheduling →

Packaging and deploying a Spring Boot service

Building the artefact

# layered jar: dependencies change rarely, code changes often
./gradlew bootJar
java -Djarmode=tools -jar build/libs/orders-0.0.1.jar extract --destination build/extracted

# inspect the layers
unzip -l build/libs/orders-0.0.1.jar | head -20

# run with an external config file and an explicit profile
java -jar orders.jar --spring.profiles.active=prod \
  --spring.config.additional-location=file:/etc/orders/

A production Dockerfile

FROM eclipse-temurin:21-jre-alpine AS runtime

RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
COPY --chown=app:app build/libs/*.jar app.jar

USER app
EXPOSE 8080
ENV JAVA_TOOL_OPTIONS="-XX:MaxRAMPercentage=75.0 -XX:+ExitOnOutOfMemoryError"

ENTRYPOINT ["java","-jar","/app/app.jar"]

Startup, probes and rollout

# Kubernetes excerpt
livenessProbe:
  httpGet: { path: /internal/health/liveness, port: 8081 }
  initialDelaySeconds: 60
  failureThreshold: 3
readinessProbe:
  httpGet: { path: /internal/health/readiness, port: 8081 }
  periodSeconds: 5
lifecycle:
  preStop:
    exec: { command: ["sh","-c","sleep 5"] }   # let the LB deregister first

Full lesson: Packaging and deploying a Spring Boot service →

Next steps: WebFlux, messaging and native images

Native images

./gradlew nativeCompile          # via GraalVM
# or a container build
./gradlew bootBuildImage --imageName=orders-native -Pnative

# run it
./build/native/nativeCompile/orders
# typical result: ~100 MB RSS, 50-100 ms to first response

Full lesson: Next steps: WebFlux, messaging and native images →

FAQ

Is this Spring Boot cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 13 lessons of the Spring Boot course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full Spring Boot course — it carries the worked explanations, the edge cases and the exercises behind every line here.

Node.js PHP Java HTTP Go Rust

Last refreshed 2026-09-27.