JSP的编译过程

每个JSP页面都会被Web容器编译成一个Java类,供web容器调用,而且生成HTML叶面回馈给用户。而了解其中的变异方法和规则,对咱们学习JSP是很是有好处的,能够说学习好了这个编译原理,就已经学习好了大部分的JSP知识,剩下的工做就只剩下熟记一些tablib和反复应用以使本身更加熟练而已了html

JSP会被编译成.java放Tomcat/work/Catalina/localhostorg/apache/jsp/page
而后编译成.classjava

jsp = java + html
servlet = java + out.print(html)

1.客户端发送请求给web容器
2.web容器将jsp首先转译成servlet源代码
3.web容器将servlet源代码编译成.class 文件
4.web容器执行.class 文件
5.web容器将结果响应给客户端web

JSPServlet
这篇文章的主要目的不是单纯的介绍JSP,也不是详细的介绍Servlet。这是一篇讲述JSPServlet之间关系的基础性文章。这篇文章主要是针对那些学习JSP的人而写的。至于Servlet和JavaBean以及Servlet和XML个人两个同窗在他们的文档中将会给出明确的解释。
本文的主要结构:
1. Servlet是什么?
2. JSPServlet.
3. Servlet 概述
4. 附录一
5. 附录二
在讲述的过程当中,主要是针对JSPServlet关系区别来写。
而本文的内容顺序之因此按这种方式来写是为了体现技术的发展顺序。
附录一提供了有关怎样来运行一个Servlet的内容,彻底是按本人的经验来写,其内容已经通过本人的证明。
附录二中收集了一些纯粹的实践笔记。(转载)
一. Servlet是什么?
客户机/服务器计算的发展。Java提供了一整套客户机/服务器解决方案,在这个方案中,程序能够自动地下载到客户端并执行,这就是applet。可是它仅仅是问题的一半。问题的另外一半就是Servlet
servlet能够被认为是服务器端的applet。servlet被Web服务器加载和执行,就如同applet被浏览器加载和执行同样。servlet从客户端(经过Web服务器)接收请求,执行某种做业,而后返回结果。使用servlet的基本流程以下:
·客户端经过HTTP提出请求.
·Web服务器接收该请求并将其发给servlet。若是这个servlet还没有被加载,Web服务器将把它加载到Java虚拟机而且执行它。
·servlet将接收该HTTP请求并执行某种处理。
·servlet将向Web服务器返回应答。
·Web服务器将从servlet收到的应答发送给客户端。
因为servlet是在服务器上执行,一般与applet相关的安全性的问题并不需实现。要注意的是Web浏览器并不直接和servlet通讯,servlet是由Web服务器加载和执行的。
servlet是用Java编写的,因此它们一开始就是平台无关的。这样,Java编写一次就能够在任何平台运行(write once,run anywhere)的承诺就一样能够在服务器上实现了。servlet还有一些CGI脚本所不具有的独特优势: (本人对CGI并非十分了解,因此这些特色不能彻底的体会到,这也是摘自论坛的贴子,请见谅)
servlet是持久的。servlet只需Web服务器加载一次,并且能够在不一样请求之间保持服务(例如一次数据库链接)。与之相反,CGI脚本是短暂的、瞬态的。每一次对CGI脚本的请求,都会使Web服务器加载并执行该脚本。一旦这个CGI脚本运行结束,它就会被从内存中清除,而后将结果返回到客户端。CGI脚本的每一次使用,都会形成程序初始化过程(例如链接数据库)的重复执行。
servlet是与平台无关的。如前所述,servlet是用Java编写的,它天然也继承了Java的平台无关性。
servlet是可扩展的。因为servlet是用Java编写的,它就具有了Java所能带来的全部优势。Java是健壮的、面向对象的编程语言,它很容易扩展以适应你的需求。servlet天然也具有了这些特征。
servlet是安全的。从外界调用一个servlet的唯一方法就是经过Web服务器。这提供了高水平的安全性保障,尤为是在你的Web服务器有防火墙保护的时候。
   setvlet能够在多种多样的客户机上使用。因为servlet是用Java编写的,因此你能够很方便地在HTML中使用它们,就像你使用applet同样。
