Spring Boot Cheatsheet
Configuration
Use this Spring Boot reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
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)
- Command-line arguments (
--server.port=9090) SPRING_APPLICATION_JSONenv var- Servlet / init parameters
- OS environment variables
application-{profile}.properties(profile-specific, outside jar)application.properties(outside jar)application-{profile}.properties(inside jar)application.properties(inside jar)@PropertySourceannotations- 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
@Valuefor more than 2-3 related properties in the same class; prefer@ConfigurationPropertiesinstead.
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
@ConfigurationPropertiesnot found — add@ConfigurationPropertiesScanor@EnableConfigurationProperties; also addspring-boot-configuration-processorto annotation processors for IDE autocomplete.- Env var name mapping —
APP_MAIL_HOSTmaps toapp.mail.host(relaxed binding with underscores and uppercase). @Valuewith@Configuration— if a@Configurationclass uses@ValueAND declares@Beanmethods, property resolution happens before bean creation; use constructor injection or@ConfigurationPropertiesto avoid ordering issues.- Profile-specific YAML in one file — use
---document separators withspring.config.activate.on-profile(Spring Boot 2.4+). logging.levelat runtime — change via Actuator/actuator/loggers/{name}without restart.