Tomcat:At least one JAR was scanned for TLDs yet contained no TLDs
启动Tomcat的时候,经常见到这样的BUG:
以前不知道怎么处理,怎么处理才是正确的,最近研究了点点Tomcat源码,也算知其一,知其二,不知其三四五六七了,下面先贴上解决方案:
解决方案:
catalina-home/conf/Catalina.properties中有这样一个属性:jarsToSkip
我们只需要将上面的属性改成:
再次启动Tomcat,查看容器启动时候效果:发现果然没有了之前的那个提示信息.
Why?
这个提示信息取消掉它出现,这是其一解决方案,其二呢?这样做会带来什么效果
可能JSP后端的动态渲染技术一定程度上会影响响应速度,如果jar包中没有tld,没有自定义tld等标签的话,我们可以放心使用上述方式。上述方式原理呢下面简单记录下:
解析上述tld代码方法位于:TldScanner#scanJars.
解析方式会按照
解释说明: 会扫描该项目所有加载到的jar包,包括jre/lib下的包,遍历每个jar检测是否有tld,而Catalina.properties配置中的两个jarsToSkip和jarsToScan作用呢?
check方法中tldSkipSet就是取的jarsToSkip的值,tldScanSet取的就是jarsToSkip的值;tldSkipSet通过正则表达式匹配当前check的jar包,所有的jar都会匹配上*.jar,但是tldScanSet就不一定可以匹配上,Catalina.properties中jarsToScan都是日志相关的jar包,无法和当前正在校验的jar包正则匹配上,所有这个jar包Tomcat不会做任何扫描处理。上述方法在一定程度上提高了Tomcat启动速度,如果在当前项目加载jar包特别多的情况下提升应该明显。
public boolean check(JarScanType jarScanType, String jarName) { Lock readLock = configurationLock.readLock(); readLock.lock(); try { final boolean defaultScan; final Set<String> toSkip; final Set<String> toScan; switch (jarScanType) { case TLD: { defaultScan = defaultTldScan; toSkip = tldSkipSet; toScan = tldScanSet; break; } case PLUGGABILITY: { defaultScan = defaultPluggabilityScan; toSkip = pluggabilitySkipSet; toScan = pluggabilityScanSet; break; } case OTHER: default: { defaultScan = true; toSkip = defaultSkipSet; toScan = defaultScanSet; } } if (defaultScan) { if (Matcher.matchName(toSkip, jarName)) { if (Matcher.matchName(toScan, jarName)) { return true; } else { return false; } } return true; } else { if (Matcher.matchName(toScan, jarName)) { if (Matcher.matchName(toSkip, jarName)) { return false; } else { return true; } } return false; } } finally { readLock.unlock(); } }
How?
假如当前情况下使用到的jar包中有使用tld文件,我们又不想全部扫描所有jar,并且不想看到上述信息At least one JAR 出现,解决方案是:
总结
通过修改Catalina.properties可以提高程序启动速度,如果有使用到tld文件,再配置比较合适。