那么,Servlet是怎样执行的?怎样来写一个Servlet,它的基本架构是怎么样的?
这些问题,将在后面部分给予介绍。
二.JSPServlet
如今已经对Servlet有了大概的了解,如今咱们就来讲说JSPServlet的关系。
JSP是一种脚本语言,包装了Java Servlet系统的界面,简化了Java和Servlet的使用难度,同时经过扩展JSP标签(TAG)提供了网页动态执行的能力。尽管如此,JSP仍没有超出Java和Servlet的范围,不只JSP页面上能够直接写Java代码,并且JSP是先被译成Servlet以后才实际运行的。JSP在服务器上执行,并将执行结果输出到客户端浏览器,咱们能够说基本上与浏览器无关。它是与JavaScript不一样的,JavaScript是在客户端的脚本语言,在客户端执行,与服务器无关。

那么JSP是什么?就是Servlet.
JSPServlet之间的主要差别在于,JSP提供了一套简单的标签,和HTML融合的比较好,可使不了解Servlet的人能够作出动态网页来。对于Java语言不熟悉的人(好比像我),会以为JSP开发比较方便。JSP修改后能够当即看到结果,不须要手工编译,JSP引擎会来作这些工做;而Servelt缺须要编译,从新启动Servlet引擎等一系列动做。可是在JSP中,HTML与程序代码混杂在一块儿,而Servlet却不是这样。也许你们比较混乱了,那么Servlet又是什么?下面咱们对JSP的运行来作一个简单的介绍,告诉你们怎样来执行一个JSP文件:
当Web服务器(或Servlet引擎,应用服务器)支持JSP引擎时,JSP引擎会照着JSP的语法,将JSP文件转换成Servlet代码源文件,接着Servlet会被编译成Java可执行字节码(bytecode),并以通常的Servlet方式载入执行
JSP语法简单,能够方便的嵌入HTML之中,很容易加入动态的部分,方便的输出HTML。在Servlet中输出HTML缺须要调用特定的方法,对于引号之类的字符也要作特殊的处理,加在复杂的HTML页面中做为动态部分,比起JSP来讲是比较困难的。
除去了转换和编译阶段,JSPServlet之间的区别实在是不大。
JSP引擎一般架构在Servlet引擎之上,自己就是一个Servlet,把JSP文件转译成Servlet源代码,再调用Java编译器,编译成Servlet。这也是JSP在第一次调用时速度比较慢的缘由,在第一次编译以后,JSPServlet速度相同.下面咱们来看看为何他们在第一次编译后再编译的速度相同:
在整个运行过程当中,JSP引擎会检查编译好的JSP(以Servlet形式存在)是否比原始的JSP文件还新,若是是,JSP引擎不会编译;若是不是,表示JSP文件比较新,就会从新执行转译与编译的过程。
为了有个深入的了解,咱们看一下JSP的运行和开发环境:
浏览器:常见的浏览器有IE和Netscape两种。
数据库:经常使用的数据库有Oracle,SQL Server,Informix,DB2,Sybase,Access,MySQL等。
操做系统:常见的有Windows,Linux,以及各类Unix系统。
Web服务器:常见的有IIS,Apache,Netscape Enterprise Server等。
JSP引擎:通常JSP引擎都以Servlet引擎为基础,并以Servlet的形式出现。同时,在各类免费和商业引擎的实现中,Servlet引擎和Jsp引擎一般也是一块儿出现,咱们成为Servlet/JSP引擎,或从某种成为JSP引擎。
JSP引擎是能够提供JSPServlet运行支持并对其生存周期进行管理的系统级实体。
JSP页面第一次被请求时,JSP引擎会将JSP原始文件转换成Servlet源代码,而后调用Java编译器,编译成Servlet,并在Servlet引擎中执行。当再次有请求的时候,JSP引擎会见差别编译好的JSP是否比原来的JSP原始文件要新,若是是,运行Servlet;若是不是,表示文件已经更新的了,就会重新执行转换和编译的过程。
说到这里,也基本把JSPServlet的关系说清楚了,从个人感受上看用JSP就能够了,简单又方便,又能够和Bean 很好的兼容使用,功能又很强大,为何又出现了Servlet,它又有什么用?况且它的编写又相对复杂。为了把问题说得更清楚一点,我想在这里说一下历史,顺便再讲一下为何还要用ServletServlet的好处是什么。
历史简述:(摘自某论坛有删节,改写)
简单的说,SUN首先发展出SERVLET,其功能比较强劲,体系设计也很先进,只是,它输出HTML语句仍是采用了老的CGI方式,是一句一句输出,因此,编写和修改HTML很是不方便。
后来SUN推出了相似于ASP的镶嵌型的JSP(是Servlet发展的产物),把JSP TAG镶嵌到HTML语句中,这样,就大大简化和方便了网页的设计和修改。新型的网络语言如ASP,PHP,JSP都是镶嵌型的SCRIPT语言。
网络三层结构的角度看,一个网络项目最少分三层:data layer,business layer, presentation layer。固然也能够更复杂。SERVLET用来写business layer是很强大的,可是对于写presentation layer就很不方便。JSP则主要是为了方便写presentation layer而设计的。固然也能够写business layer。写惯了ASP,PHP,CGI的朋友,常常会不自觉的把presentation layer和business layer混在一块儿。把数据库处理信息放到JSP中,其实,它应该放在business layer中。 
根据SUN本身的推荐,JSP中应该仅仅存放与presentation layer有关的内容,也就是说,只放输出HTML网页的部份。而全部的数据计算,数据分析,数据库联结处理,通通是属于business layer,应该放在JAVA BEANS中。经过JSP调用JAVA BEANS,实现两层的整合。 
实际上,微软推出的DNA技术,简单说,就是ASP+COM/DCOM技术。与JSP+BEANS彻底相似,全部的presentation layer由ASP完成,全部的business layer由COM/DCOM完成。经过调用,实现整合。如今微软推出的.NET也是经过这个理念,全部的presentation layer由ASP.NET完成,business layer由C#或VB.NET或VC.NET来完成。
为何要采用这些组件技术呢?由于单纯的ASP/JSP语言是很是低效率执行的,若是出现大量用户点击,纯SCRIPT语言很快就到达了他的功能上限,而组件技术就能大幅度提升功能上限,加快执行速度。 
另一方面,纯SCRIPT语言将presentation layer和business layer混在一块儿,形成修改不方便,而且代码不能重复利用。若是想修改一个地方,常常会牵涉到十几页CODE,采用组件技术就只改组件就能够了。 
综上所述,SERVLET是一个早期的不完善的产品,写business layer很好,写presentation layer就很很差,而且两层混杂,显得十分混乱。
因此,推出JSP+BAEN,用JSP写presentation layer,用BAEN写business layer。SUN本身的意思也是未来用JSP替代SERVLET
看了上面的叙述,你们可能对JSPServlet共存有了比较好的认识。能够看到JSP和Bean结合后的的实用性,强大的表现功能,易用性都是Servlet所不能及的。那么是否是Servlet就被取代了?不是!在之后的发展中,它仍是有着巨大的做用的。上面只不过是将了问题的一方面,下面咱们来看看Servlet自己的特色。
因为它是由java来写的,因此相关的特色咱们就不说了,上文已经有了详细的介绍,咱们来看看其余的:
Servlet是用于开发服务器端应用程序的一种编程模型,若是只是一个普通的java应用,能够不使用servlet来编写,可是若是想要提供基于web的服务能力,那么就必须按照这种模型来编写,并且servlet也必须容许在符合servlet规范的java web server or app server之上,不然没法运行。除非你本身实现一个web server,可是其复杂度是比较高的,特别是在企业级应用中,对系统的稳定性和健壮性都要求比较高,因此servlet的模型其实是简化了编写稳健的服务器端的应用开发过程。Servlet 能够做为提供web服务能力的一个接入方式
如今也许能够理解了什么是Servlet什么是JSP,它们之间的关系是怎样的。下面我就对Servlet这个技术作一个简要的介绍。
Servlet概述
一.Servlet的结构
Servlet API中最重要的是Servlet interface. 全部的servlets implement(执行)这个interface, 方式多种:或者是直接的,或者经过extending 这个class执行它,如 HttpServlet. 这个Servlet interface 提供安排servlet与客户端联系的方法. Servlet 编写者能够在他们开发servlet程序时提供更多一些或全部的这样方法. 
当一个servlet接收来自客户端的调用请求, 它接收两个对象: 一个是ServletRequest,另一个是ServletResponse. 这个ServletRequest class 归纳从客户端到服务器之间的联系, 而 ServletResponse class 归纳从servlet返回客户端的联系. 
ServletRequest interface 能够获取到这样一些信息如由客户端传送的阐述名称,客户端正在使用的协议, 产生请求而且接收请求的服务器远端主机名. 它也提供获取数据流的servlet, ServletInputStream, 这些数据是客户端引用中使用HTTP POST 和 PUT 方法递交的. 一个ServletRequest的子类可让servlet获取更多的协议特性数据. 例如: HttpServletRequest 包含获取HTTP-specific头部信息的方法. 
ServletResponse interface 给出相应客户端的servlet方法. 它容许servlet设置内容长度和回应的mime类型, 而且提供输出流, ServletOutputStream, 经过编写者能够发回相应数据. ServletResponse子类能够给出更多protocol-specific容量的信息。 例如: HttpServletResponse 包含容许servlet操做HTTP-specific头部信息的方法. 
上面有关classes 和 interfaces描述构成了一个基本的Servlet框架. HTTP servlets有一些附加的能够提供session-tracking capabilities的方法. servlet编写者能够用这些API在有他人操做时维护servlet与客户端之间的状态.
二.编写Servlet
Servlets 执行 javax.servlet.Servlet interface. servlet编写者能够经过直接implement interface开发servlet, 但这样一般没有必要. 由于大多数servlet是针对用HTTP协议的web服务器, 这样最通用开发servlet办法是用 javax.servlet.http.HttpServlet 内.HttpServlet 类经过extend GenericServlet基类执行 Servlet interface, 提供了处理HTTP协议的功能. 他的service方法支持标准HTTP/1.1请求. 通常地, 用HttpServlet指定的类编写的servlets能够多线程地并发运行service方法.
Servlet编写者注意HttpServlet类有几个欠缺的方法,你能够本身定义方法中内容,可是必须使用这些方法名称以使servlet知道你想作什么, 
doGet, 用于处理 GET、有条件的GET 和头部 HEAD请求 
doPost, 用户处理 POST 请求
doPut, 用于处理 PUT 请求
doDelete, 用于处理 DELETE请求 
HttpServlet的service方法, 通常地, 当它接收到一个OPTIONS请求时,会调用doOptions 方法, 当接收一个TRACE请求是调用doTrace . doOptions缺省执行方式是自动决定什么样的HTTP被选择而且返回哪一个信息. 
在你使用这些方法时,必须带两个阐述. 第一个包含来自客户端的数据HttpServletRequest. 第二个参数包含客户端的响应HttpServletResponse. 在下例中是这样的状况. 
一个HttpServletRequest对象提供到达HTTP 头部数据, 也容许你获取客户端的数据. 怎样获取这些数据取决于HTTP端请求方法. 
无论任何HTTP方式, 你能够用]getParameterValues方法, 这个用来返回特定名称的参数值.
对于用 HTTP GET 请求的方式, 这个getQueryString方法将会返回一个能够用来解剖分析的。对于用HTTP POST, PUT, 和 DELETE请求的方式, 你有两种方法能够选择. 若是是文本数据,你能经过getReader方法用BufferedReader获取;若是是二进制数据, 能经过getReader 方法用 ServletInputStream获取.
为了响应客户端, 一个HttpServletResponse对象提供返回数据给用户的两个方法. 你能够用getWriter 方法返回,或者 getOutputStream 方法以输出流返回. 你应该用getWriter返回文本数据,而用getOutputStream返回二进制数据. 
在使用Writer 或 OutputStream以前, HTTP 头部应该先被设置. HttpServletResponse内提供这样一个方法,以后能够用writer 或 outputstream 将响应主体部分发回用户. 完成后要关闭 writer 或 output stream以便让服务器知道响应已经完毕. 


