0
# Resource Handling
1
2
Spring MVC provides comprehensive static resource serving capabilities with support for resource transformation, compression, versioning, and caching. It handles CSS, JavaScript, images, and other static assets with customizable resolution strategies.
3
4
## Capabilities
5
6
### ResourceHttpRequestHandler
7
8
HttpRequestHandler that serves static resources from configurable locations with customizable resource resolution and transformation.
9
10
```java { .api }
11
/**
12
* HttpRequestHandler that serves static resources optimized for superior browser performance.
13
*/
14
public class ResourceHttpRequestHandler implements HttpRequestHandler, EmbeddedValueResolverAware, InitializingBean {
15
16
/** Set the locations to serve resources from */
17
public void setLocations(List<Resource> locations);
18
19
/** Get configured resource locations */
20
public List<Resource> getLocations();
21
22
/** Set resource resolvers for custom resolution logic */
23
public void setResourceResolvers(List<ResourceResolver> resourceResolvers);
24
25
/** Get configured resource resolvers */
26
public List<ResourceResolver> getResourceResolvers();
27
28
/** Set resource transformers for content transformation */
29
public void setResourceTransformers(List<ResourceTransformer> resourceTransformers);
30
31
/** Get configured resource transformers */
32
public List<ResourceTransformer> getResourceTransformers();
33
34
/** Set cache period in seconds */
35
public void setCacheSeconds(int cacheSeconds);
36
37
/** Set cache control directives */
38
public void setCacheControl(CacheControl cacheControl);
39
40
/** Set whether to use last-modified header */
41
public void setUseLastModified(boolean useLastModified);
42
43
/** Set supported media types */
44
public void setSupportedMediaTypes(List<MediaType> supportedMediaTypes);
45
46
/** Set whether to optimize locations */
47
public void setOptimizeLocations(boolean optimizeLocations);
48
}
49
```
50
51
### DefaultServletHttpRequestHandler
52
53
HttpRequestHandler that forwards requests to the default Servlet for serving static resources.
54
55
```java { .api }
56
/**
57
* HttpRequestHandler that forwards to the default Servlet.
58
*/
59
public class DefaultServletHttpRequestHandler implements HttpRequestHandler, ServletContextAware {
60
61
/** Set the name of the default servlet */
62
public void setDefaultServletName(String defaultServletName);
63
64
/** Set the servlet context */
65
public void setServletContext(ServletContext servletContext);
66
}
67
```
68
69
**Usage Examples:**
70
71
```java
72
@Configuration
73
@EnableWebMvc
74
public class ResourceConfig implements WebMvcConfigurer {
75
76
@Override
77
public void addResourceHandlers(ResourceHandlerRegistry registry) {
78
// Serve static assets with caching
79
registry.addResourceHandler("/static/**")
80
.addResourceLocations("classpath:/static/")
81
.setCachePeriod(3600)
82
.resourceChain(true)
83
.addResolver(new PathResourceResolver());
84
85
// Serve webjars with versioning
86
registry.addResourceHandler("/webjars/**")
87
.addResourceLocations("classpath:/META-INF/resources/webjars/")
88
.setCachePeriod(31536000)
89
.resourceChain(true)
90
.addResolver(new WebJarsResourceResolver())
91
.addTransformer(new AppCacheManifestTransformer());
92
93
// Serve uploaded files
94
registry.addResourceHandler("/uploads/**")
95
.addResourceLocations("file:/var/app/uploads/")
96
.setCacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePrivate());
97
}
98
99
@Override
100
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
101
// Enable default servlet for static resources not handled by Spring MVC
102
configurer.enable();
103
}
104
}
105
106
@Bean
107
public ResourceHttpRequestHandler resourceHandler() {
108
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
109
110
// Set locations
111
List<Resource> locations = Arrays.asList(
112
new ClassPathResource("/static/"),
113
new FileSystemResource("/var/www/assets/")
114
);
115
handler.setLocations(locations);
116
117
// Configure caching
118
handler.setCacheControl(CacheControl.maxAge(1, TimeUnit.DAYS).cachePublic());
119
120
// Add resolvers
121
List<ResourceResolver> resolvers = Arrays.asList(
122
new CachingResourceResolver(new ConcurrentMapCache("resources")),
123
new GzipResourceResolver(),
124
new PathResourceResolver()
125
);
126
handler.setResourceResolvers(resolvers);
127
128
// Add transformers
129
List<ResourceTransformer> transformers = Arrays.asList(
130
new CachingResourceTransformer(new ConcurrentMapCache("resources")),
131
new CssLinkResourceTransformer()
132
);
133
handler.setResourceTransformers(transformers);
134
135
return handler;
136
}
137
```
138
139
## Resource Resolution Strategy
140
141
### ResourceResolver
142
143
Strategy interface for resolving requests to server-side resources.
144
145
```java { .api }
146
/**
147
* A strategy for resolving a request to a server-side resource.
148
*/
149
public interface ResourceResolver {
150
151
/**
152
* Resolve the supplied request and request path to a Resource.
153
* @param request the current request
154
* @param requestPath the portion of the request path to use
155
* @param locations the locations to search in
156
* @param chain the chain of remaining resolvers to delegate to
157
* @return the resolved resource, or null if unresolved
158
*/
159
Resource resolveResource(HttpServletRequest request, String requestPath,
160
List<? extends Resource> locations, ResourceResolverChain chain);
161
162
/**
163
* Resolve the externally facing public URL path for clients to request.
164
* @param resourcePath the internal resource path
165
* @param locations the locations to search in
166
* @param chain the chain of remaining resolvers to delegate to
167
* @return the resolved public URL path, or null if unresolved
168
*/
169
String resolveUrlPath(String resourcePath, List<? extends Resource> locations,
170
ResourceResolverChain chain);
171
}
172
```
173
174
### Common ResourceResolver Implementations
175
176
#### PathResourceResolver
177
178
Simple resolver that attempts to find a physical resource under the given locations.
179
180
```java { .api }
181
/**
182
* A simple ResourceResolver that tries to find a resource under the given locations.
183
*/
184
public class PathResourceResolver implements ResourceResolver {
185
186
/** Set allowed resource locations */
187
public void setAllowedLocations(Resource... allowedLocations);
188
189
/** Set URL path helper */
190
public void setUrlPathHelper(UrlPathHelper urlPathHelper);
191
192
/** Set location validator */
193
public void setLocationValidator(Resource.ResourceVisitor locationValidator);
194
}
195
```
196
197
#### CachingResourceResolver
198
199
Resolver that caches resolved resources.
200
201
```java { .api }
202
/**
203
* A ResourceResolver that resolves resources from a Cache.
204
*/
205
public class CachingResourceResolver implements ResourceResolver {
206
207
/** Create with cache instance */
208
public CachingResourceResolver(Cache cache);
209
210
/** Create with cache name */
211
public CachingResourceResolver(String cacheName);
212
213
/** Get the cache instance */
214
public Cache getCache();
215
}
216
```
217
218
#### VersionResourceResolver
219
220
Resolver that adds version information to resource URLs.
221
222
```java { .api }
223
/**
224
* A ResourceResolver that resolves request paths containing a version string.
225
*/
226
public class VersionResourceResolver implements ResourceResolver {
227
228
/** Add version strategy for path patterns */
229
public VersionResourceResolver addVersionStrategy(VersionStrategy strategy, String... pathPatterns);
230
231
/** Add fixed version strategy */
232
public VersionResourceResolver addFixedVersionStrategy(String version, String... pathPatterns);
233
234
/** Add content-based version strategy */
235
public VersionResourceResolver addContentVersionStrategy(String... pathPatterns);
236
}
237
```
238
239
## Resource Transformation
240
241
### ResourceTransformer
242
243
Strategy interface for transforming the content of a resource.
244
245
```java { .api }
246
/**
247
* An abstraction for transforming the content of a resource.
248
*/
249
public interface ResourceTransformer {
250
251
/**
252
* Transform the given resource.
253
* @param request the current request
254
* @param resource the resource to transform
255
* @param transformerChain the chain of remaining transformers to delegate to
256
* @return the transformed resource
257
*/
258
Resource transform(HttpServletRequest request, Resource resource,
259
ResourceTransformerChain transformerChain) throws IOException;
260
}
261
```
262
263
### Common ResourceTransformer Implementations
264
265
#### CssLinkResourceTransformer
266
267
Transformer that modifies links in CSS files to match the public URL paths.
268
269
```java { .api }
270
/**
271
* A ResourceTransformer implementation that modifies links in a CSS file.
272
*/
273
public class CssLinkResourceTransformer implements ResourceTransformer {
274
275
/** Set the list of supported media types */
276
public void setMediaTypes(List<MediaType> mediaTypes);
277
278
/** Get the configured media types */
279
public List<MediaType> getMediaTypes();
280
}
281
```
282
283
#### AppCacheManifestTransformer
284
285
Transformer for HTML5 AppCache manifest files.
286
287
```java { .api }
288
/**
289
* A ResourceTransformer implementation that helps handling resources within HTML5 AppCache manifests.
290
*/
291
public class AppCacheManifestTransformer implements ResourceTransformer {
292
// Implementation for AppCache manifest transformation
293
}
294
```
295
296
**Advanced Resource Configuration Example:**
297
298
```java
299
@Configuration
300
public class AdvancedResourceConfig {
301
302
@Bean
303
public ResourceUrlProvider resourceUrlProvider() {
304
return new ResourceUrlProvider();
305
}
306
307
@Bean
308
public ResourceChainRegistration resourceChain() {
309
return new ResourceChainRegistration(true)
310
.addResolver(new CachingResourceResolver(new ConcurrentMapCache("resources", 1000, false)))
311
.addResolver(new VersionResourceResolver()
312
.addFixedVersionStrategy("v1.0.0", "/**/*.js")
313
.addContentVersionStrategy("/**/*.css"))
314
.addResolver(new GzipResourceResolver())
315
.addResolver(new PathResourceResolver())
316
.addTransformer(new CachingResourceTransformer(new ConcurrentMapCache("resources", 1000, false)))
317
.addTransformer(new CssLinkResourceTransformer());
318
}
319
320
@Bean
321
public SimpleUrlHandlerMapping resourceHandlerMapping() {
322
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
323
mapping.setOrder(Integer.MAX_VALUE - 1);
324
325
Map<String, HttpRequestHandler> urlMap = new HashMap<>();
326
urlMap.put("/resources/**", resourceHandler());
327
urlMap.put("/static/**", staticResourceHandler());
328
mapping.setUrlMap(urlMap);
329
330
return mapping;
331
}
332
333
private ResourceHttpRequestHandler resourceHandler() {
334
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
335
handler.setLocations(Arrays.asList(
336
new ClassPathResource("/static/"),
337
new ServletContextResource(servletContext, "/resources/")
338
));
339
340
// Enable resource chain
341
handler.setResourceResolvers(Arrays.asList(
342
new CachingResourceResolver(new ConcurrentMapCache("resources")),
343
new VersionResourceResolver()
344
.addContentVersionStrategy("/**/*.css")
345
.addFixedVersionStrategy("v1.0", "/**/*.js"),
346
new PathResourceResolver()
347
));
348
349
handler.setResourceTransformers(Arrays.asList(
350
new CachingResourceTransformer(new ConcurrentMapCache("resources")),
351
new CssLinkResourceTransformer()
352
));
353
354
handler.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS).cachePublic());
355
return handler;
356
}
357
}
358
```
359
360
## Resource URL Generation
361
362
### ResourceUrlProvider
363
364
Utility for generating URLs to static resources with version information.
365
366
```java { .api }
367
/**
368
* A central component for obtaining the public URL path that clients should use to access a static resource.
369
*/
370
public class ResourceUrlProvider implements ApplicationContextAware {
371
372
/** Get the public URL path for the given resource path */
373
public String getForLookupPath(String lookupPath);
374
375
/** Get the public URL path for a resource served by the given handler mapping */
376
public String getForRequestUrl(HttpServletRequest request, String requestUrl);
377
378
/** Set resource handler mappings */
379
public void setHandlerMap(Map<String, ResourceHttpRequestHandler> handlerMap);
380
381
/** Set application context */
382
public void setApplicationContext(ApplicationContext applicationContext);
383
}
384
```
385
386
**Usage in Templates:**
387
388
```html
389
<!-- JSP -->
390
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
391
<link rel="stylesheet" href="<c:url value='/resources/css/style.css' />">
392
<script src="<c:url value='/resources/js/app.js' />"></script>
393
394
<!-- Thymeleaf -->
395
<link rel="stylesheet" th:href="@{/resources/css/style.css}">
396
<script th:src="@{/resources/js/app.js}"></script>
397
```
398
399
```java
400
@Controller
401
public class HomeController {
402
403
@Autowired
404
private ResourceUrlProvider resourceUrlProvider;
405
406
@GetMapping("/")
407
public String home(HttpServletRequest request, Model model) {
408
String cssUrl = resourceUrlProvider.getForRequestUrl(request, "/resources/css/style.css");
409
String jsUrl = resourceUrlProvider.getForRequestUrl(request, "/resources/js/app.js");
410
411
model.addAttribute("cssUrl", cssUrl);
412
model.addAttribute("jsUrl", jsUrl);
413
414
return "home";
415
}
416
}
417
```