Starter for building web, including RESTful, applications using Spring MVC with embedded Tomcat server.
—
Serve static content like CSS, JavaScript, images, and other assets with built-in caching and versioning support.
Configure where static resources are served from.
# Default static resource locations (in order of precedence)
spring.web.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
# Enable/disable default resource handling
spring.web.resources.add-mappings=true
# Static resource URL pattern
spring.mvc.static-path-pattern=/**
# WebJars URL pattern
spring.mvc.webjars-path-pattern=/webjars/**Configure HTTP caching headers for static resources.
# Basic cache period (deprecated, use cache-control)
spring.web.resources.cache.period=3600
# Use last-modified headers
spring.web.resources.cache.use-last-modified=true
# Cache-Control header settings
spring.web.resources.cache.cachecontrol.max-age=3600
spring.web.resources.cache.cachecontrol.no-cache=false
spring.web.resources.cache.cachecontrol.no-store=false
spring.web.resources.cache.cachecontrol.must-revalidate=false
spring.web.resources.cache.cachecontrol.no-transform=false
spring.web.resources.cache.cachecontrol.cache-public=true
spring.web.resources.cache.cachecontrol.cache-private=false
spring.web.resources.cache.cachecontrol.proxy-revalidate=false
spring.web.resources.cache.cachecontrol.stale-while-revalidate=
spring.web.resources.cache.cachecontrol.stale-if-error=
spring.web.resources.cache.cachecontrol.s-max-age=Configure resource transformation and versioning strategies.
# Enable resource processing chain
spring.web.resources.chain.enabled=true
spring.web.resources.chain.cache=true
spring.web.resources.chain.compressed=false
# Content-based versioning (hash-based)
spring.web.resources.chain.strategy.content.enabled=true
spring.web.resources.chain.strategy.content.paths=/**
# Fixed versioning
spring.web.resources.chain.strategy.fixed.enabled=false
spring.web.resources.chain.strategy.fixed.paths=/**
spring.web.resources.chain.strategy.fixed.version=v1.0.0Configure static resources programmatically.
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* Add custom resource handlers
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// Custom static content location
registry.addResourceHandler("/assets/**")
.addResourceLocations("classpath:/assets/", "file:./uploads/")
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new PathResourceResolver());
// Uploaded files
registry.addResourceHandler("/uploads/**")
.addResourceLocations("file:./uploads/")
.setCachePeriod(0); // No caching for user uploads
// Custom favicon
registry.addResourceHandler("/favicon.ico")
.addResourceLocations("classpath:/static/images/")
.setCachePeriod(86400); // 1 day cache
}
}
/**
* Resource handler registration
*/
public class ResourceHandlerRegistration {
public ResourceHandlerRegistration addResourceLocations(String... locations);
public ResourceHandlerRegistration setCachePeriod(Integer cachePeriod);
public ResourceHandlerRegistration setCacheControl(CacheControl cacheControl);
public ResourceChainRegistration resourceChain(boolean cacheResources);
public ResourceHandlerRegistration setOptimizeLocations(boolean optimizeLocations);
}
/**
* Resource chain configuration for transformations and resolvers
*/
public class ResourceChainRegistration {
public ResourceChainRegistration addResolver(ResourceResolver resolver);
public ResourceChainRegistration addTransformer(ResourceTransformer transformer);
}Serve client-side libraries packaged as WebJars.
/**
* WebJar configuration (automatically available when WebJars are on classpath)
*/
// Add WebJar dependency in Maven/Gradle:
// implementation 'org.webjars:bootstrap:5.1.3'
// implementation 'org.webjars:jquery:3.6.0'
// Access WebJar resources at:
// /webjars/bootstrap/5.1.3/css/bootstrap.min.css
// /webjars/jquery/3.6.0/jquery.min.js
/**
* Custom WebJar configuration
*/
@Configuration
public class WebJarConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(86400)
.resourceChain(true)
.addResolver(new WebJarsResourceResolver());
}
}Customize resource resolution and transformation.
/**
* Built-in resource resolvers
*/
public class PathResourceResolver implements ResourceResolver {
// Resolves resources by matching request path to resource location
}
public class WebJarsResourceResolver implements ResourceResolver {
// Resolves WebJar resources with version-agnostic URLs
}
public class VersionResourceResolver implements ResourceResolver {
// Resolves versioned resources (content-based or fixed version)
}
/**
* Built-in resource transformers
*/
public class CssLinkResourceTransformer implements ResourceTransformer {
// Updates CSS @import and url() references
}
public class AppCacheManifestTransformer implements ResourceTransformer {
// Updates HTML5 AppCache manifest files
}
/**
* Custom resource resolver example
*/
@Component
public class CustomResourceResolver implements ResourceResolver {
@Override
public Resource resolveResource(HttpServletRequest request, String requestPath,
List<? extends Resource> locations, ResourceResolverChain chain) {
// Custom resource resolution logic
return chain.resolveResource(request, requestPath, locations);
}
@Override
public String resolveUrlPath(String resourcePath, List<? extends Resource> locations,
ResourceResolverChain chain) {
// Custom URL path resolution
return chain.resolveUrlPath(resourcePath, locations);
}
}Handle different resource formats based on request.
@Configuration
public class ResourceConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/api/docs/**")
.addResourceLocations("classpath:/api-docs/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath, Resource location) {
Resource resource = location.createRelative(resourcePath);
// Custom logic for format negotiation
if (resourcePath.endsWith(".json")) {
return resource.exists() ? resource : null;
}
return super.getResource(resourcePath, location);
}
});
}
}// Resource interface for accessing static resources
public interface Resource {
boolean exists();
String getFilename();
String getDescription();
InputStream getInputStream() throws IOException;
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
}
// HTTP cache control configuration
public class CacheControl {
public static CacheControl maxAge(long maxAge, TimeUnit unit);
public static CacheControl noCache();
public static CacheControl noStore();
public CacheControl mustRevalidate();
public CacheControl cachePrivate();
public CacheControl cachePublic();
public CacheControl proxyRevalidate();
public CacheControl sMaxAge(long sMaxAge, TimeUnit unit);
}
// Resource handler registry for configuration
public class ResourceHandlerRegistry {
public ResourceHandlerRegistration addResourceHandler(String... pathPatterns);
public void setOrder(int order);
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-web