附录一
运行你的Servlet
当一个servlet已经写好怎样来运行测试呢?我花了好长时间来研究这个,也许是由于我太笨。但其实如今想一想也不是很难。我想经过一个例子详细的说说,这样会有一个感性的把握。我会把我当时遇到的主要问题用黑体字写出,那时我当时主要浪费时间的地方,但愿你们也注意。(我用的运行环境是Tomcat5.0)
首先咱们来写一个最简单的servlet:
package test;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");

PrintWriter out=response.getWriter();
out.println("<HTML>");
out.println("<BODY>");
out.println("<p>Hello!这是个人第一个Java Servlet程序。</p>");
out.println("</BODY>");
out.println("</HTML>");
}
}
因为咱们把它进行了打包,因此把这个编译好的.class文件放到/Tomcat文件夹/webapps/ourappfiles/WEB-INF/classes/test的文件夹下。
接着咱们须要写一个调用该Servlet的html文件:
<html>
<head>
<title>Java Servlets Sample-Properties</title>
</head>
<body>
<form method="get" action="test.HelloServlet">
<input name="test" type="submit" value="Test HelloServlet servlet">
</body>
</html>
注意:这里的method不能用post,否则不会在IE中正常显示,我当初就是在这个地方没有弄好,浪费了好多时间。至于为何这样写,我也弄不太清楚,因为水平有限,多多包涵。
如今咱们还差最后一步,编写咱们的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd";>
<web-app>
<servlet>
<servlet-name>helloservlet</servlet-name>
<servlet-class>test.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloservlet</servlet-name>
<url-pattern>/test.HelloServlet</url-pattern>
</servlet-mapping>
</web-app>
把编写好的web.xml文件放到/Tomcat文件夹/webapps/ourappfiles/WEB-INF下。
好了,如今万事俱备,就差启动Tomcat运行咱们的Servlet了。
以上就是运行Servlet的几个步骤。
附录二
这个附录纯粹是另外一个读书笔记,我感受比较好,因此摘录下来。里面写的是经验的结晶,我尚未这么多的经验,因此只有摘抄别人的以做补充了。
1.ServletConfig
l 一个ServletConfig对象是servlet container在servlet initialization的时候传递给servlet的。

