Tomcat7 的源码分析---JSP的编译(一)

 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行号的对应关系.

 

 待续...

 

 

 

你可能感兴趣的:(tomcat)