【1】是什么
WebJars是将web前端资源(js,css等)打成jar包文件,然后借助Maven工具,以jar包形式对web前端资源进行统一依赖管理,保证这些Web资源版本唯一性。WebJars的jar包部署在Maven中央仓库上。
【2】WebJars使用
在官网首页,找到资源文件对应的maven依赖,写入项目pom.xml文件,然后在页面引用即可。
如下图所示,引入JQuery和Bootstrap:
pom.xml文件如下所示:
<!--引入jquery-webjar--> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.3.1</version> </dependency> <!--引入bootstrap--> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>4.0.0</version> </dependency>
引入的jar包如下:
【3】SpringBoot对WebJars支持
查看WebMWebMVCAutoConfiguration源码如下:
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); return; } Integer cachePeriod = this.resourceProperties.getCachePeriod(); //注意这里,对webjars支持 if (!registry.hasMappingForPattern("/webjars/**")) { customizeResourceHandlerRegistration( registry.addResourceHandler("/webjars/**") .addResourceLocations( "classpath:/META-INF/resources/webjars/") .setCachePeriod(cachePeriod)); } //这里是对静态资源的映射支持 String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration( registry.addResourceHandler(staticPathPattern) .addResourceLocations( this.resourceProperties.getStaticLocations()) .setCachePeriod(cachePeriod)); } }
其中如下代码说明SpringBoot如何对WebJars进行支持:
所有 /webjars/**都去 classpath:/META-INF/resources/webjars/ 找资源
;
//注意这里,对webjars支持 if (!registry.hasMappingForPattern("/webjars/**")) { customizeResourceHandlerRegistration( registry.addResourceHandler("/webjars/**") .addResourceLocations( "classpath:/META-INF/resources/webjars/") .setCachePeriod(cachePeriod)); }
【4】页面使用
页面引入如下:
<link rel="stylesheet" href="/webjars/bootstrap/4.0.0/css/bootstrap.css" /> <script src="/webjars/jquery/3.3.1/jquery.js"></script> <script src="/webjars/bootstrap/4.0.0/js/bootstrap.js"></script>
如上所示,路径中是需要添加版本号的,这是很不友好的,下面去掉版本号。
pom.xml添加依赖如下:
<dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator</artifactId> <version>0.32</version> </dependency>
对应的类-WebJarsResourceResolver如下:
- WebJarsResourceResolver 的作用是可以让页面引用省略 webjar 的版本。
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; /** * 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 "org.webjars:webjars-locator" library on 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="http://www.webjars.org">webjars.org</a> */ public class WebJarsResourceResolver extends AbstractResourceResolver { private final static String WEBJARS_LOCATION = "META-INF/resources/webjars/";//默认去该路径下寻找 private final static 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(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; } // 这里获取请求对应的项目中实际资源路径, //返回结果如:bootstrap/4.0.0/css/bootstrap.css 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 = webJarAssetLocator.getFullPathExact(webjar, partialPath); if (webJarPath != null) { return webJarPath.substring(WEBJARS_LOCATION_LENGTH); } } return null; } }
页面引用修改如下:
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" /> <script src="/webjars/jquery/jquery.js"></script> <script src="/webjars/bootstrap/js/bootstrap.js"></script>
此时,使用两种形式(带版本号和不带版本号)的请求都可以正确获取资源!