jsp自己主动编译机制

总的来说,Jasper的自己主动检測实现的机制比較简单,依靠某后台线程不断检測JSP文件与编译后的class文件的最后改动时间是否同样,若同样则觉得没有改动。但倘若不同则须要又一次编译。实际上因为在Tomcat部署的项目的JSP可能引入了其它页面。或者引入了其它jar包,并且这些资源都可能是远程的资源,所以实际处理会比較复杂,同样要遍历检測这些引入的不同资源是否做了改动。

 

上图是一个形象的示意图。我们知道Tomcat架构中有四个级别的容器,EngineHostContextWrapper,而jsp编译相应在wrapper级别。所以通过StandardWrapper不断运行任务去调用jasper,而jasper则不断检測校验本地和远程的各种资源,一旦发现须要又一次编译则进行重编译。往下看看详细怎样实现。

首先,须要一个后台运行线程,Tomcat中有专门的一条线程处理不同容器的background任务。想在不同的容器中运行某些后台任务仅仅需重写backgroundProcess方法就可以实现。因为JspServlet相应于Wrapper级别。所以要在StandardWrapper中重写backgroundProcess。它会调用实现了PeriodicEventListener接口的Servlet,当中JspServlet就实现了PeriodicEventListener接口,此接口仅仅有一个periodicEvent方法。详细的检測逻辑在此方法中实现就可以。

其次,检測推断又一次编译的根据是什么?又一次编译就是再次把jsp变成java再变成class,而触发这个动作的条件就是当我们改动了某个jsp文件后,或者某jsp文件引入的资源被改动后。都将触发又一次编译动作。所以最好的推断根据就是某jsp或资源的最后改动时间lastmodified属性。正常顺序是jsp经过编译后生成class文件,把此class文件的lastmodified属性设置成jsp文件的lastmodified,此时两个文件的lastmodified属性是同样的,当我们改了jsp文件保存后,jsplastmodified属性就被置为当前时间。此时通过推断两个文件的lastmodified属性决定是否又一次编译。

又一次编译后jspclass文件的lastmodified属性再次被置为同样。对于引入的资源。内存中维护了上次编译时引入资源的lastmodified属性,不断获取引入资源的lastmodified属性并与内存中相应的lastmodified属性进行比較,同样能够非常easy推断是否须要又一次编译。

最后,对于本地和远程资源分别怎样检測?对于本地资源来说。使用java.io.File类能够非常方便的实现对某JSP文件或其它文件的lastmodified属性读取。对于远程资源。比方jar包,为了方便处理jar包括的属性,使用java.net.URL能够非常方便操作,它包括了非常多协议,比如常见的jarfileftp等协议,使用相当方便,

URL includeUrl = new URL("jar:http://hostname/third.jar!/");

URLConnection iuc = includeUrl.openConnection();

long includeLastModified = ((JarURLConnection) iuc).getJarEntry().getTime();

仅仅需三步即完毕对远程jar包的读取且取出最后改动时间。当然URL还支持本地文件资源的读取,所以它是非常好的资源读取抽象对象。Tomcat中对引入资源的管理都是使用URL作为操作对象。

本小节探讨了Jasper自己主动检測机制的实现。自己主动检測机制给我们的开发带来了非常好的体验,我们不必自己改动了jsp后自己去运行编译操作。而是tomcat通过jasper帮我们定时检測编译操作。


点击订购作者《Tomcat内核设计剖析》



原文地址:https://www.cnblogs.com/lytwajue/p/7270523.html