现在我们接着上文章讨论来解决疑问2:如何计算缓存base文件名.
引入:
当我们在上文中获取了资源文件在Liferay服务器上的真实路径后,下面一步就是获取缓存文件,当然了,最重要的一步是获取其base文件名,从上文结果看,这是一串很长的数字,
这里就是来分析这段数字得到的奥秘。
分析:
这个base名是通过以下调用:
String cacheCommonFileName = getCacheFileName(request);获得的。
我们来看下getCacheFileName()方法:
protected String getCacheFileName(HttpServletRequest request) { CacheKeyGenerator cacheKeyGenerator = CacheKeyGeneratorUtil.getCacheKeyGenerator( DynamicCSSFilter.class.getName()); cacheKeyGenerator.append(request.getRequestURI()); String queryString = request.getQueryString(); if (queryString != null) { cacheKeyGenerator.append(sterilizeQueryString(queryString)); } String cacheKey = String.valueOf(cacheKeyGenerator.finish()); return _tempDir.concat(StringPool.SLASH).concat(cacheKey); }
从这里可以看出,
(1)它首先是在第3行通过CacheKeyGeneratorUtil工具类来获取一个cacheKey产生器。
这里可以看出,它是一个HashCodeCacheKeyGenerator的实例。
然后第5行吧请求的requestURI附加到cacheKeyGenerator后面,实际是附加到cacheKeyGenerator的keyBundler中:
接下来,第6行从Request中获取查询字符串,这其中包括了一些浏览器信息,theme的Id之类信息:
然后第9行对于查询字符串进行sterilize处理:
说白了,这步骤作用就是消除平台差异,它吧所有查询字符串中的"/"和"\\"都替换为下划线"_":
最后吧sterilize后的字符串也拼接在cacheKeyGenerator的keyBundler后面。
最后第11行,它调用cacheKeyGenerator的finish()方法产生一个hash值,它委托HashcodeCacheKeyGenerator的getCacheKey()完成的,基本算法也是素数和一些hashCode的简单运算,不过基本可以保证唯一性:
最后,它12行,它吧这个产生的哈希数串和临时文件目录拼接在一起产生最终的缓存文件的base文件。
其中_tempDir这个值是SystemProperties中读取"SystemProperties.TMP_DIR"读来的,然后拼接/liferay/css字符串。
查阅后发现SystemProperties.TMP_DIR为字符串"java.io.tmpdir":
它会去先从system.properties和system-ext.properties中找java.io.tmpdir对应的值,如果没有则从环境中找。因为我们在启动liferay中配置了java.io.tmpdir,
深究下去其实对应的脚本在catalina.sh中:
这里可以看出它动态的传递了-Djava.io.tmpdir 为$CATALINA_TMPDIR
所以很快的就找到了结果是/app/Liferay/RI/liferay-portal-6.1.0-ce-ga1/tomcat-7.0.23/temp 目录。
这也和调试的结果匹配.
所以综上所述,我们获取的第12行的_tempDir就是上面的app/Liferay/RI/liferay-portal-6.1.0-ce-ga1/tomcat-7.0.23/temp 再拼接 /liferay/css/portal,然后再在后面拼接上我们的Hash值,这就形成了最终的缓存文件的base文件名。
所以最终结果是:
结论:
(1)缓存文件的文件名是一个hash值,它是由文件名,浏览器类型,themeId共同参与hash运算得到了。基本保证唯一性。
(2)缓存的文件的位置来自于动态的系统参数java.io.tmpdir,这个参数是由liferay启动时候提供的,在tomcat的temp目录。