ServletConfig包涵 ServletContext 和 一些 Name/Value pair (来自于deployment descriptor)

l ServletContext接口封装了Web应用程序的上下文概念。

2.会话跟踪
1) Session
l 当一个Client请求多个Servlets时,一个session能够被多个servlet共享。

l 一般状况下,若是server detect到browser支持cookie,那么URL就不会重写。


2) cookie
l 在Java Servlet中,若是你光 Cookie cookie = new Cookie(name,value)
那么当用户退出Browser时,cookie会被删除掉,而不会被存储在客户端的硬盘上。

若是要存储 cookie,需加一句 cookie.setMaxAge(200)

l cookie是跟某一个server相关的,运行在同一个server上的servlet共享一个cookie.

3) URL Rewriting
在使用URL Rewriting来维护Session ID的时候,每一次HTTP请求都须要EncodeURL()
典型的用在两个地方
1) out.print(“form action=/” ”);
out.print(response.encodeURL(“sessionExample”));
out.print(“form action=/” ”);
out.print(“method = GET>”);
2) out.print(“<p><a href=/” ”);
out.print(response.encodeURL(“SessionExample?database=foo&datavalue=bar”));
out.println(“/” >URL encoded </a>”);

3.SingleThreadModel
默认的,每个servlet definition in a container只有一个servlet class的实例。
只有实现了SingleThreadModel,container才会让servlet有多个实例。

