WEB容器JSP页面的访问请求时,它将把该访问请求交给JSP引擎去处理。Tomcat中的JSP引擎就是一个Servlet程序,它负责解释和执行JSP页面。
第一次请求:当服务器上的一个JSP页面被第一次请求执行时,服务器上的JSP引擎首先将JSP页面文件转译成一个.java文件,也就是servlet源程序,接着再把这个Servlet源程序编译这个java文件生成.class的字节码文件(对于Tomcat,生成的class文件默认情况下存放在<Tomcat>/work目录下),然后执行字节码文件响应客户端的请求。
再次请求:JSP引擎将直接执行字节码文件来响应客户。
即:
①客户端发出请求。
②Web容器将JSP转译成Servlet源代码。
③Web容器将产生的源代码进行编译。
④Web容器加载编译后的代码并执行。
⑤把执行结果响应至客户端。
在执行 JSP 网页时,通常可分为两个时期:转译时期(TranslationTime)和请求时期(Request Time)
- 转译时期:JSP网页转译成Servlet类。
- 请求时期:Servlet类执行后,响应结果至客户端。
注:将JSP网页转译为 Servlet源代码(.java),此段称为转译时期(Translation time);将Servlet源代码(.java)编译成 Servlet 类(.class),此段称为编译时期(Compilation time)。
接下来我们看每一步的具体实现:
①客户端请求jsp文件,web服务器(tomcat等)根据jsp文件生成java文件:
②java文件生成对应的class字节码文件,字节码文件是可以通过class loader加载进虚拟机的:
③ web容器加载class字节码文件:
④ web容器通过反射等手段建立hello_jsp实例:
⑤ 调用对应的jspInit来进行实例初始化:
⑥ 调用_jspservice,响应用户请求:
⑦ 调用jspDestroy销毁jsp_hello实例:
因为jsp_hello继承自HttpJspBase,HttpJspBase又继承自Servlet,所以jsp_hello是个servlet,其生命周期可以交由web服务器控制。
举实例来解释:
用户在浏览器地址栏上输入http://localhost:8080/dage/index.jsp,web服务器判断用户请求的资源是dage应用中的index.jsp页面,web服务器在dage应用中找到index.jsp,启动JSP翻译引擎,将index.jsp翻译成index_jsp.java文件,并且将index_jsp.java文件编译生成index_jsp.class字节码文件,将其存储在Tomcat服务器work目录中。index_jsp.class类继承了HttpJspBase,HttpJspBase继承了HttpServlet,所以JSP本质上就是Servlet,和Servlet完全相同。只有用户第一次访问这个JSP或者JSP页面被修改了,才会重新翻译。JSP有三个阶段:翻译(一次),编译(一次),运行(多次)。JSP更改,不需要重启服务器,也不需要重新部署项目。
Jsp和Servlet本质上没有区别,但是JSP和Servlet它们的主要职责是有区别的:JSP主要是提取数据做页面展示,而Servlet主要完成业务逻辑处理以及资源跳转。Servlet是Controller(控制层),JSP是View(展示层)。项目开发中只使用JSP也可以完成开发,因为JSP最终也是一个java类,可以在JSP中编写JDBC等其他程序,但是这样做就违背了设计原则,我们要把的主要职责凸显出来,它的弱点我们还是要尽量避让的。(JSP和Servlet都是单实例多线程的环境下运行的,JSP和Servlet中出现的实例变量、静态变量都会存在线程安全问题。)
参考:
http://blog.youkuaiyun.com/fengdongkun/article/details/8159381
http://blog.youkuaiyun.com/hanxuemin12345/article/details/23831645