ResourceHttpRequestHandler uses EmbeddedValueResolverAware
This commit is contained in:
parent
14a7da8183
commit
20fcefc647
|
@ -99,9 +99,7 @@ public class ResourceHandlerRegistration {
|
||||||
/**
|
/**
|
||||||
* Specify the {@link org.springframework.http.CacheControl} which should be used
|
* Specify the {@link org.springframework.http.CacheControl} which should be used
|
||||||
* by the resource handler.
|
* by the resource handler.
|
||||||
*
|
|
||||||
* <p>Setting a custom value here will override the configuration set with {@link #setCachePeriod}.
|
* <p>Setting a custom value here will override the configuration set with {@link #setCachePeriod}.
|
||||||
*
|
|
||||||
* @param cacheControl the CacheControl configuration to use
|
* @param cacheControl the CacheControl configuration to use
|
||||||
* @return the same {@link ResourceHandlerRegistration} instance, for chained method invocation
|
* @return the same {@link ResourceHandlerRegistration} instance, for chained method invocation
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
|
@ -114,11 +112,9 @@ public class ResourceHandlerRegistration {
|
||||||
/**
|
/**
|
||||||
* Configure a chain of resource resolvers and transformers to use. This
|
* Configure a chain of resource resolvers and transformers to use. This
|
||||||
* can be useful, for example, to apply a version strategy to resource URLs.
|
* can be useful, for example, to apply a version strategy to resource URLs.
|
||||||
*
|
|
||||||
* <p>If this method is not invoked, by default only a simple
|
* <p>If this method is not invoked, by default only a simple
|
||||||
* {@link PathResourceResolver} is used in order to match URL paths to
|
* {@link PathResourceResolver} is used in order to match URL paths to
|
||||||
* resources under the configured locations.
|
* resources under the configured locations.
|
||||||
*
|
|
||||||
* @param cacheResources whether to cache the result of resource resolution;
|
* @param cacheResources whether to cache the result of resource resolution;
|
||||||
* setting this to "true" is recommended for production (and "false" for
|
* setting this to "true" is recommended for production (and "false" for
|
||||||
* development, especially when applying a version strategy)
|
* development, especially when applying a version strategy)
|
||||||
|
@ -133,11 +129,9 @@ public class ResourceHandlerRegistration {
|
||||||
/**
|
/**
|
||||||
* Configure a chain of resource resolvers and transformers to use. This
|
* Configure a chain of resource resolvers and transformers to use. This
|
||||||
* can be useful, for example, to apply a version strategy to resource URLs.
|
* can be useful, for example, to apply a version strategy to resource URLs.
|
||||||
*
|
|
||||||
* <p>If this method is not invoked, by default only a simple
|
* <p>If this method is not invoked, by default only a simple
|
||||||
* {@link PathResourceResolver} is used in order to match URL paths to
|
* {@link PathResourceResolver} is used in order to match URL paths to
|
||||||
* resources under the configured locations.
|
* resources under the configured locations.
|
||||||
*
|
|
||||||
* @param cacheResources whether to cache the result of resource resolution;
|
* @param cacheResources whether to cache the result of resource resolution;
|
||||||
* setting this to "true" is recommended for production (and "false" for
|
* setting this to "true" is recommended for production (and "false" for
|
||||||
* development, especially when applying a version strategy
|
* development, especially when applying a version strategy
|
||||||
|
@ -154,15 +148,16 @@ public class ResourceHandlerRegistration {
|
||||||
return this.resourceChainRegistration;
|
return this.resourceChainRegistration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the URL path patterns for the resource handler.
|
* Return the URL path patterns for the resource handler.
|
||||||
*/
|
*/
|
||||||
protected String[] getPathPatterns() {
|
protected String[] getPathPatterns() {
|
||||||
return this.pathPatterns;
|
return this.pathPatterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link ResourceHttpRequestHandler} instance.
|
* Return a {@link ResourceHttpRequestHandler} instance.
|
||||||
*/
|
*/
|
||||||
protected ResourceHttpRequestHandler getRequestHandler() {
|
protected ResourceHttpRequestHandler getRequestHandler() {
|
||||||
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
|
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
|
||||||
|
|
|
@ -31,8 +31,8 @@ import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.EmbeddedValueResolverAware;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.UrlResource;
|
import org.springframework.core.io.UrlResource;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
@ -49,6 +49,7 @@ import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.util.StringValueResolver;
|
||||||
import org.springframework.web.HttpRequestHandler;
|
import org.springframework.web.HttpRequestHandler;
|
||||||
import org.springframework.web.accept.ContentNegotiationManager;
|
import org.springframework.web.accept.ContentNegotiationManager;
|
||||||
import org.springframework.web.accept.PathExtensionContentNegotiationStrategy;
|
import org.springframework.web.accept.PathExtensionContentNegotiationStrategy;
|
||||||
|
@ -93,19 +94,19 @@ import org.springframework.web.util.UrlPathHelper;
|
||||||
* @since 3.0.4
|
* @since 3.0.4
|
||||||
*/
|
*/
|
||||||
public class ResourceHttpRequestHandler extends WebContentGenerator
|
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 Log logger = LogFactory.getLog(ResourceHttpRequestHandler.class);
|
||||||
|
|
||||||
private static final String URL_RESOURCE_CHARSET_PREFIX = "[charset=";
|
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 List<Resource> locations = new ArrayList<>(4);
|
||||||
|
|
||||||
private final Map<Resource, Charset> locationCharsets = new HashMap<>(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<ResourceResolver> resourceResolvers = new ArrayList<>(4);
|
||||||
|
|
||||||
private final List<ResourceTransformer> resourceTransformers = new ArrayList<>(4);
|
private final List<ResourceTransformer> resourceTransformers = new ArrayList<>(4);
|
||||||
|
@ -128,12 +129,29 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||||
@Nullable
|
@Nullable
|
||||||
private UrlPathHelper urlPathHelper;
|
private UrlPathHelper urlPathHelper;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private StringValueResolver embeddedValueResolver;
|
||||||
|
|
||||||
|
|
||||||
public ResourceHttpRequestHandler() {
|
public ResourceHttpRequestHandler() {
|
||||||
super(HttpMethod.GET.name(), HttpMethod.HEAD.name());
|
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
|
* Set the {@code List} of {@code Resource} locations to use as sources
|
||||||
* for serving static resources.
|
* for serving static resources.
|
||||||
|
@ -147,28 +165,16 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the configured {@code List} of {@code Resource} locations.
|
* 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
|
* instead of loaded Resource-based locations, this method will return
|
||||||
* empty until after initialization via {@link #afterPropertiesSet()}.
|
* empty until after initialization via {@link #afterPropertiesSet()}.
|
||||||
|
* @see #setLocationValues
|
||||||
|
* @see #setLocations
|
||||||
*/
|
*/
|
||||||
public List<Resource> getLocations() {
|
public List<Resource> getLocations() {
|
||||||
return this.locations;
|
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.
|
* Configure the list of {@link ResourceResolver}s to use.
|
||||||
* <p>By default {@link PathResourceResolver} is configured. If using this property,
|
* <p>By default {@link PathResourceResolver} is configured. If using this property,
|
||||||
|
@ -246,7 +252,6 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||||
* Configure a {@code ContentNegotiationManager} to help determine the
|
* Configure a {@code ContentNegotiationManager} to help determine the
|
||||||
* media types for resources being served. If the manager contains a path
|
* media types for resources being served. If the manager contains a path
|
||||||
* extension strategy it will be checked for registered file extension.
|
* extension strategy it will be checked for registered file extension.
|
||||||
* @param contentNegotiationManager the manager in use
|
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
public void setContentNegotiationManager(@Nullable ContentNegotiationManager contentNegotiationManager) {
|
public void setContentNegotiationManager(@Nullable ContentNegotiationManager contentNegotiationManager) {
|
||||||
|
@ -298,11 +303,15 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||||
return this.urlPathHelper;
|
return this.urlPathHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||||
|
this.embeddedValueResolver = resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
resolveResourceLocations();
|
||||||
loadResourceLocations();
|
|
||||||
|
|
||||||
if (logger.isWarnEnabled() && CollectionUtils.isEmpty(this.locations)) {
|
if (logger.isWarnEnabled() && CollectionUtils.isEmpty(this.locations)) {
|
||||||
logger.warn("Locations list is empty. No resources will be served unless a " +
|
logger.warn("Locations list is empty. No resources will be served unless a " +
|
||||||
|
@ -325,23 +334,23 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||||
this.contentNegotiationStrategy = initContentNegotiationStrategy();
|
this.contentNegotiationStrategy = initContentNegotiationStrategy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadResourceLocations() {
|
private void resolveResourceLocations() {
|
||||||
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.");
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isEmpty(this.locationValues)) {
|
if (CollectionUtils.isEmpty(this.locationValues)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ApplicationContext appContext = obtainApplicationContext();
|
else if (!CollectionUtils.isEmpty(this.locations)) {
|
||||||
ConfigurableBeanFactory beanFactory = null;
|
throw new IllegalArgumentException("Please set either Resource-based \"locations\" or " +
|
||||||
if (appContext.getAutowireCapableBeanFactory() instanceof ConfigurableBeanFactory) {
|
"String-based \"locationValues\", but not both.");
|
||||||
beanFactory = ((ConfigurableBeanFactory) appContext.getAutowireCapableBeanFactory());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApplicationContext applicationContext = obtainApplicationContext();
|
||||||
for (String location : this.locationValues) {
|
for (String location : this.locationValues) {
|
||||||
if (beanFactory != null) {
|
if (this.embeddedValueResolver != null) {
|
||||||
location = beanFactory.resolveEmbeddedValue(location);
|
String resolvedLocation = this.embeddedValueResolver.resolveStringValue(location);
|
||||||
Assert.notNull(location, "Null location");
|
if (resolvedLocation == null) {
|
||||||
|
throw new IllegalArgumentException("Location resolved to null: " + location);
|
||||||
|
}
|
||||||
|
location = resolvedLocation;
|
||||||
}
|
}
|
||||||
Charset charset = null;
|
Charset charset = null;
|
||||||
location = location.trim();
|
location = location.trim();
|
||||||
|
@ -354,7 +363,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||||
charset = Charset.forName(value);
|
charset = Charset.forName(value);
|
||||||
location = location.substring(endIndex + 1);
|
location = location.substring(endIndex + 1);
|
||||||
}
|
}
|
||||||
Resource resource = appContext.getResource(location);
|
Resource resource = applicationContext.getResource(location);
|
||||||
this.locations.add(resource);
|
this.locations.add(resource);
|
||||||
if (charset != null) {
|
if (charset != null) {
|
||||||
if (!(resource instanceof UrlResource)) {
|
if (!(resource instanceof UrlResource)) {
|
||||||
|
|
Loading…
Reference in New Issue