我们知道在开发工程的时候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文件。
一个class只能由classloader加载一次,如果再次加载将会导致类冲突。但是JVM表示一个类是否是同一个类有两个条件。
如果是同一个ClassLoader的不同的实例加载同一个类,那么就可以实现热更新部署了。
下面具体分析一下这个过程:
JSP文件请求时序图
private Map<String, JspServletWrapper> jsps = new ConcurrentHashMap<String, JspServletWrapper>();
2.调用JspServletWrapper.service() 方法
JspServlet 模式是development模式,可以通过web.xml中把development模式关闭 development=false
判断上次请求的时候+4秒的时候,是否大于当前时间,也就是说,距离上次检查文件更新时间是否有4秒的时间,如果小于4秒则不进行检查文件是否更新,不重新加载编译jsp文件。
根据上次最后修改时间,和这次获得的文件最后修改时候做对比,来判断文件是否更新过。
ctxt.getOptions().getModificationTestInterval() 默认的时间为4秒
在JspServlet.serviceJspFile() 方法 获取Jsp对应的Servlet实例后,然后调用Servlet的Service方法。