SpringBoot源码:WebJars

别等时光非礼了梦想. 提交于 2019-11-28 12:08:48

    在启动App的时候,控制台会输出下面一行:

Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]

    很好奇,GG了一下WebJars? 找到了 Roy Clarkson 在2014年写的一篇文章《Utilizing WebJars in Spring Boot》

WebJars is simply taking the concept of a JAR and applying it to client-side libraries or resources. For example, the jQuery library may be packaged as a JAR and made available to your Spring MVC application. 

    大概意思就是,WebJars借鉴了类似JAR的概念,把jQuery等js/css库打包成JAR,应用在服务端,方便在SpringMVC应用中使用,官网入口

    下面介绍如何使用和其原理。

一.SpringBoot中使用WebJars

    1.首先在pom.xml中引入需要的资源依赖:

    <!-- 引用Bootstrap -->
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>bootstrap</artifactId>
      <version>3.3.7-1</version>
    </dependency>

    <!-- 引用jQuery -->
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>jquery</artifactId>
      <version>3.1.1</version>
    </dependency>

    2.在html页面中引用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebJar Demo</title>
    <!-- 页面引用WebJar -->
    <link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css" />
    <script src="/webjars/jquery/3.1.1/jquery.min.js"></script>
    <script src="/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="container"><br/>
        <div class="alert alert-success">
            <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
            Hello, <strong>I am using webjars!</strong>
        </div>
    </div>
</body>
</html>

    3.demo的使用效果

    可以看到,index.html中的jQuery和Bootstrap资源确实被引用到了:

二.WebJars背后的原理

    起初的猜想是,直接把js等静态资源打包成JAR作为Resource加入到SpringBoot中。通过看JAR包结构和源码,发现确实是这样做的。

    1.WebJars的目录结构

    如上图所示,jQuery的相关文件被打包放在resources目录下特定名字webjars下面,可以记住这个路径,因为后面解析引用资源的时候,就是从该路径下访问获取资源的。

    2.SpringMVC中负责解析WebJars的资源-WebJarsResourceResolver

    WebJarsResourceResolver继承自AbstractResourceResolver,负责解析WebJars类型的资源,下面看看这个类中做了什么工作。

    WebJarsResourceResolver#resolveResourceInternal,解析URL中请求的资源,返回Resource:

    private final static String WEBJARS_LOCATION = "META-INF/resources/webjars/";// webjars的位置
    @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);// 寻找WebJars资源的路径
			if (webJarResourcePath != null) {
				return chain.resolveResource(request, webJarResourcePath, locations);
			}
		}
		return resolved;// 返回解析成功的资源
	}

    WebJarsResourceResolver#findWebJarResourcePath,找到WebJars的资源路径:

    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;
	}

 

    类似这种把JavaScript/css资源打包管理不是一个新概念,在 npm 和 bower 为web提供了相似的解决方案。

    发现自己不知道的东西还有好多,慢慢学吧~

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!