Spring Boot Cheatsheet

Configuration

Use this Spring Boot reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

application.properties vs application.yml

Both formats are equivalent. Properties files are simpler; YAML is more readable for nested config.

# application.properties
server.port=8080
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=user
spring.datasource.password=secret
# application.yml
server:
  port: 8080
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: user
    password: secret

Spring Boot loads both; properties take precedence over YAML when both exist. Use one format per project.

Property Sources and Precedence (highest → lowest)

  1. Command-line arguments (--server.port=9090)
  2. SPRING_APPLICATION_JSON env var
  3. Servlet / init parameters
  4. OS environment variables
  5. application-{profile}.properties (profile-specific, outside jar)
  6. application.properties (outside jar)
  7. application-{profile}.properties (inside jar)
  8. application.properties (inside jar)
  9. @PropertySource annotations
  10. Default properties (SpringApplication.setDefaultProperties)

Profiles

# application-dev.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.jpa.hibernate.ddl-auto=create-drop
logging.level.com.example=DEBUG

# application-prod.properties
spring.datasource.url=${DATABASE_URL}
spring.jpa.hibernate.ddl-auto=validate
logging.level.root=WARN
# Activate at runtime
java -jar app.jar --spring.profiles.active=prod

# Or via env var
SPRING_PROFILES_ACTIVE=prod java -jar app.jar
// Activate in code
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(App.class);
        app.setAdditionalProfiles("dev");
        app.run(args);
    }
}

// Conditional beans on profile
@Service
@Profile("dev")
public class MockEmailService implements EmailService { ... }

@Service
@Profile("!dev")   // all profiles except dev
public class RealEmailService implements EmailService { ... }

@Service
@Profile({"prod", "staging"})
public class ProductionEmailService implements EmailService { ... }

@ConfigurationProperties — Typed Config

Preferred over @Value for groups of related properties.

# application.properties
app.mail.host=smtp.gmail.com
app.mail.port=587
app.mail.username=noreply@example.com
app.mail.password=secret
app.mail.from=Hack University <noreply@example.com>
app.mail.retry-count=3
@ConfigurationProperties(prefix = "app.mail")
@Validated   // triggers Bean Validation on the properties
public record MailProperties(
    @NotBlank String host,
    @Min(1) @Max(65535) int port,
    @NotBlank String username,
    @NotBlank String password,
    @NotBlank String from,
    @Min(0) int retryCount
) {}
// Register — pick ONE of:
@SpringBootApplication
@ConfigurationPropertiesScan  // scans for @ConfigurationProperties

// Or per-class:
@EnableConfigurationProperties(MailProperties.class)
// Inject like any bean
@Service
@RequiredArgsConstructor
public class MailService {
    private final MailProperties mail;
}

@Value — Single Property Injection

@Component
public class AppInfo {
    @Value("${app.name}")
    private String appName;

    @Value("${app.max-connections:10}")   // default value after ':'
    private int maxConnections;

    @Value("${app.allowed-origins}")      // injects List<String> from CSV
    private List<String> allowedOrigins;

    @Value("#{T(java.lang.Math).PI}")     // SpEL expression
    private double pi;

    @Value("${app.secret:#{null}}")       // null default
    private String secret;
}

Avoid @Value for more than 2-3 related properties in the same class; prefer @ConfigurationProperties instead.

Environment and PropertySources

@Component
public class EnvInspector {

    private final Environment env;

    public EnvInspector(Environment env) {
        this.env = env;
    }

    public String getProperty(String key) {
        return env.getProperty(key, "default");
    }

    public boolean isDevProfile() {
        return env.acceptsProfiles(Profiles.of("dev"));
    }
}

Custom @PropertySource

@Configuration
@PropertySource("classpath:custom.properties")
@PropertySource(value = "file:/etc/myapp/secrets.properties", ignoreResourceNotFound = true)
public class ExtraConfig {}

Externalized Secrets — Best Practices

# Reference env vars in properties
spring.datasource.password=${DB_PASSWORD}
jwt.secret=${JWT_SECRET}
stripe.api-key=${STRIPE_SECRET_KEY}
// Or use Spring Cloud Vault / AWS Parameter Store / Kubernetes Secrets
// spring-cloud-starter-vault-config
spring.cloud.vault.uri=http://vault:8200
spring.cloud.vault.authentication=TOKEN
spring.cloud.vault.token=${VAULT_TOKEN}

@Configuration Classes

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins("https://myapp.com")
                .allowedMethods("GET", "POST", "PUT", "DELETE");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoggingInterceptor())
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/health");
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new MappingJackson2HttpMessageConverter());
    }
}

Logging Configuration

# Root level
logging.level.root=INFO

# Package-level
logging.level.com.example=DEBUG
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

# File output
logging.file.name=logs/app.log
logging.file.max-size=10MB
logging.file.max-history=30

# Pattern
logging.pattern.console=%d{HH:mm:ss} %-5level %logger{36} - %msg%n
// In code (SLF4J — included via spring-boot-starter)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class OrderService {
    private static final Logger log = LoggerFactory.getLogger(OrderService.class);
    // Or with Lombok:
    // @Slf4j on the class
    
    public void process(Order order) {
        log.debug("Processing order {}", order.getId());
        log.info("Order {} processed", order.getId());
        log.warn("Order {} has unusual amount: {}", order.getId(), order.getTotal());
        log.error("Failed to process order {}", order.getId(), exception);
    }
}

Common Server Properties

server.port=8080
server.servlet.context-path=/api          # global URL prefix
server.error.include-message=always       # include message in error response
server.error.include-stacktrace=never     # never expose stack in prod
server.compression.enabled=true
server.compression.mime-types=application/json,application/xml,text/html
server.compression.min-response-size=1024

# SSL / TLS
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=${KEYSTORE_PASS}
server.ssl.key-store-type=PKCS12
server.port=443

Jackson / Serialization Properties

spring.jackson.serialization.write-dates-as-timestamps=false
spring.jackson.default-property-inclusion=non_null
spring.jackson.deserialization.fail-on-unknown-properties=false
spring.jackson.time-zone=UTC
spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ss'Z'

Common Pitfalls

  • @ConfigurationProperties not found — add @ConfigurationPropertiesScan or @EnableConfigurationProperties; also add spring-boot-configuration-processor to annotation processors for IDE autocomplete.
  • Env var name mappingAPP_MAIL_HOST maps to app.mail.host (relaxed binding with underscores and uppercase).
  • @Value with @Configuration — if a @Configuration class uses @Value AND declares @Bean methods, property resolution happens before bean creation; use constructor injection or @ConfigurationProperties to avoid ordering issues.
  • Profile-specific YAML in one file — use --- document separators with spring.config.activate.on-profile (Spring Boot 2.4+).
  • logging.level at runtime — change via Actuator /actuator/loggers/{name} without restart.