ResourceHandlerRegistration exposes List<Resource> locations
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,6 +42,8 @@ public class ResourceHandlerRegistration {
|
||||
|
||||
private final List<String> locationValues = new ArrayList<>();
|
||||
|
||||
private final List<Resource> locationsResources = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private Integer cachePeriod;
|
||||
|
||||
@@ -82,8 +84,21 @@ public class ResourceHandlerRegistration {
|
||||
* @return the same {@link ResourceHandlerRegistration} instance, for
|
||||
* chained method invocation
|
||||
*/
|
||||
public ResourceHandlerRegistration addResourceLocations(String... resourceLocations) {
|
||||
this.locationValues.addAll(Arrays.asList(resourceLocations));
|
||||
public ResourceHandlerRegistration addResourceLocations(String... locations) {
|
||||
this.locationValues.addAll(Arrays.asList(locations));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure locations to serve static resources from based on pre-resolved
|
||||
* {@code Resource} references.
|
||||
* @param locations the resource locations to use
|
||||
* @return the same {@link ResourceHandlerRegistration} instance, for
|
||||
* chained method invocation
|
||||
* @since 5.3.3
|
||||
*/
|
||||
public ResourceHandlerRegistration addResourceLocations(Resource... locations) {
|
||||
this.locationsResources.addAll(Arrays.asList(locations));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -181,6 +196,7 @@ public class ResourceHandlerRegistration {
|
||||
handler.setResourceTransformers(this.resourceChainRegistration.getResourceTransformers());
|
||||
}
|
||||
handler.setLocationValues(this.locationValues);
|
||||
handler.setLocations(this.locationsResources);
|
||||
if (this.cacheControl != null) {
|
||||
handler.setCacheControl(this.cacheControl);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,12 +21,10 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -69,9 +67,10 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
* {@code HttpRequestHandler} that serves static resources in an optimized way
|
||||
* according to the guidelines of Page Speed, YSlow, etc.
|
||||
*
|
||||
* <p>The {@linkplain #setLocations "locations"} property takes a list of Spring
|
||||
* {@link Resource} locations from which static resources are allowed to be served
|
||||
* by this handler. Resources could be served from a classpath location, e.g.
|
||||
* <p>The properties {@linkplain #setLocations "locations"} and
|
||||
* {@linkplain #setLocationValues "locationValues"} accept locations from which
|
||||
* static resources can be served by this handler. This can be relative to the
|
||||
* root of the web application, or from the classpath, e.g.
|
||||
* "classpath:/META-INF/public-web-resources/", allowing convenient packaging
|
||||
* and serving of resources such as .js, .css, and others in jar files.
|
||||
*
|
||||
@@ -106,7 +105,9 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
|
||||
private final List<String> locationValues = new ArrayList<>(4);
|
||||
|
||||
private final List<Resource> locations = new ArrayList<>(4);
|
||||
private final List<Resource> locationResources = new ArrayList<>(4);
|
||||
|
||||
private final List<Resource> locationsToUse = new ArrayList<>(4);
|
||||
|
||||
private final Map<Resource, Charset> locationCharsets = new HashMap<>(4);
|
||||
|
||||
@@ -149,40 +150,52 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Configure String-based locations to serve resources from.
|
||||
* <p>For example, {{@code "/"}, {@code "classpath:/META-INF/public-web-resources/"}}
|
||||
* allows resources to be served both from the web application root and
|
||||
* from any JAR on the classpath that contains a
|
||||
* {@code /META-INF/public-web-resources/} directory, with resources in the
|
||||
* web application root taking precedence.
|
||||
* <p>For {@link org.springframework.core.io.UrlResource URL-based resources}
|
||||
* (e.g. files, HTTP URLs, etc) this method supports a special prefix to
|
||||
* indicate the charset associated with the URL so that relative paths
|
||||
* appended to it can be encoded correctly, for example
|
||||
* {@code "[charset=Windows-31J]https://example.org/path"}.
|
||||
* @since 4.3.13
|
||||
* @see #setLocations(List)
|
||||
*/
|
||||
public void setLocationValues(List<String> locationValues) {
|
||||
Assert.notNull(locationValues, "Location values list must not be null");
|
||||
public void setLocationValues(List<String> locations) {
|
||||
Assert.notNull(locations, "Locations list must not be null");
|
||||
this.locationValues.clear();
|
||||
this.locationValues.addAll(locationValues);
|
||||
this.locationValues.addAll(locations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code List} of {@code Resource} locations to use as sources
|
||||
* for serving static resources.
|
||||
* Configure locations to serve resources from as pre-resourced Resource's.
|
||||
* @see #setLocationValues(List)
|
||||
*/
|
||||
public void setLocations(List<Resource> locations) {
|
||||
Assert.notNull(locations, "Locations list must not be null");
|
||||
this.locations.clear();
|
||||
this.locations.addAll(locations);
|
||||
this.locationResources.clear();
|
||||
this.locationResources.addAll(locations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured {@code List} of {@code Resource} locations.
|
||||
* <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()}.
|
||||
* Return the configured {@code List} of {@code Resource} locations including
|
||||
* both String-based locations provided via
|
||||
* {@link #setLocationValues(List) setLocationValues} and pre-resolved {@code Resource}
|
||||
* locations provided via {@link #setLocations(List) setLocations}.
|
||||
* <p>Note that the returned list is fully initialized only after
|
||||
* initialization via {@link #afterPropertiesSet()}.
|
||||
* @see #setLocationValues
|
||||
* @see #setLocations
|
||||
*/
|
||||
public List<Resource> getLocations() {
|
||||
return this.locations;
|
||||
if (this.locationsToUse.isEmpty()) {
|
||||
// Possibly not yet initialized, return only what we have so far
|
||||
return this.locationResources;
|
||||
}
|
||||
return this.locationsToUse;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,7 +387,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
resolveResourceLocations();
|
||||
|
||||
if (logger.isWarnEnabled() && CollectionUtils.isEmpty(this.locations)) {
|
||||
if (logger.isWarnEnabled() && CollectionUtils.isEmpty(getLocations())) {
|
||||
logger.warn("Locations list is empty. No resources will be served unless a " +
|
||||
"custom ResourceResolver is configured as an alternative to PathResourceResolver.");
|
||||
}
|
||||
@@ -410,43 +423,38 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
}
|
||||
|
||||
private void resolveResourceLocations() {
|
||||
if (CollectionUtils.isEmpty(this.locationValues)) {
|
||||
return;
|
||||
}
|
||||
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 (this.embeddedValueResolver != null) {
|
||||
String resolvedLocation = this.embeddedValueResolver.resolveStringValue(location);
|
||||
if (resolvedLocation == null) {
|
||||
throw new IllegalArgumentException("Location resolved to null: " + location);
|
||||
if (!this.locationValues.isEmpty()) {
|
||||
ApplicationContext applicationContext = obtainApplicationContext();
|
||||
for (String location : this.locationValues) {
|
||||
if (this.embeddedValueResolver != null) {
|
||||
String resolvedLocation = this.embeddedValueResolver.resolveStringValue(location);
|
||||
if (resolvedLocation == null) {
|
||||
throw new IllegalArgumentException("Location resolved to null: " + location);
|
||||
}
|
||||
location = resolvedLocation;
|
||||
}
|
||||
location = resolvedLocation;
|
||||
}
|
||||
Charset charset = null;
|
||||
location = location.trim();
|
||||
if (location.startsWith(URL_RESOURCE_CHARSET_PREFIX)) {
|
||||
int endIndex = location.indexOf(']', URL_RESOURCE_CHARSET_PREFIX.length());
|
||||
if (endIndex == -1) {
|
||||
throw new IllegalArgumentException("Invalid charset syntax in location: " + location);
|
||||
Charset charset = null;
|
||||
location = location.trim();
|
||||
if (location.startsWith(URL_RESOURCE_CHARSET_PREFIX)) {
|
||||
int endIndex = location.indexOf(']', URL_RESOURCE_CHARSET_PREFIX.length());
|
||||
if (endIndex == -1) {
|
||||
throw new IllegalArgumentException("Invalid charset syntax in location: " + location);
|
||||
}
|
||||
String value = location.substring(URL_RESOURCE_CHARSET_PREFIX.length(), endIndex);
|
||||
charset = Charset.forName(value);
|
||||
location = location.substring(endIndex + 1);
|
||||
}
|
||||
String value = location.substring(URL_RESOURCE_CHARSET_PREFIX.length(), endIndex);
|
||||
charset = Charset.forName(value);
|
||||
location = location.substring(endIndex + 1);
|
||||
}
|
||||
Resource resource = applicationContext.getResource(location);
|
||||
this.locations.add(resource);
|
||||
if (charset != null) {
|
||||
if (!(resource instanceof UrlResource)) {
|
||||
throw new IllegalArgumentException("Unexpected charset for non-UrlResource: " + resource);
|
||||
Resource resource = applicationContext.getResource(location);
|
||||
this.locationsToUse.add(resource);
|
||||
if (charset != null) {
|
||||
if (!(resource instanceof UrlResource)) {
|
||||
throw new IllegalArgumentException("Unexpected charset for non-UrlResource: " + resource);
|
||||
}
|
||||
this.locationCharsets.put(resource, charset);
|
||||
}
|
||||
this.locationCharsets.put(resource, charset);
|
||||
}
|
||||
}
|
||||
this.locationsToUse.addAll(this.locationResources);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -455,7 +463,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
* match the {@link #setLocations locations} configured on this class.
|
||||
*/
|
||||
protected void initAllowedLocations() {
|
||||
if (CollectionUtils.isEmpty(this.locations)) {
|
||||
if (CollectionUtils.isEmpty(getLocations())) {
|
||||
return;
|
||||
}
|
||||
for (int i = getResourceResolvers().size() - 1; i >= 0; i--) {
|
||||
@@ -785,17 +793,6 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ResourceHttpRequestHandler " + formatLocations();
|
||||
return "ResourceHttpRequestHandler " + getLocations();
|
||||
}
|
||||
|
||||
private Object formatLocations() {
|
||||
if (!this.locationValues.isEmpty()) {
|
||||
return this.locationValues.stream().collect(Collectors.joining("\", \"", "[\"", "\"]"));
|
||||
}
|
||||
else if (!this.locations.isEmpty()) {
|
||||
return this.locations;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user