Servlet specification上建议,不要使用synchronized,而使用SingleThreadModel。

SingleThreadModel(没有方法)
保证servlet在同一时刻只处理一个客户的请求。
SingleThreadModel是耗费资源的,特别是当有大量的请求发送给Servlet时,SingleThreadModel的做用是使包容器以同步时钟的方式调用service方法。
这等同于在servlet的service()方法种使用synchronized.

Single Thread Model通常使用在须要响应一个heavy request的时候,好比是一个须要和数据库打交道的链接。


2. 在重载Servlet地init( )方法后,必定要记得调用super.init( );

3. the client经过发送一个blank line表示它已经结束request
而the server经过关闭the socket来表示response已结束了。

4. 一个Http Servlet能够送三种东西给Client
1) a single status code
2) any number of http headers
3) a response body

5. Servlet之间信息共享的一个最简单的方法就是
System.getProperties().put(“key”,”value”);

6. Post和Get
Post:将form内各字段名称和内容放置在html header内传送给server
Get: ?以后的查询字符串要使用URLEncode,通过URLEncode后,这个字符串再也不带有空格,之后将在server上恢复所带有的空格。

Get是Web上最常用的一种请求方法,每一个超连接都使用这种方法。

7. Web.xml就是Web Applicatin 的deployment descriptor
做用有:组织各种元素
设置init param
设置安全性

8. Request Dispatcher用来把接收到的request forward processing到另外一个servlet
要在一个response里包含另外一个servlet的output时,也要用到Request Dispatcher.

9. ServletJsp在同一个JVM中,能够经过ServeltContext的
setAttribute( )
getAttribute( )
removeAttribute( )
来共享对象
10. 利用request.getParameter( )获得的String存在字符集问题。
能够用 strTitle = request.getParameter(“title”);
strTitle = new String(strTitle.getBytes(“8859-1”),”gb2312”);

若是你但愿获得更大得兼容性
String encoding = response.getCharacterEncoding(); //肯定Application server用什么编码来读取输入的。
strTitle = new String(strTitle.getBytes(encoding),”gb2312”);数据库

相关文章
相关标签/搜索