32
32
import org .apache .commons .logging .LogFactory ;
33
33
34
34
import org .springframework .beans .factory .InitializingBean ;
35
- import org .springframework .beans .factory .config .ConfigurableBeanFactory ;
36
35
import org .springframework .context .ApplicationContext ;
36
+ import org .springframework .context .EmbeddedValueResolverAware ;
37
37
import org .springframework .core .io .Resource ;
38
38
import org .springframework .core .io .UrlResource ;
39
39
import org .springframework .core .io .support .ResourceRegion ;
51
51
import org .springframework .util .ObjectUtils ;
52
52
import org .springframework .util .ResourceUtils ;
53
53
import org .springframework .util .StringUtils ;
54
+ import org .springframework .util .StringValueResolver ;
54
55
import org .springframework .web .HttpRequestHandler ;
55
56
import org .springframework .web .accept .ContentNegotiationManager ;
56
57
import org .springframework .web .accept .PathExtensionContentNegotiationStrategy ;
95
96
* @since 3.0.4
96
97
*/
97
98
public class ResourceHttpRequestHandler extends WebContentGenerator
98
- implements HttpRequestHandler , InitializingBean , CorsConfigurationSource {
99
+ implements HttpRequestHandler , EmbeddedValueResolverAware , InitializingBean , CorsConfigurationSource {
99
100
100
101
// Servlet 3.1 setContentLengthLong(long) available?
101
102
private static final boolean contentLengthLongAvailable =
@@ -106,12 +107,12 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
106
107
private static final String URL_RESOURCE_CHARSET_PREFIX = "[charset=" ;
107
108
108
109
110
+ private final List <String > locationValues = new ArrayList <String >(4 );
111
+
109
112
private final List <Resource > locations = new ArrayList <Resource >(4 );
110
113
111
114
private final Map <Resource , Charset > locationCharsets = new HashMap <Resource , Charset >(4 );
112
115
113
- private final List <String > locationValues = new ArrayList <String >(4 );
114
-
115
116
private final List <ResourceResolver > resourceResolvers = new ArrayList <ResourceResolver >(4 );
116
117
117
118
private final List <ResourceTransformer > resourceTransformers = new ArrayList <ResourceTransformer >(4 );
@@ -128,12 +129,28 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
128
129
129
130
private UrlPathHelper urlPathHelper ;
130
131
132
+ private StringValueResolver embeddedValueResolver ;
133
+
131
134
132
135
public ResourceHttpRequestHandler () {
133
136
super (HttpMethod .GET .name (), HttpMethod .HEAD .name ());
134
137
}
135
138
136
139
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
+
137
154
/**
138
155
* Set the {@code List} of {@code Resource} locations to use as sources
139
156
* for serving static resources.
@@ -147,28 +164,16 @@ public void setLocations(List<Resource> locations) {
147
164
148
165
/**
149
166
* 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,
151
168
* instead of loaded Resource-based locations, this method will return
152
169
* empty until after initialization via {@link #afterPropertiesSet()}.
170
+ * @see #setLocationValues
171
+ * @see #setLocations
153
172
*/
154
173
public List <Resource > getLocations () {
155
174
return this .locations ;
156
175
}
157
176
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
-
172
177
/**
173
178
* Configure the list of {@link ResourceResolver}s to use.
174
179
* <p>By default {@link PathResourceResolver} is configured. If using this property,
@@ -211,8 +216,8 @@ public List<ResourceTransformer> getResourceTransformers() {
211
216
* <p>By default a {@link ResourceHttpMessageConverter} will be configured.
212
217
* @since 4.3
213
218
*/
214
- public void setResourceHttpMessageConverter (ResourceHttpMessageConverter resourceHttpMessageConverter ) {
215
- this .resourceHttpMessageConverter = resourceHttpMessageConverter ;
219
+ public void setResourceHttpMessageConverter (ResourceHttpMessageConverter messageConverter ) {
220
+ this .resourceHttpMessageConverter = messageConverter ;
216
221
}
217
222
218
223
/**
@@ -228,8 +233,8 @@ public ResourceHttpMessageConverter getResourceHttpMessageConverter() {
228
233
* <p>By default a {@link ResourceRegionHttpMessageConverter} will be configured.
229
234
* @since 4.3
230
235
*/
231
- public void setResourceRegionHttpMessageConverter (ResourceRegionHttpMessageConverter resourceRegionHttpMessageConverter ) {
232
- this .resourceRegionHttpMessageConverter = resourceRegionHttpMessageConverter ;
236
+ public void setResourceRegionHttpMessageConverter (ResourceRegionHttpMessageConverter messageConverter ) {
237
+ this .resourceRegionHttpMessageConverter = messageConverter ;
233
238
}
234
239
235
240
/**
@@ -244,7 +249,6 @@ public ResourceRegionHttpMessageConverter getResourceRegionHttpMessageConverter(
244
249
* Configure a {@code ContentNegotiationManager} to help determine the
245
250
* media types for resources being served. If the manager contains a path
246
251
* extension strategy it will be checked for registered file extension.
247
- * @param contentNegotiationManager the manager in use
248
252
* @since 4.3
249
253
*/
250
254
public void setContentNegotiationManager (ContentNegotiationManager contentNegotiationManager ) {
@@ -293,11 +297,15 @@ public UrlPathHelper getUrlPathHelper() {
293
297
return this .urlPathHelper ;
294
298
}
295
299
300
+ @ Override
301
+ public void setEmbeddedValueResolver (StringValueResolver resolver ) {
302
+ this .embeddedValueResolver = resolver ;
303
+ }
304
+
296
305
297
306
@ Override
298
307
public void afterPropertiesSet () throws Exception {
299
-
300
- loadResourceLocations ();
308
+ resolveResourceLocations ();
301
309
302
310
if (logger .isWarnEnabled () && CollectionUtils .isEmpty (this .locations )) {
303
311
logger .warn ("Locations list is empty. No resources will be served unless a " +
@@ -320,23 +328,23 @@ public void afterPropertiesSet() throws Exception {
320
328
this .contentNegotiationStrategy = initContentNegotiationStrategy ();
321
329
}
322
330
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 () {
328
332
if (CollectionUtils .isEmpty (this .locationValues )) {
329
333
return ;
330
334
}
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." );
335
338
}
339
+
340
+ ApplicationContext applicationContext = getApplicationContext ();
336
341
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 ;
340
348
}
341
349
Charset charset = null ;
342
350
location = location .trim ();
@@ -349,7 +357,7 @@ private void loadResourceLocations() {
349
357
charset = Charset .forName (value );
350
358
location = location .substring (endIndex + 1 );
351
359
}
352
- Resource resource = appContext .getResource (location );
360
+ Resource resource = applicationContext .getResource (location );
353
361
this .locations .add (resource );
354
362
if (charset != null ) {
355
363
if (!(resource instanceof UrlResource )) {
0 commit comments