org.springframework.web.servlet.resource.WebJarsResourceResolver Maven / Gradle / Ivy
/*
* Copyright 2002-2019 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.resource;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.webjars.WebJarAssetLocator;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
/**
* A {@code ResourceResolver} that delegates to the chain to locate a resource and then
* attempts to find a matching versioned resource contained in a WebJar JAR file.
*
* This allows WebJars.org users to write version agnostic paths in their templates,
* like {@code }.
* This path will be resolved to the unique version {@code },
* which is a better fit for HTTP caching and version management in applications.
*
*
This also resolves resources for version agnostic HTTP requests {@code "GET /jquery/jquery.min.js"}.
*
*
This resolver requires the {@code org.webjars:webjars-locator-core} library
* on the classpath and is automatically registered if that library is present.
*
* @author Brian Clozel
* @since 4.2
* @see org.springframework.web.servlet.config.annotation.ResourceChainRegistration
* @see webjars.org
*/
public class WebJarsResourceResolver extends AbstractResourceResolver {
private static final String WEBJARS_LOCATION = "META-INF/resources/webjars/";
private static final int WEBJARS_LOCATION_LENGTH = WEBJARS_LOCATION.length();
private final WebJarAssetLocator webJarAssetLocator;
/**
* Create a {@code WebJarsResourceResolver} with a default {@code WebJarAssetLocator} instance.
*/
public WebJarsResourceResolver() {
this(new WebJarAssetLocator());
}
/**
* Create a {@code WebJarsResourceResolver} with a custom {@code WebJarAssetLocator} instance,
* e.g. with a custom index.
* @since 4.3
*/
public WebJarsResourceResolver(WebJarAssetLocator webJarAssetLocator) {
this.webJarAssetLocator = webJarAssetLocator;
}
@Override
protected Resource resolveResourceInternal(@Nullable HttpServletRequest request, String requestPath,
List extends Resource> locations, ResourceResolverChain chain) {
Resource resolved = chain.resolveResource(request, requestPath, locations);
if (resolved == null) {
String webJarResourcePath = findWebJarResourcePath(requestPath);
if (webJarResourcePath != null) {
return chain.resolveResource(request, webJarResourcePath, locations);
}
}
return resolved;
}
@Override
protected String resolveUrlPathInternal(String resourceUrlPath,
List extends Resource> locations, ResourceResolverChain chain) {
String path = chain.resolveUrlPath(resourceUrlPath, locations);
if (path == null) {
String webJarResourcePath = findWebJarResourcePath(resourceUrlPath);
if (webJarResourcePath != null) {
return chain.resolveUrlPath(webJarResourcePath, locations);
}
}
return path;
}
@Nullable
protected String findWebJarResourcePath(String path) {
int startOffset = (path.startsWith("/") ? 1 : 0);
int endOffset = path.indexOf('/', 1);
if (endOffset != -1) {
String webjar = path.substring(startOffset, endOffset);
String partialPath = path.substring(endOffset + 1);
String webJarPath = this.webJarAssetLocator.getFullPathExact(webjar, partialPath);
if (webJarPath != null) {
return webJarPath.substring(WEBJARS_LOCATION_LENGTH);
}
}
return null;
}
}