深入理解JSP(一)

欢迎点击「算法与编程之美」↑关注我们!

本文首发于微信公众号:"算法与编程之美",欢迎关注,及时了解更多此系列文章。

在Java Web的开发过程中,可能有过这样的疑问,Tomcat是一个Servlet运行环境(容器),所有经过Tomcat的请求都是由一个Servlet来处理的。Servlet是一个Java类,可是JSP不是,那JSP又是怎么在Tomcat里面运行的呢?

事实上,JSP是Servlet的一种特殊形式,每个JSP页面就是一个Servlet实例——JSP页面由系统编译成Servlet,Servlet再负责响应用户请求。JSP其实也是Servlet的一种简化,使用JSP时,其实还是使用Servlet,因为Web应用中的每个JSP页面都会由Servlet容器生成对应的Servlet。

根据上面的分析,我们又有一个疑问:为什么说JSP就是一个Servlet,是根据什么来判定的呢?

1 为什么说JSP是Servlet

首先在IntelljIdea里面编写一个简单的test.jsp页面

640?wx_fmt=png

当启动Tomcat后,可以在Tomcat的\work\Catalina\localhost\ROOT\org\apache\jsp目录下找到如下文件:

640?wx_fmt=png

这两个文件便是test.jsp经过系统编译生成的对应的 .java文件和 .class文件,打开test_jsp.java文件

640?wx_fmt=png

可以看到,这个test_jsp类继承了HttpJspBase,并且实现了org.apache.jasper.runtime.JspSourceDependent与org.apache.jasper.runtime.JspSourceImports这两个接口,我们知道判定一个类是Servlet的方法是看这个类是否间接或直接实现了Servlet接口,所以我们要看test_jsp这个类是否间接或直接实现了该接口,这里它并没有直接实现Servlet接口,所以现在我们还不能从这里看出test_jsp这个类就是一个Servlet,我们便可以猜想,会不会是HttpJspBase这个类实现了此接口呢。

于是我们进一步分析HttpJspBase这个类的继承结构。

 我们去查看HttpJspBase类的源码

640?wx_fmt=png

从上面就可以看出,该类继承了HttpServlet,我们之前便知道HttpServlet间接实现了Servlet接口。如果不知道的我们可以在IntelljIdea里面将鼠标定位在HttpJspBase上面按住ctrl+alt+u查看他的继承关系图:

640?wx_fmt=png

图 1-1 HttpJspBase继承关系

到这里我们便能清晰的知道为什么说JSP是一个Servlet了。

2  Tomcat处理JSP文件流程分析

经过上面的分析,我们已经知道了JSP就是一个Servlet。那JSP又是如何转换成Servlet的呢?每一个Servlet都需要在web.xml 文件进行配置,这样浏览器才能访问得到这个Servlet。可是现在这个test.jsp并没有在我们项目的web.xml里面做任何配置,那浏览器是怎么访问到jsp页面的呢?回答这个问题之前我们先来了解一下Tomcat如何响应静态资源。

DefaultServlet介绍

本质上讲,Tomcat对于所有的静态资源会做统一处理,也就是在所有你没有配置URL匹配的地方,Tomcat这个全局统一处理的配置就开始接管工作了。在Tomcat的conf目录下面可以看到有一个web.xml文件,打开后你会发现这样的说明:

640?wx_fmt=png

在向下你会看到关于这个全局处理的Servlet声明,如下图

640?wx_fmt=png

这个DefaultServlet的servlet-mapping是这样配置的:

640?wx_fmt=png

到这里不禁有人会问,既然url-pattern 配置的是  / ,那不就应该可以响应所有的请求了吗?其实上面的图中已经给出了解释,事实上这是匹配所有你没有定义的Servlet-mapping的请求。之所以自己定义的Servlet可以优先生效,则是因为Tomcat内的Servlet的mapping配置是严格按照声明顺序初始化,并按此顺序响应请求,一层层按此比对,有一个可以响应请求,就用其处理。有相关疑问可以参考一下博文:

http://k1121.iteye.com/blog/1564241

综上所述,所有经过Tomcat的请求都是由一个servlet来处理的,如果一个请求没有匹配到任何应用指定的Servlet,那么就会流到Tomcat的默认的servlet来,这个Servlet名字叫做DefaultServlet,DefaultServlet是配置在/conf/web.xml里面。

JspServlet介绍

上一节我们了解到Tomcat使用DefaultServlet处理所有的静态资源。这一节我们来看一个jsp请求又是怎么被响应的。同DefaultServlet类似,jsp的处理也不需要我们单独配置,而是在/conf/web.xml中做为全局配置存在。其对应的处理类为JspServlet,用于处理所有的jsp请求。同样我们打开/conf/web.xml,可以看到以下代码与注释:

640?wx_fmt=png

640?wx_fmt=png

  

通过看注释我们便对该配置的作用一目了然,往下看我们会看到JspServlet的mapping配置,其url-pattern为*.jsp和*.jspx。所以它可以拦截所有的jsp请求并作出相应的反应。

640?wx_fmt=png

到这里我们便知道了为什么浏览器在我们自己没对jsp文件做任何配置的情况下依旧能访问的原因。

JSP转化为Servlet

在文章开头我们知道当Tomcat启动过后,一个xxx.jsp文件会在\org\apache\jsp目录下生成相应的xxx_jsp.java文件与xxx_jsp.class文件,打开我们之前已经生成的test_jsp.java 文件,这个文件结构如下图所示:

640?wx_fmt=png

640?wx_fmt=png

 

主要的转换动作是在方法_japService()中实现的,如下的Servlet类的代码截图可以看出,其中插入了session、application等对象的初始化,这几个对象都是通过页面级别的对象pageContext获取到的。

 

640?wx_fmt=png

页面中的java代码去哪儿了呢,转换过程中,HTML页面元素内容可以理解为通过out.write()直接输出给前端页面,java代码(<%%>包含的内容)直接去掉<%%>写到类中执行。部分代码截图如下:

640?wx_fmt=png

图中红色方框内的内容就是我们在jsp页面中<% %>中的Java代码。在转化中直接去除<% %>后放到类代码中,而其余的可以理解为直接out.write()输出给前端页面。至此我们便解释了Tomcat如何处理jsp文件的问题。

总结

本文对JSP的运行原理进行了详细的分析,可以得出下面的流程图:

 

640?wx_fmt=png

图3-1 jsp页面工作原理图

根据上面的JSP页面工作原理图,可以得到如下结论:

    — JSP文件必须在JSP服务器内运行。

    — JSP文件必须生成Servlet才能执行。

JSP和Servlet会有如下转换:

    - JSP页面的静态内容、JSP脚本都会转换成Servlet的xxxService()方法,类似于自行创建Servlet时service()方法。

    - JSP声明部分,转换成Servlet的成员部分。所有JSP声明部分可以使用private,protected,public,static等修饰符,其他地方则不行。

    - JSP的输出表达式(<%= ..%>部分),输出表达式会转换成Servlet的xxxService()方法里的输出语句。

    - 九个内置对象要么是xxxService()方法的形参,要么是该方法的局部变量,所以九个内置对象只能在JSP脚本和输出表达式中使用。


更多精彩文章:

 where2go 团队


   

微信号:算法与编程之美          

640?wx_fmt=jpeg

长按识别二维码关注我们!

温馨提示:点击页面右下角“写留言”发表评论,期待您的参与!期待您的转发!

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:猿与汪的秘密 设计师:我叫白小胖 返回首页

打赏作者

算法与编程之美

欢迎关注『算法与编程之美』

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值