Skip to content

Commit 122a3fe

Browse files
committed
ResourceHttpRequestHandler uses EmbeddedValueResolverAware
(cherry picked from commit 20fcefc)
1 parent 2a309a0 commit 122a3fe

File tree

2 files changed

+53
-49
lines changed

2 files changed

+53
-49
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistration.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ public class ResourceHandlerRegistration {
3838

3939
private final String[] pathPatterns;
4040

41-
private final List<String> locationValues = new ArrayList<String>(4);
41+
private final List<String> locationValues = new ArrayList<String>();
4242

4343
private Integer cachePeriod;
4444

@@ -56,6 +56,7 @@ public ResourceHandlerRegistration(String... pathPatterns) {
5656
this.pathPatterns = pathPatterns;
5757
}
5858

59+
5960
/**
6061
* Add one or more resource locations from which to serve static content.
6162
* Each location must point to a valid directory. Multiple locations may
@@ -94,9 +95,7 @@ public ResourceHandlerRegistration setCachePeriod(Integer cachePeriod) {
9495
/**
9596
* Specify the {@link org.springframework.http.CacheControl} which should be used
9697
* by the resource handler.
97-
*
9898
* <p>Setting a custom value here will override the configuration set with {@link #setCachePeriod}.
99-
*
10099
* @param cacheControl the CacheControl configuration to use
101100
* @return the same {@link ResourceHandlerRegistration} instance, for chained method invocation
102101
* @since 4.2
@@ -109,11 +108,9 @@ public ResourceHandlerRegistration setCacheControl(CacheControl cacheControl) {
109108
/**
110109
* Configure a chain of resource resolvers and transformers to use. This
111110
* can be useful, for example, to apply a version strategy to resource URLs.
112-
*
113111
* <p>If this method is not invoked, by default only a simple
114112
* {@link PathResourceResolver} is used in order to match URL paths to
115113
* resources under the configured locations.
116-
*
117114
* @param cacheResources whether to cache the result of resource resolution;
118115
* setting this to "true" is recommended for production (and "false" for
119116
* development, especially when applying a version strategy)
@@ -128,11 +125,9 @@ public ResourceChainRegistration resourceChain(boolean cacheResources) {
128125
/**
129126
* Configure a chain of resource resolvers and transformers to use. This
130127
* can be useful, for example, to apply a version strategy to resource URLs.
131-
*
132128
* <p>If this method is not invoked, by default only a simple
133129
* {@link PathResourceResolver} is used in order to match URL paths to
134130
* resources under the configured locations.
135-
*
136131
* @param cacheResources whether to cache the result of resource resolution;
137132
* setting this to "true" is recommended for production (and "false" for
138133
* development, especially when applying a version strategy
@@ -149,15 +144,16 @@ public ResourceChainRegistration resourceChain(boolean cacheResources, Cache cac
149144
return this.resourceChainRegistration;
150145
}
151146

147+
152148
/**
153-
* Returns the URL path patterns for the resource handler.
149+
* Return the URL path patterns for the resource handler.
154150
*/
155151
protected String[] getPathPatterns() {
156152
return this.pathPatterns;
157153
}
158154

159155
/**
160-
* Returns a {@link ResourceHttpRequestHandler} instance.
156+
* Return a {@link ResourceHttpRequestHandler} instance.
161157
*/
162158
protected ResourceHttpRequestHandler getRequestHandler() {
163159
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();

spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
import org.apache.commons.logging.LogFactory;
3333

3434
import org.springframework.beans.factory.InitializingBean;
35-
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
3635
import org.springframework.context.ApplicationContext;
36+
import org.springframework.context.EmbeddedValueResolverAware;
3737
import org.springframework.core.io.Resource;
3838
import org.springframework.core.io.UrlResource;
3939
import org.springframework.core.io.support.ResourceRegion;
@@ -51,6 +51,7 @@
5151
import org.springframework.util.ObjectUtils;
5252
import org.springframework.util.ResourceUtils;
5353
import org.springframework.util.StringUtils;
54+
import org.springframework.util.StringValueResolver;
5455
import org.springframework.web.HttpRequestHandler;
5556
import org.springframework.web.accept.ContentNegotiationManager;
5657
import org.springframework.web.accept.PathExtensionContentNegotiationStrategy;
@@ -95,7 +96,7 @@
9596
* @since 3.0.4
9697
*/
9798
public class ResourceHttpRequestHandler extends WebContentGenerator
98-
implements HttpRequestHandler, InitializingBean, CorsConfigurationSource {
99+
implements HttpRequestHandler, EmbeddedValueResolverAware, InitializingBean, CorsConfigurationSource {
99100

100101
// Servlet 3.1 setContentLengthLong(long) available?
101102
private static final boolean contentLengthLongAvailable =
@@ -106,12 +107,12 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
106107
private static final String URL_RESOURCE_CHARSET_PREFIX = "[charset=";
107108

108109

110+
private final List<String> locationValues = new ArrayList<String>(4);
111+
109112
private final List<Resource> locations = new ArrayList<Resource>(4);
110113

111114
private final Map<Resource, Charset> locationCharsets = new HashMap<Resource, Charset>(4);
112115

113-
private final List<String> locationValues = new ArrayList<String>(4);
114-
115116
private final List<ResourceResolver> resourceResolvers = new ArrayList<ResourceResolver>(4);
116117

117118
private final List<ResourceTransformer> resourceTransformers = new ArrayList<ResourceTransformer>(4);
@@ -128,12 +129,28 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
128129

129130
private UrlPathHelper urlPathHelper;
130131

132+
private StringValueResolver embeddedValueResolver;
133+
131134

132135
public ResourceHttpRequestHandler() {
133136
super(HttpMethod.GET.name(), HttpMethod.HEAD.name());
134137
}
135138

136139

140+
/**
141+
* An alternative to {@link #setLocations(List)} that accepts a list of
142+
* String-based location values, with support for {@link UrlResource}'s
143+
* (e.g. files or HTTP URLs) with a special prefix to indicate the charset
144+
* to use when appending relative paths. For example
145+
* {@code "[charset=Windows-31J]http://example.org/path"}.
146+
* @since 4.3.13
147+
*/
148+
public void setLocationValues(List<String> locationValues) {
149+
Assert.notNull(locationValues, "Location values list must not be null");
150+
this.locationValues.clear();
151+
this.locationValues.addAll(locationValues);
152+
}
153+
137154
/**
138155
* Set the {@code List} of {@code Resource} locations to use as sources
139156
* for serving static resources.
@@ -147,28 +164,16 @@ public void setLocations(List<Resource> locations) {
147164

148165
/**
149166
* Return the configured {@code List} of {@code Resource} locations.
150-
* Note that if {@link #setLocationValues(List) locationValues} are provided,
167+
* <p>Note that if {@link #setLocationValues(List) locationValues} are provided,
151168
* instead of loaded Resource-based locations, this method will return
152169
* empty until after initialization via {@link #afterPropertiesSet()}.
170+
* @see #setLocationValues
171+
* @see #setLocations
153172
*/
154173
public List<Resource> getLocations() {
155174
return this.locations;
156175
}
157176

158-
/**
159-
* An alternative to {@link #setLocations(List)} that accepts a list of
160-
* String-based location values, with support for {@link UrlResource}'s
161-
* (e.g. files or HTTP URLs) with a special prefix to indicate the charset
162-
* to use when appending relative paths. For example
163-
* {@code "[charset=Windows-31J]http://example.org/path"}.
164-
* @since 4.3.13
165-
*/
166-
public void setLocationValues(List<String> locationValues) {
167-
Assert.notNull(locationValues, "Location values list must not be null");
168-
this.locationValues.clear();
169-
this.locationValues.addAll(locationValues);
170-
}
171-
172177
/**
173178
* Configure the list of {@link ResourceResolver}s to use.
174179
* <p>By default {@link PathResourceResolver} is configured. If using this property,
@@ -211,8 +216,8 @@ public List<ResourceTransformer> getResourceTransformers() {
211216
* <p>By default a {@link ResourceHttpMessageConverter} will be configured.
212217
* @since 4.3
213218
*/
214-
public void setResourceHttpMessageConverter(ResourceHttpMessageConverter resourceHttpMessageConverter) {
215-
this.resourceHttpMessageConverter = resourceHttpMessageConverter;
219+
public void setResourceHttpMessageConverter(ResourceHttpMessageConverter messageConverter) {
220+
this.resourceHttpMessageConverter = messageConverter;
216221
}
217222

218223
/**
@@ -228,8 +233,8 @@ public ResourceHttpMessageConverter getResourceHttpMessageConverter() {
228233
* <p>By default a {@link ResourceRegionHttpMessageConverter} will be configured.
229234
* @since 4.3
230235
*/
231-
public void setResourceRegionHttpMessageConverter(ResourceRegionHttpMessageConverter resourceRegionHttpMessageConverter) {
232-
this.resourceRegionHttpMessageConverter = resourceRegionHttpMessageConverter;
236+
public void setResourceRegionHttpMessageConverter(ResourceRegionHttpMessageConverter messageConverter) {
237+
this.resourceRegionHttpMessageConverter = messageConverter;
233238
}
234239

235240
/**
@@ -244,7 +249,6 @@ public ResourceRegionHttpMessageConverter getResourceRegionHttpMessageConverter(
244249
* Configure a {@code ContentNegotiationManager} to help determine the
245250
* media types for resources being served. If the manager contains a path
246251
* extension strategy it will be checked for registered file extension.
247-
* @param contentNegotiationManager the manager in use
248252
* @since 4.3
249253
*/
250254
public void setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager) {
@@ -293,11 +297,15 @@ public UrlPathHelper getUrlPathHelper() {
293297
return this.urlPathHelper;
294298
}
295299

300+
@Override
301+
public void setEmbeddedValueResolver(StringValueResolver resolver) {
302+
this.embeddedValueResolver = resolver;
303+
}
304+
296305

297306
@Override
298307
public void afterPropertiesSet() throws Exception {
299-
300-
loadResourceLocations();
308+
resolveResourceLocations();
301309

302310
if (logger.isWarnEnabled() && CollectionUtils.isEmpty(this.locations)) {
303311
logger.warn("Locations list is empty. No resources will be served unless a " +
@@ -320,23 +328,23 @@ public void afterPropertiesSet() throws Exception {
320328
this.contentNegotiationStrategy = initContentNegotiationStrategy();
321329
}
322330

323-
private void loadResourceLocations() {
324-
if (!CollectionUtils.isEmpty(this.locations) && !CollectionUtils.isEmpty(this.locationValues)) {
325-
throw new IllegalArgumentException("Please set either Resource-based \"locations\" or " +
326-
"String-based \"locationValues\", but not both.");
327-
}
331+
private void resolveResourceLocations() {
328332
if (CollectionUtils.isEmpty(this.locationValues)) {
329333
return;
330334
}
331-
ApplicationContext appContext = getApplicationContext();
332-
ConfigurableBeanFactory beanFactory = null;
333-
if (appContext.getAutowireCapableBeanFactory() instanceof ConfigurableBeanFactory) {
334-
beanFactory = ((ConfigurableBeanFactory) appContext.getAutowireCapableBeanFactory());
335+
else if (!CollectionUtils.isEmpty(this.locations)) {
336+
throw new IllegalArgumentException("Please set either Resource-based \"locations\" or " +
337+
"String-based \"locationValues\", but not both.");
335338
}
339+
340+
ApplicationContext applicationContext = getApplicationContext();
336341
for (String location : this.locationValues) {
337-
if (beanFactory != null) {
338-
location = beanFactory.resolveEmbeddedValue(location);
339-
Assert.notNull(location, "Null location");
342+
if (this.embeddedValueResolver != null) {
343+
String resolvedLocation = this.embeddedValueResolver.resolveStringValue(location);
344+
if (resolvedLocation == null) {
345+
throw new IllegalArgumentException("Location resolved to null: " + location);
346+
}
347+
location = resolvedLocation;
340348
}
341349
Charset charset = null;
342350
location = location.trim();
@@ -349,7 +357,7 @@ private void loadResourceLocations() {
349357
charset = Charset.forName(value);
350358
location = location.substring(endIndex + 1);
351359
}
352-
Resource resource = appContext.getResource(location);
360+
Resource resource = applicationContext.getResource(location);
353361
this.locations.add(resource);
354362
if (charset != null) {
355363
if (!(resource instanceof UrlResource)) {

0 commit comments

Comments
 (0)