?Tomcat7的JSP编译分析?
首先, 当一个jsp的请求发起后, 会由JspServlet进行接受(请求的流程会在后续文章里详细说明),? 会调用其service方法,? 解析获得该jsp的urlPath,? 并在参数中确定是否预编译模式.?
?之后, 调用serviceJspFile方法,?? 当该jsp是第一次请求时, 会新实例化JspServletWrapper对象,? 并将其加入JspRuntimeContext里.? 以后会直接从JspRuntimeContext中取JspServletWrapper对象, KEY值为jspUrl.
代码如下:
?
而后, 调用JspServletWrapper的service方法.?
?
?
?
?
以上就是jsp页面请求的流程. ?
觉得很奇怪吧, jsp的文件怎么就变成了servlet的class类了呢,????第一当然是将jsp变为java的源代码文件了.
?jsp怎么变成.java文件的呢?
在JspServletWrapper的service方法中调用ctxt.compile();?ctxt就是JspCompilationContext编译上下文
该方法主要做了以下几件事:
1.? 创建Compiler, 根据选项参数反射得到Compiler
???? tomcat7 提供使用Eclipse的JDT org.apache.jasper.compiler.JDTCompiler,?
???? 使用ANT的org.apache.jasper.compiler.AntCompiler
2. 移除旧的.java和.class文件.?
3.?将jsp文件转换生产.java
4.? 将生成的.java编译生成.class文件.
代码跟踪如下:
?
?
?
?以上代码来自tomcat源码类org.apache.jasper.compiler.Compiler
?
再跟进jspCompiler.compile();
?
?
?
?再次跟进String[] smap = generateJava();? 大家你一定很奇怪, 为什么结果是smap 呢?? 请大家耐心看下去吧.
这里就要简单介绍一下JSR-45
?? JSR-45(Debugging Support for Other Languages)为那些非 JAVA 语言写成,却需要编译成 JAVA 代码,运行在 JVM 中的程序,提供了一个进行调试的标准机制。也许字面的意思有点不好理解,什么算是非 JAVA 语言呢?其实 JSP 就是一个再好不过的例子,JSR-45 的样例就是一个 JSP。
JSP的调试一直依赖于具体应用服务器的实现,没有一个统一的模式,JSR-45 针对这种情况,提供了一个标准的模式。我们知道,JAVA 的调试中,主要根据行号作为标志,进行定位。但是 JSP 被编译为 JAVA 代码之后,JAVA 行号与 JSP 行号无法一一对应,怎样解决呢?
JSR-45 是这样规定的:JSP 被编译成 JAVA 代码时,同时生成一份 JSP 文件名和行号与 JAVA 行号之间的对应表(SMAP)。JVM 在接受到调试客户端请求后,可以根据这个对应表(SMAP),从 JSP 的行号转换到 JAVA 代码的行号;JVM 发出事件通知前, 也根据对应表(SMAP)进行转化,直接将 JSP 的文件名和行号通知调试客户端。
?
?当参数支持JSR-45则产生的smap就是jsp的行号与生产.java行号的对应关系.
?
?待续...
?
?
?