前面几篇文章,我们研究过了几个servlet:
DefaultServlet是专门处理静态资源的,如png,文本,html页面这些东西;
基于http规范之上的一个WebDav规范,这个规范是在http基础又增加了几个方法,如在服务器上copy资源,move资源,针对于服务器上的目录资源的操作,甚至可以对服务器上的资源加lock,加一些属性,这些Tomcat也都基本实现了;
这篇文章我们继续研究一个非常重要的Servlet,JSPServlet,看看其是怎么实现的jsp编译,加载,并处理的;
index_jsp.java
JSP其实是JAVA EE规范中的一个,好处很多,主要是有一个规范去引导,并且从规范的级别中提供了n多种的标签,可以做出很炫的效果出来(这句话有点牵强,现在很多js框架比这个要好,呵呵);
缺点也是显而易见的,JSP在服务器端编译为servlet,然后通过类加载器去加载这个Servlet,最后执行这个xxx_jsp(编译的servlet),整个过程都是在服务器端完成的,客户端没有任何的帮助,对比js这种客户端的技术,服务器向客户端发送的数据会非常大,占据网络IO,增加了服务器的压力;
这也就是JSP被诟病的原因,在JSP刚出来的时候,JSP能完美的解决了CGI那种脚本画页面的难题,以一个页面的形态就可以和html的一块混合服务器端和客户端的逻辑,但现在,js主导的客户端技术已经将其抛在后面了,目前只有企业级的应用会用到jsp;
我们来看看一个简单的index.jsp编译成的Servlet的继承关系:
首先,index_jsp是一个servlet,其和普通的servlet没有任何的区别,
其次,jsp的生命周期,编译成的servlet,有几个回调函数,_jspinit,_jspDestory,_jspService这几个方法实际上就是从servlet的这几个对应方法中进行的回调,只不过JSpServlet单独给起了一个名字而已;
除此之外,它还有一些jsp相关的环境注入,如el资源,jsp编译的时候需要依赖的一些类,包:
这些环境是Tomcat自身就建设好的,从jsp页面编译到java文件的过程中,将其写入到jsp的servlet中;
我们在学习JSP的时候,经常在各种书中都说到8大对象,实际上在jsp编译成servlet的过程中,将这8个对象注入到service方法中:
pageContext,页面上下文,在页面中放一些东西
session,其实就是在Servlet中写的httpSession
Application,就是ServletContext
config,就是ServletConfig
out,是写出到页面的JspWriter,这个是JSP单独封装的,实际就是向页面刷输出流
request,是httprequest,
response,是httpresponse,
page是页面对象,很多人不太理解,看过源码就知道,大白话这个page就是当前的index_jsp的实例,你可以在页面中直接获取这个jsp编译成的servlet实例,进行一些操作(实际上没什么用);
对于很多书中写的还有一个exception对象,在Tomcat8.0之后的版本中没有看见,目前就是8个内置对象;
index.jsp页面中就有一个yuantong的字符,_jspService方法中事先也很简单,jsp工厂负责从request和response中创建PageContext上下文,然后通过从PageContext获得JspWriter对象,通过JspWriter将html流刷到客户端,最后再关闭jsp工厂:
整个流程一气呵成,再复杂的页面,主要就是通过JspWriter刷流的过程比较复杂而已,这个的框架还是不变的;
下一篇文章,关注整个JSPServlet在Tomcat中是如何实现的;