Tomcat之Jasper

Jasper简介

对于基于Jsp的web应用来说,我们可以直接在Jsp页面中编写Java代码,添加第三方的标签库,以及使用EL表达式。但是无论经过何种形式的处理,最终输出到客户端的都是标准的HTML页面(包含js,css..),并不包含任何的java相关的语法。也就是说,我们可以把Jsp看做是一种运行在服务端的脚本。那么服务器是如何将Jsp页面转换为HTML页面的呢?

Jasper模块是 Tomcat的Jsp核心引擎,我们知道jsp本质上是一个servlet。 Tomcat使用 jasper对Jsp语法进行解析,生成servlet并生成class字节码,用户在进行访问jsp时,会访问servlet,最终将访问的结果直接响应在浏览器端。另外,在运行的时候, Jasper还会检测Jsp文件是否修改,如果修改,则会重新编译Jsp文件。

JSP编译方式

运行时编译

Tomcat并不会在启动web应用的时候自动编译jsp文件,而是在客户端第一次请求时,才编译需要访问的jsp文件。

编译过程

Tomcat在默认的web.xml中配置了一个org.apache.jasper.servlet.JspServlet,用于处理所有的.jsp或.jspx结尾的请求,该servlet实现的即是运行时编译的入口。

    <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
            <param-name>fork</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>xpoweredBy</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
        <url-pattern>*.jspx</url-pattern>
    </servlet-mapping>

 JspServlet处理流程图:

编译结果

  • 如果在tomcat/conf/web.xml中配置了参数scratchdir,则编译后的结果,就会存储在该目录下。
<init-param>
    <param-name>scratchdir</param-name>
    <param-value>D:/tem/jsp/</param-name>
</init-param>
  •  如果没有配置该选项,则会将编译后的结果,存储在tomcat安装目录下的work/Catalina/localhost/Context。假设项目名称为jsp_demo_01,默认的目录为:work/Catalina/localhost/jsp_demo_01
  • 如果使用的是idea开发工具集成tomcat访问web工程中的jsp,编译后的结果,存放在:
C:\Users\Administartor\.IntelliJIdea2019.1\system\tomcat\_project_tomcat\work\Catalina\localhost\jsp_demo_01_war_exploder\org\apache\jsp

预编译

除了运行时编译,我们还可以直接在web应用启动时,一次性将web应用中的所有的Jsp页面一次性编译完成。在这种情况下,Web应用运行过程中,便可以不必再进行实时编译,而是直接调用Jsp页面对应的sexvlet完成请求处理,从而提升系统性能。

Tomcat提供了一个shell程序Jspc,用于支持Jsp预编译,而且在 Tomcat的安装目录下提供了一个catalina- tasks.xml文件声明了

Tomcat支持的Ant任务,因此,我们很容易使用ant来执行Jsp预编译。(要想使用这种方式,必须得确保在此之前已经下载并安装了

(Apache Ant)

JSP编译原理

  • 其类名为 index_jsp,继承自org.apache.Jasper.runtime.HttpjspBase,该类是HttpServlet的子类,所以jsp本质就是一个servlet。
  • 通过属性_ jspx_dependants保存了当前Jsp页面依赖的资源,包含引入的外部的Jsp页面、导入的标签、标签所在的jar包等,便于后续处理过程中使用(如重新编译检测,因此它以Map形式保存了每个资源的上次修改时间)。
  • 通过属性_jsp_import_packages存放导入的java包,默认导入javax.servlet,javax.servlet.http,Javax.servletJsp
  • 通过属性 _jspx_imports_classes存放导入的类,通过 import指令导入的 Dateformat、 SimpleDateFormat、Date都会包含在该集合中。 _jspx_imports_packages和 _jspx_imports_classes属性主要用于配置EL引擎上下文。
  • 请求处理由方法_ JspService完成,而在父类HttpJspBase中的 service方法通过模板方法模式,调用了子类的_jspService方法
  • _jspService方法中定义了几个重要的局部变量: page、context、 Session、application、 config、out、page。由于整个页面的输出有 Jspservice方法完成,因此这些变量和参数会对整个Jsp页面生效。这也是我们为什么可以在JsP页面使用这些变量的原因
  • 指定文档类型的指令(page)最终转换为response.setContentType()方法调用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章