/*
 * 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 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 <script src="/jquery/jquery.min.js"/>. This path will be resolved to the unique version <script src="/jquery/1.2.0/jquery.min.js"/>, which is a better fit for HTTP caching and version management in applications.

This also resolves resources for version agnostic HTTP requests "GET /jquery/jquery.min.js".

This resolver requires the org.webjars:webjars-locator-core library on the classpath and is automatically registered if that library is present.

Author:Brian Clozel
See Also:
Since:4.2
/** * 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. * * <p>This allows WebJars.org users to write version agnostic paths in their templates, * like {@code <script src="/jquery/jquery.min.js"/>}. * This path will be resolved to the unique version {@code <script src="/jquery/1.2.0/jquery.min.js"/>}, * which is a better fit for HTTP caching and version management in applications. * * <p>This also resolves resources for version agnostic HTTP requests {@code "GET /jquery/jquery.min.js"}. * * <p>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 <a href="https://www.webjars.org">webjars.org</a> */
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 WebJarsResourceResolver with a default WebJarAssetLocator instance.
/** * Create a {@code WebJarsResourceResolver} with a default {@code WebJarAssetLocator} instance. */
public WebJarsResourceResolver() { this(new WebJarAssetLocator()); }
Create a WebJarsResourceResolver with a custom WebJarAssetLocator instance, e.g. with a custom index.
Since:4.3
/** * 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; } }