6.1.3 JSP的运行原理

优质
小牛编辑
137浏览
2023-12-01

Web容器在处理请求路径时都会从web.xml文件中寻找和该路径匹配的Web资源,如果找到该资源,就会使用相应的方法来处理,否则,就会将该请求交由DefaultServlet类来处理,该类是一个Servlet类,负责处理所有未在web.xml文件中配置的Web资源,如HTML页面等。

当Web容器接收到客户端发送的.jsp请求后,就会在web.xml文件中查询是否有与该请求匹配的路径。web.xml文件有两种,一种是当前Web应用程序中的web.xml,在该web.xml文件中的配置只对当前Web应用程序有效。另外一种就是Tomcat提供的系统web.xml,该文件位于<Tomcat安装目录\conf目录中。为了匹配整个Web容器中的JSP程序,必须在该文件中配置JSP映射路径。

实际上,配置JSP映射路径的工作并不需要开发人员来做,在Tomcat已经在web.xml文件中预先配置JSP映射路径,代码如下:

<servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    ... ...
</servlet>
... ...
<servlet-mapping>
    <servlet-name>jsp</servlet-name>
    <url-pattern>*.jsp</url-pattern>
</servlet-mapping>

从上面的配置代码可以看出,JSP的映射路径是“*.jsp”,因此,所有扩展名为.jsp的Web资源都会匹配该映射路径,并将配置该映射路径的Web请求交由org.apache.jasper.servlet.JspServlet类处理,该类是一个JSP引擎。该引擎负责翻译JSP页面,并将其转换成Servlet。如果在JSP页面中有错误,JSP引擎会停止翻译,并将出错信息发送到客户端。

Tomcat6.x把JSP转换成Servlet后,将生成的Servlet源文件和.class文件放到了<Tomcat安装目录>\ work\Catalina\localhost目录中。文件名的命名规则是xxxx_jsp,其中xxxx表示JSP文件名。如6.1.2节中的simple.jsp文件被翻译后,生成的Servlet源文件和.class文件分别为simple_jsp.java和simple_jsp.class,这两个文件可以在<Tomcat安装目录>\work\Catalina\localhost\ myjsp\org\apache\jsp目录中找到,如图6.2所示。

02

图6.2 由JSP生成的Servlet被保存的位置

将JSP页面翻译成Servlet的一个明显的好处就是JSP引擎只需要负责JSP页面的翻译,而运行JSP页面的工作仍由Servlet引擎来完成。这样有利于Servlet引擎技术的复用。在JSP规范中并没有规定如何翻译JSP页面,因此,不同的JSP引擎可能翻译的结果不同,但运行的结果是完全一样的。

在访问JSP页面时,只是在第一次才被编译成Servlet,当再次访问该JSP页面时,Web容器会直接调用由该JSP页面生成的Servlet。但如果这个JSP页面被修改了,Web容器就会再次将这个JSP页面翻译成Servlet。从这一点可以看出,在每次访问JSP页面时,Web容器都会检察该JSP页面的修改时间是否比Servlet的生成时间晚,如果JSP页面的修改时间更晚,那么Web容器就会调用JSP引擎来翻译该JSP页面,否则,Web容器会直接通过Servlet引擎来调用由这个JSP页面翻译生成的Servlet。

虽然上面所述的JSP页面的运行过程非常适合于开发阶段来调试JSP程序,但当程序正式发布时,一般情况下,JSP页面是不会变化的(除非升级程序),这就会显得每次在访问JSP页面时都检查JSP和Servlet的更新时间有些多余,因此,可以通过JspServlet类的development参数将检测更新时间的功能关闭。配置代码如下:

<servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <!--  配置development参数  -->
    <init-param>
        <param-name>development</param-name>
        <param-value>false</param-value>
    </init-param>
    ... ...
</servlet>

如果采用了上面的代码来配置JspServlet,Web容器只有在第一次访问JSP页面时调用JSP引擎将JSP页面翻译成Servlet,当再次访问该JSP页面时,Web容器就会直接通过Servlet引擎调用由该JSP页面生成的Servlet。