@ -31,8 +31,8 @@ import org.apache.commons.logging.Log;
@@ -31,8 +31,8 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory ;
import org.springframework.beans.factory.InitializingBean ;
import org.springframework.beans.factory.config.ConfigurableBeanFactory ;
import org.springframework.context.ApplicationContext ;
import org.springframework.context.EmbeddedValueResolverAware ;
import org.springframework.core.io.Resource ;
import org.springframework.core.io.UrlResource ;
import org.springframework.http.HttpHeaders ;
@ -49,6 +49,7 @@ import org.springframework.util.CollectionUtils;
@@ -49,6 +49,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils ;
import org.springframework.util.ResourceUtils ;
import org.springframework.util.StringUtils ;
import org.springframework.util.StringValueResolver ;
import org.springframework.web.HttpRequestHandler ;
import org.springframework.web.accept.ContentNegotiationManager ;
import org.springframework.web.accept.PathExtensionContentNegotiationStrategy ;
@ -93,19 +94,19 @@ import org.springframework.web.util.UrlPathHelper;
@@ -93,19 +94,19 @@ import org.springframework.web.util.UrlPathHelper;
* @since 3 . 0 . 4
* /
public class ResourceHttpRequestHandler extends WebContentGenerator
implements HttpRequestHandler , InitializingBean , CorsConfigurationSource {
implements HttpRequestHandler , EmbeddedValueResolverAware , InitializingBean , CorsConfigurationSource {
private static final Log logger = LogFactory . getLog ( ResourceHttpRequestHandler . class ) ;
private static final String URL_RESOURCE_CHARSET_PREFIX = "[charset=" ;
private final List < String > locationValues = new ArrayList < > ( 4 ) ;
private final List < Resource > locations = new ArrayList < > ( 4 ) ;
private final Map < Resource , Charset > locationCharsets = new HashMap < > ( 4 ) ;
private final List < String > locationValues = new ArrayList < > ( 4 ) ;
private final List < ResourceResolver > resourceResolvers = new ArrayList < > ( 4 ) ;
private final List < ResourceTransformer > resourceTransformers = new ArrayList < > ( 4 ) ;
@ -128,12 +129,29 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
@@ -128,12 +129,29 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
@Nullable
private UrlPathHelper urlPathHelper ;
@Nullable
private StringValueResolver embeddedValueResolver ;
public ResourceHttpRequestHandler ( ) {
super ( HttpMethod . GET . name ( ) , HttpMethod . HEAD . name ( ) ) ;
}
/ * *
* An alternative to { @link # setLocations ( List ) } that accepts a list of
* String - based location values , with support for { @link UrlResource } ' s
* ( e . g . files or HTTP URLs ) with a special prefix to indicate the charset
* to use when appending relative paths . For example
* { @code "[charset=Windows-31J]http://example.org/path" } .
* @since 4 . 3 . 13
* /
public void setLocationValues ( List < String > locationValues ) {
Assert . notNull ( locationValues , "Location values list must not be null" ) ;
this . locationValues . clear ( ) ;
this . locationValues . addAll ( locationValues ) ;
}
/ * *
* Set the { @code List } of { @code Resource } locations to use as sources
* for serving static resources .
@ -147,28 +165,16 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
@@ -147,28 +165,16 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
/ * *
* Return the configured { @code List } of { @code Resource } locations .
* Note that if { @link # setLocationValues ( List ) locationValues } are provided ,
* < p > Note that if { @link # setLocationValues ( List ) locationValues } are provided ,
* instead of loaded Resource - based locations , this method will return
* empty until after initialization via { @link # afterPropertiesSet ( ) } .
* @see # setLocationValues
* @see # setLocations
* /
public List < Resource > getLocations ( ) {
return this . locations ;
}
/ * *
* An alternative to { @link # setLocations ( List ) } that accepts a list of
* String - based location values , with support for { @link UrlResource } ' s
* ( e . g . files or HTTP URLs ) with a special prefix to indicate the charset
* to use when appending relative paths . For example
* { @code "[charset=Windows-31J]http://example.org/path" } .
* @since 4 . 3 . 13
* /
public void setLocationValues ( List < String > locationValues ) {
Assert . notNull ( locationValues , "Location values list must not be null" ) ;
this . locationValues . clear ( ) ;
this . locationValues . addAll ( locationValues ) ;
}
/ * *
* Configure the list of { @link ResourceResolver } s to use .
* < p > By default { @link PathResourceResolver } is configured . If using this property ,
@ -246,7 +252,6 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
@@ -246,7 +252,6 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
* Configure a { @code ContentNegotiationManager } to help determine the
* media types for resources being served . If the manager contains a path
* extension strategy it will be checked for registered file extension .
* @param contentNegotiationManager the manager in use
* @since 4 . 3
* /
public void setContentNegotiationManager ( @Nullable ContentNegotiationManager contentNegotiationManager ) {
@ -298,11 +303,15 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
@@ -298,11 +303,15 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
return this . urlPathHelper ;
}
@Override
public void setEmbeddedValueResolver ( StringValueResolver resolver ) {
this . embeddedValueResolver = resolver ;
}
@Override
public void afterPropertiesSet ( ) throws Exception {
loadResourceLocations ( ) ;
resolveResourceLocations ( ) ;
if ( logger . isWarnEnabled ( ) & & CollectionUtils . isEmpty ( this . locations ) ) {
logger . warn ( "Locations list is empty. No resources will be served unless a " +
@ -325,23 +334,23 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
@@ -325,23 +334,23 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
this . contentNegotiationStrategy = initContentNegotiationStrategy ( ) ;
}
private void loadResourceLocations ( ) {
if ( ! CollectionUtils . isEmpty ( this . locations ) & & ! CollectionUtils . isEmpty ( this . locationValues ) ) {
throw new IllegalArgumentException ( "Please set either Resource-based \"locations\" or " +
"String-based \"locationValues\", but not both." ) ;
}
private void resolveResourceLocations ( ) {
if ( CollectionUtils . isEmpty ( this . locationValues ) ) {
return ;
}
ApplicationContext appContext = obtainApplicationContext ( ) ;
ConfigurableBeanFactory beanFactory = null ;
if ( appContext . getAutowireCapableBeanFactory ( ) instanceof ConfigurableBeanFactory ) {
beanFactory = ( ( ConfigurableBeanFactory ) appContext . getAutowireCapableBeanFactory ( ) ) ;
else if ( ! CollectionUtils . isEmpty ( this . locations ) ) {
throw new IllegalArgumentException ( "Please set either Resource-based \"locations\" or " +
"String-based \"locationValues\", but not both." ) ;
}
ApplicationContext applicationContext = obtainApplicationContext ( ) ;
for ( String location : this . locationValues ) {
if ( beanFactory ! = null ) {
location = beanFactory . resolveEmbeddedValue ( location ) ;
Assert . notNull ( location , "Null location" ) ;
if ( this . embeddedValueResolver ! = null ) {
String resolvedLocation = this . embeddedValueResolver . resolveStringValue ( location ) ;
if ( resolvedLocation = = null ) {
throw new IllegalArgumentException ( "Location resolved to null: " + location ) ;
}
location = resolvedLocation ;
}
Charset charset = null ;
location = location . trim ( ) ;
@ -354,7 +363,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
@@ -354,7 +363,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
charset = Charset . forName ( value ) ;
location = location . substring ( endIndex + 1 ) ;
}
Resource resource = appContext . getResource ( location ) ;
Resource resource = application Context . getResource ( location ) ;
this . locations . add ( resource ) ;
if ( charset ! = null ) {
if ( ! ( resource instanceof UrlResource ) ) {