通过之前的学习,我们已经对Servlet有所了解,现在我们先来学习JSP,当能使用JSP进行友好的页面显示之后,再回去学习Servlet的其他高级特性会将整个学习很好的融入进来。

  JSP,即Java Server Pages,和Servlet一样,都是SUN公司定义的一种用于开发动态WEB资源的技术。

  为什么说JSP也是动态web开发的一项技术呢?这是因为写JSP虽然像是在写HTML,但是JSP允许在页面中嵌套Java代码,或者利用某个标签表示Java代码(EL与jstl)。这就使得我们在写JSP时能够获取请求对象Request和响应对象Response等这样的web开发常用对象,实现与浏览器的交互。其实JSP就是一种Servlet,为什么这么说,后面会谈到。

  我们先来写一个JSP,具体的原理我们先不用管,只先看效果:

  在MyEclipse中创建一个【JSPLearning】的web项目,在【WebRoot】下创建一个“1.jsp”

  

  可以看到头部分内容是比较多的,这原因其实和Servlet一样,都是由于MyEclipse创建JSP也是依靠模板来创建的(当然我们可以改模板代码使我们的JSP更加简洁):

  

我们在<body>标签中输入如下代码:

  <body>
<%
Date date = new Date();
out.write(date.toLocaleString());
%>
</body>

然后通过浏览器来浏览我们这个JSP,就可以看到当前时间:

  

  写JSP的一大便捷之处在于如果该JSP不在【WEB-INF】文件下,那么每次修改代码只需保存即可在浏览器上观察,不需要像Servlet一样要重新部署。

我们看到上面JSP例子,不仅包含了HTML标签语言,同时融入了JAVA代码。

  我们知道浏览器在访问JSP时能将JSP解释并将内容显示在浏览器上,JSP中有HTML的部分不用说,这浏览器肯定知道,但是我们上面的例子中JSP内还有Java部分,那么浏览器又不是JVM,怎么能执行这部分代码呢?

  这就要说明一点了,其实浏览器访问JSP只是一个假象,真正的还是去访问Servlet。只是Servlet将JSP文件进行了翻译转换,即将JSP又变成了Servlet,然后输出给浏览器的就是这翻译转换后的Servlet。

  那翻译转换后的Servlet在哪里呢?我们并没有看到在自己的web工程中有多出来的Servlet。其实这个Servlet就在Tomcat的【work】目录下。【work】目录是Tomcat的工作目录,也是Tomcat将JSP转换为class文件的工作目录。转换的工作原理是当浏览器访问某个JSP页面时,Tomcat会在【work】目录下把这个JSP页面转换成 .java文件(例如index.jsp会被转换成index_jsp.java,如果以数字开头,最前面还会有一下划线,例如: _1_jsp.java),而后编译为 .class文件,最后Tomcat容器通过ClassLoader类将这个转换后的 .class类装载进内存,响应客户端的工作。

  当第一次有人来访问时,Tomcat需要将JSP转换成Servlet,访问可能会比较慢,但是一旦编译成Servlet后,除非JSP再次修改,否则之后再有用户访问就可以直接访问该Servlet,所以之后访问速度快。如果清空了【work】目录中的内容,那么所有的过程都会重新来过。

  Tomcat会定时扫描容器内的JSP文件,当发现某个JSP进行了修改之后,Tomcat会重新编译转换这个JSP成Servlet。但是Tomcat对JSP的扫描是定时的,即不是实时的,所有并不是修改完后就立即生效(如上面所说的虽然修改JSP并不需要重新部署,但是有可能会发生访问时还未修改)。所以有时候为了能立刻生效,很多老前辈会建议在修改JSP后立即清除【work】目录里的内容。

  (另外,Tomcat容器中,对于转换后的Java文件(例如index_jsp.java)的编译最大只支持64K,所以在其他服务器容器中的JSP移植到Tomcat容器中时会发生大JSP文件无法编译的情况。所以建议把JSP中的业务逻辑写入单独的类,在JSP中通过调用这个类的静态方法来执行,并将JSP中的JS,CSS等放入单独的JS文件或CSS文件依靠链接来加入样式等。)

  上面说了这么多,我们来探究下Tomcat的【work】目录,我们会发现在这个目录下还有【Catalina】文件夹,还有【localhost】文件夹(如果我们有其他虚拟主机,那么也在【Catalina】下建立其他虚拟主机的目录来存放JSP转换后的class文件):

  

这时候我们也看到了刚才刚建的web工程,接着我们继续点击进去(你会发现目录相当的多 T_T):

  

