遇到的问题
对jsp页面进行了一些修改,部署到服务器的jsp页面不起作用。发现并不管用,而且文件的修改时间一直没变。 甚是奇怪。后面touch一下文件就好了。后面就了解了下tomcat的热部署。如下:
我们知道在开发工程的时候jsp文件是即修改即生效的,由于比较好奇就研究了一下tomcat对于jsp热部署的实现原理,总结沉淀一下吧。Tomcat jsp热部署的实现原理大体是这样的,每个JSP页面从上次访问到下次访问总是有默认几秒的缓存时间的,也就说并不是严格的即修改即生效,tocmat7默认是有4秒的缓存延迟的。这个默认的缓存延迟是在类EmbeddedServletOptions的private intmodificationTestInterval = 4;这个属性定义的。如果过了4秒缓存时间即失效,这个时候tomcat就会读取jsp的modified时间戳和work目录下编译好的class文件的modified的时间戳作对比。如果相等则class文件没有过期,则不会重新编译jsp文件,如果过期了则重新将jsp编译成java,并进一步编译成class。同时调用JasperLoader来重新加载这个有jsp编译好的class文件。下面具体分析一下这个过程:
大体的类通信时序图是这样的:
其中上文说的时间戳的校验逻辑主要封装在JDTCompiler的isOutDated方法里面,这个方法的主要源代码如下:
其中第一个红框就是涉及到的N秒缓存逻辑,如果缓存没有失效,则不会重新加载,这个ctxt.getOptions()获取到的其实是EmbeddedServletOptions类,这个类默认定义的时间间隔是:
在实验的时候我比较好奇就收到把这个值改为了40,果然jsp并没有及时生效,而是过了40秒之后才生效。第二个红框检测的是获取work目录下的class文件的对象。第三个红框就是比较class文件的时间戳和JSP文件的时间戳,如果不相等则重新编译加载(上面时序图的流程)。这个就是jsp的热部署流程!
(原文链接:http://www.linuxidc.com/Linux/2013-05/83816.htm)
一下是涉及到tomcat work目录的另一篇文章。
jsp,tomcat的工作原理是当浏览器访问某个jsp页面时,tomcat会在work目录里把这个jsp页面转换成.java文件,比如将index.jsp转换为index_jsp.java文件,而后编译为index_jsp.class文件,最后tomcat容器通过ClassLoader类把这个index_jsp.class类装载入内存,进行响应客户端的工作。
tomcat会定时稍描容器内的jsp文件,读取每个文件的属性,当发现某个jsp文件发生改变时(文件的最后修改时间与上次稍描时不相同时),tomcat会重新转换、编译这个jsp文件。但是tomcat的稍描是定时的不是实时的,这也正是为什么jsp文件修改后需要几分钟的时间来等修改过的jsp生效。当然为了即刻生效,很多老前辈都会建议在修改jsp页面后立即清除work目录里的文件。
另外,tomcat容器中,对转换后的java文件(比如:index_jsp.java)的编译最大只支持64k,所以在其他容器中的jsp移植到tomcat容器中时会遇到大jsp文件会发生无法编译的情况,所以建议把jsp中的业务逻辑写入单独的类,在jsp中通过调用这个类的静态方法来执行,并将jsp页面中的js提取出来放到单独的js文件内。