Refreshing static content with Spring MVC and Boot
Data Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.
Introduction
During development, changing a CSS, JavaScript, or HTML file in a Spring Boot application requires a server restart to see the update. This slows down front-end development. Spring Boot provides several ways to serve fresh static content without restarts: Spring DevTools enables automatic reload, resource versioning with content hashing ensures browsers fetch updated files, and cache-control headers prevent stale content in production. This article covers each approach for both development-time live reload and production-ready cache-busting.
Default Static Content Locations
Spring Boot serves static files from these classpath directories (in priority order):
classpath:/META-INF/resources/classpath:/resources/classpath:/static/classpath:/public/
Files can also be served from file: locations outside the classpath.
Development: Spring DevTools (Live Reload)
Spring DevTools automatically restarts the application when classpath files change, and includes a LiveReload server that refreshes the browser:
With restart.exclude=static/**, changing CSS/JS files triggers a LiveReload (browser refresh) without a full application restart. Install the LiveReload browser extension for automatic refresh.
IDE Configuration
For IntelliJ IDEA, enable automatic build on save:
- Settings > Build, Execution, Deployment > Compiler > "Build project automatically"
- Settings > Advanced Settings > "Allow auto-make to start even if developed application is currently running"
For Eclipse/STS, automatic build is enabled by default.
Development: Serve from File System
Serve static files directly from the file system so changes are visible immediately without any restart:
Files served from file: locations are read directly from disk on each request, so edits are visible immediately.
Production: Cache-Busting with Content Hashing
In production, static files should be cached aggressively but invalidated when content changes. Spring's VersionResourceResolver appends a content hash to filenames:
This transforms URLs like /static/css/style.css into /static/css/style-abc123def.css. When the file changes, the hash changes, and browsers fetch the new version.
Using in Thymeleaf Templates
Using ResourceUrlProvider in JSP
Production: Cache-Control Headers
With content-hashed URLs, setting a long cache duration is safe because changed files get new URLs.
Production: Fixed Version Strategy
If content hashing is not suitable, use a fixed version string (e.g., application version):
This transforms /css/style.css into /v2.1.0/css/style.css. Update the version on each deployment.
Profile-Based Configuration
Common Pitfalls
- Forgetting to disable caching in development: Without
setCachePeriod(0)orno-cacheheaders, the browser caches static files and you do not see changes even after restarting. Setspring.web.resources.cache.cachecontrol.no-cache=truefor development profiles. - Using DevTools in production: Spring DevTools is intended for development only. It is automatically disabled when running from a packaged JAR, but ensure it is declared with
<scope>runtime</scope>and<optional>true</optional>to prevent accidental inclusion. - Setting long cache durations without content hashing: If you set
max-age=365dbut do not use versioned URLs, browsers serve stale files until the cache expires. Always pair long cache durations with content hashing or a fixed version strategy. - Not using Thymeleaf's
@{}syntax for resource URLs: Hardcoding paths likehref="/css/style.css"bypasses Spring's resource versioning. Useth:href="@{/css/style.css}"so Spring resolves the versioned URL automatically. - Mixing
file:andclasspath:locations incorrectly: When both are configured,file:takes precedence for matching paths. In production, removefile:locations to ensure static files are served from the packaged JAR, not from a nonexistent file path.
Summary
- Use Spring DevTools with LiveReload for instant static content updates during development
- Serve from
file:locations to avoid restarts entirely for front-end changes - Use
VersionResourceResolverwith content hashing for production cache-busting - Set
Cache-Control: max-age=365dwith versioned URLs for optimal browser caching - Use Spring profiles to separate development (no-cache, DevTools) from production (long cache, versioning) configurations
Related reading
- Regex doesn't work in String.matches
- Regex Named Groups in Java
- Register SPI dynamically at runtime
- Remote debugging a Java application
- Removal of negative numbers from an array in Java
- Remove ✅, \U0001F525, ✈ , ♛ and other such emojis/images/signs from Java strings
- Remove last character of a StringBuilder?
- Remove multiple keys from Map in efficient way?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseData Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.