进到【JSP】目录下,我们就可以看到刚才从1.JSP转换过来的 _1_jsp.java文件和 _1_jsp.class文件了(数字开头,所以前面有一个下划线)。

  我们点击 _1_jsp.java文件,看一看里面的内容:

  

我们的 _1_jsp作为我们1.JSP所定义的类,继承了一个名为HttpJspBase这个类,而HttpJspBase类是可以从Tomcat的源码中(因为包中有apache)根据这个类的包名找到:

  

在这个类中继承了HttpServlet!所以这必须是一个Servlet :

  

  所以我们访问JSP,其实并不是真正在访问JSP,而是访问将JSP转换后的Servlet。在这个Servlet中,我们使用请求对象,将所需要的数据通过流的形式写回客户端,这点跟之前Servlet的学习到的是一样的。我们可以再看看那个浏览器访问的JSP页面,查看其码源:

  

  我们看到其码源已经像是正常的HTML页面,因为只有这样浏览器才能解释和显示,同时在原来JSP写Java代码的地方直接变成了我们Java运行后的结果,这是为什么呢?

  当知道JSP要转成Servlet,然后又Servlet来处理浏览器的请求,那根据之前学习的Servlet可以知道,这个请求是在Servlet中的service()方法中执行的,我们来看一看 _1_jsp 中的service()方法:

  

  

  我们可以看到,在这个service方法中,确实有接收请求对象和响应对象为参数,同时在方法的内部,通过IO流对象将一些HTML代码通过write()方法写出到浏览器,并且也将在JSP中写的Java代码原封不动的搬移到这个Servlet中,这就是为什么可以在JSP中写Java代码,因为最后Java代码都会交给Servlet,剩下的就跟之前Servlet的学习没啥区别了,通过流写给响应对象,再将响应对象交给浏览器显示。

  这里你可能会注意到我们在JSP编写是对Date对象是通过传统Java创建对象的方式来实现实例对象,而后面我们直接通过“out”这个对象来调用方法,那么这个“out”指的是哪个对象?还有别的什么对象可以直接调用吗?

  我们已经知道了JSP最终是要转换为Servlet的,而Servlet就是一个Java代码的类,那么在JSP中写的Java代码会原封不动的搬移到Servlet上,那么某些某名出现在JSP上的对象肯定就是在Servlet上已经被定义过的,我们再次看看上面刚才的截图,可以看到“out”这个对象是JSPWriter的实例(截图中out还未获得引用,但是后面的代码会使out对象获得引用,具体请看JSP转换后的JAVA源码),通过JSP的API手册:

  

  JspWriter是继承Writer的一个类。如果还记得通过响应对象Response.getWriter()方法获得的PrintWriter其实也是Writer下的一个类,所以JSP使用的字符流和Servlet能获取到的字符流其实都一个意思。

  综上,正是因为在转换的Servlet中会自动帮我们定义了JspWriter类的一个实例对象:out,所以我们能在JSP中直接使用这个对象,当然通过上诉截图我们还可以直接使用别的已经定义好的对象,比在JSP中使用“application”代表这个web的Context对象,用“page”代表了JSP对于的这个Servlet,用“session”代表这个web应用中的Session对象 等等,所以这些都是可以直接在JSP中使用,并代表某个类的对象的:

  

  简单说来,只要是在JSP转换后的Servlet中的_jspService()方法中定义过的变量,在JSP页面编写代码时都可以直接使用。

  在本篇博客的最后,我们来最后说明一点,不管是JSP还是Servlet,虽然都可以用于开发动态web工程,但由于这两个技术的各自特点:

  · 使用JSP即用Java代码产生动态数据,又做浏览器界面显示会导致页面难以维护。

  · 使用Servlet即处理数据,又在里面嵌套HTML代码用于界面显示,同样导致程序可读性差,难以维护,就如同上面的转换后的Servlet中各种out输出HTML代码。

  · 因此最好的方法就是根据这两门技术的特点,让它们各自负责各的,Servlet只负责响应请求并处理数据,并把数据通过转发(forward()方法)带给JSP,由JSP来显示,其实就是丢给转换后自动产生的Servlet来显示,让它来帮我们通过各种out来输出HTML代码。

  这篇文章主要介绍了JSP的一些知识和底层的一些技术,下一篇会具体讲诉JSP中所需要学习的语法。

