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

上图是一个形象的示意图。我们知道Tomcat架构中有四个级别的容器,Engine、Host、Context和Wrapper,而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文件保存后,jsp的lastmodified属性就被置为当前时间。此时通过推断两个文件的lastmodified属性决定是否又一次编译。

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

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

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内核设计剖析》

jsp自己主动编译机制的更多相关文章

  1. jsp自动编译机制

    总的来说,Jasper的自动检测实现的机制比较简单,依靠某后台线程不断检测JSP文件与编译后的class文件的最后修改时间是否相同,若相同则认为没有改动,但倘若不同则需要重新编译.实际上由于在Tomc ...

  2. 浅谈java编译机制和运行机制

    源文件和字节码的组成方式 源文件: 拓展名后跟java的文件即java的源文件. Java 源码编译由以下三个过程组成: 1.分析和输入到符号表 2.注解处理 3.语义分析和生成class文件 流程图 ...

  3. 编译时和运行时、OC中对象的动态编译机制

    编译时 编译时顾名思义就是正在编译的时候.那啥叫编译呢?就是编译器帮你把源代码翻译成机器能识别的代码.(当然只是一般意义上这么说,实际上可能只是翻译成某个中间状态的语言.比如Java只有JVM识别的字 ...

  4. JSP中的编译指令和动作指令的区别

    JSP中的编译指令和动作指令的区别 1.编译指令是通知Servlet引擎的处理消息,而动作指令只是运行时的脚本动作 2.编译指令是在将JSP编译成Servlet时起作用,而动作指令可替换成JSP脚本, ...

  5. angular编译机制

    转载https://segmentfault.com/a/1190000011562077 Angular编译机制 前言 http://www.cnblogs.com/ztwBlog/p/620975 ...

  6. Ant自己主动编译打包&公布 android项目

    Eclipse用起来尽管方便,可是编译打包android项目还是比較慢,尤其将应用打包公布到各个渠道时,用Eclipse手动打包各种渠道包就有点不切实际了,这时候我们用到Ant帮我们自己主动编译打包了 ...

  7. JSP中的编译指令和动作指令的差别

    JSP中的编译指令和动作指令的差别 1.编译指令是通知Servlet引擎的处理消息.而动作指令仅仅是执行时的脚本动作 2.编译指令是在将JSP编译成Servlet时起作用,而动作指令可替换成JSP脚本 ...

  8. 【Android】Eclipse自己主动编译NDK/JNI的三种方法

    [Android]Eclipse自己主动编译NDK/JNI的三种方法 SkySeraph Sep. 18th  2014 Email:skyseraph00@163.com 一.Eclipse关联cy ...

  9. OC的动态继承编译机制

    [问]为什么OC不能sizeof一个对象的大小或一个类的大小?和类结构相近的结构体却能够. [再问]为什么OC不能将对象声明到静态空间,如栈中?和类结构相近的结构体却能够. [答]由于OC的动态继承编 ...

随机推荐

  1. Node.js+MySQL管理工作的详细信息所遇到的问题

    问题陈述: Error: ER_TRUNCATED_WRONG_VALUE_FOR_FIELD: Incorrect string value: '\xE8\xB4\xAD\xE7\x89\xA9' ...

  2. Go -- php 中的pack("H*", $string) 转换成go

    pack("H*", $string) 转化成这样: //16进制字符串转[]byte func HexToByte(hex string) []byte { length := ...

  3. PHP之is_a()函数执行代码之总结

    今天看到云舒在群里贴的漏洞公告,原始的文章在 http://www.byte.nl/blog/2011/09/23/security-bug-in-is_a-function-in-php-5-3-7 ...

  4. MFC【17-2】线程和线程同步化

    17-2线程同步 Windows支持4中类型的同步对象,可以用过来同步由并发运行的线程执行的操作: 临界区 互斥量 事件 信号量 MFC在名为CCriticalSection\CMutex\CEven ...

  5. http://www.blogjava.net/crespochen/archive/2011/04/22/348819.html

    http://blog.csdn.net/supersky07/article/details/7407523 http://blog.csdn.net/cuker919/article/detail ...

  6. 《Linux操作系统编译构建指南》

    在线阅读地址:http://www.doc88.com/p-5126905896771.html Linux编译构建定制qq群: 521902245 文件夹...0 前言...3 第零章 绪论...5 ...

  7. ElasticSearch reindex报错:the final mapping would have more than 1 type

    ElasticSearch reindex报错:the final mapping would have more than 1 type 学习了:https://blog.csdn.net/qq_2 ...

  8. 有趣的Java之调皮的浮点数

    **当你在写一个电商网站的时候,你可能会给你的商品标价1.99,10.9这样的价格来吸引顾客.我应该用浮点数float/double来储存它们,当我的顾客购买商品的时候,从他们的账户里扣费,使用整型是 ...

  9. Android RxJava/RxAndroid结合Retrofit使用

    概述 RxJava是一个在 Java VM 上使用可观測的序列来组成异步的.基于事件的程序的库.更重要的是:使用RxJava在代码逻辑上会非常简洁明了,尤其是在复杂的逻辑上.告别迷之缩进. RxAnd ...

  10. redis常用配置参数详解

    Redis 支持很多的参数,但都有默认值. daemonize 默认情况下, redis 不是在后台运行的,如果需要在后台运行,把该项的值更改为 yes. pidfile 当 Redis 在后台运行的 ...