JSP的学习(1)——基本知识与底层原理的更多相关文章

  1. spring源码学习之:springAOP实现底层原理

    一:springAOP底层实现是基于动态代理实现的.增强和切面,以及通知.是在动态代理生成的代理类inoke方法中调用实现 //+++++++++++++aop动态代理++++++++++++++++ ...

  2. JSP的学习(6)——九大隐式对象及其out对象

    本篇将介绍JSP中的九大隐式对象,并重点介绍其中的out对象. 我们在之前的博客<JSP的学习(1)——基础知识与底层原理>一文中已经知道,JSP最终要被翻译和转换成Servlet,在转换 ...

  3. JSP的学习(2)——语法知识一

    上一篇<JSP的学习>讲述了JSP的一些基础知识和底层原理,本篇将来学习JSP所需掌握的语法知识等. JSP的语法主要包括以下几个部分的内容: 1)         JSP模板元素 2)  ...

  4. JSP的学习(5)——语法知识三之include指令

    本篇继续来对JSP语法中的JSP指令进行学习,在<JSP的学习(3)——语法知识二之page指令>中,已经介绍了JSP指令的书写格式和page指令的详细信息,所以在这一篇中我们会对JSP指 ...

  5. JSP的学习(4)——中文乱码的解决

    本篇将以JSP页面中可能存在的中文乱码问题进行分析和解决. 中文乱码的问题一直是国人在编程过程中的一大头疼问题,这点上在JSP.Servlet或Tomcat上随处可见.比如我们在写一个Servlet时 ...

  6. JSP的学习(3)——语法知识二之page指令

    本篇接上一篇<JSP的学习(2)——语法知识一>,继续来学习JSP的语法.本文主要从JSP指令中的page指令,对其各个属性进行详细的学习: JSP指令: JSP指令是为JSP引擎而设计的 ...

  7. JSP的学习

    JSP的学习 1. (1).服务器的名字:Tomcat (2).服务器浏览器访问的地址为: http://localhost:8080 http://127.0.0.1:8080 2.简单的知识 (1 ...

  8. jsp/servlet相关技术及知识

    JSP页面的内容由两部分组成: 静态部分:标准的HTML标签.静态的页面内容, 动态部分:受Java程序控制的内容,这些都由java语言动态生成 简单的jsp页面代码: <%@ page lan ...

  9. jQuery学习笔记 - 基础知识扫盲入门篇

    jQuery学习笔记 - 基础知识扫盲入门篇 2013-06-16 18:42 by 全新时代, 11 阅读, 0 评论, 收藏, 编辑 1.为什么要使用jQuery? 提供了强大的功能函数解决浏览器 ...

随机推荐

  1. [Swust OJ 1091]--土豪我们做朋友吧(并查集,最值维护)

    题目链接:http://acm.swust.edu.cn/problem/1091/ Time limit(ms): 1000 Memory limit(kb): 32768   人都有缺钱的时候,缺 ...

  2. 实战nginx 基础知识总结(一)1.1

    squid Squid是一个缓存Internet数据的软件,其接收用户的下载申请,并自动处理所下载的数据.当一个用户想要下载一个主页时,可以向Squid发出一个申请,要Squid代替其进行下载,然后S ...

  3. 树莓派安装ftp服务器

    在树莓派安装ftp服务器,可上载\下载文件 vsftpd是开源的轻量级的常用ftp服务器. 1,安装vsftpd服务器 (约400KB)sudo apt-get install vsftpd 2,启动 ...

  4. Android Activity Fragment 生命周期

    从开源项目中看到 这个,就情不自禁的收藏了~ https://github.com/xxv/android-lifecycle

  5. python学习笔记——第三章 串

    第三章 字符串学习 1.字符串不灵活, 它不能被分割符值 >>> format = "hello, %s. %s enough for ya?" >> ...

  6. Sort List 分类: leetcode 算法 2015-07-10 15:35 1人阅读 评论(0) 收藏

    对链表进行排序,要求时间复杂度为O(n log n) ,不使用额外的空间. 我一开始的想法是借助quicksort的思想,代码如下: # time O(nlog(n)) # Definition fo ...

  7. Inter IPP 跟 Microsoft V100编译器区别

    最近做项目用了两个编译器,由于是一种精度的算法计算,对计算的精度要求非常高,同时都用的float型,发现inter的结果比vs的结果好许多.但是不知道是什么原因,最后测试发现,是两个编译器的问题.   ...

  8. 用css实现列表菜单的效果

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Qt 智能指针学习(7种QT智能指针和4种std智能指针)

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  10. Swift实现糗事百科Demo(实战项目)

    在这里,你将会学习到解析JSON数据,网络请求功能,动态调整cell内容等功能!!! 最终的结果 是这样的,项目相对简单,很适合入门!下面让我们一起开始教程之旅吧! 1.先看下项目工程结构: 第一步: ...