Java Servlet.docx
《Java Servlet.docx》由会员分享,可在线阅读,更多相关《Java Servlet.docx(26页珍藏版)》请在冰豆网上搜索。
JavaServlet
JavaServlet技术
一、概述:
1、Java Servlet及其特点
(1)JavaServlet
Servlet是使用JavaServlet应用程序设计接口(API)及相关类和方法的Java程序。
Servlet程序在服务器端运行并隐藏在Servlet容器里(如Tomcat)。
Servlet与传统的从命令行启动的Java应用程序不同,Servlet由Web服务器(如Tomcat)进行加载,该Web服务器必须包含支持Servlet的Java虚拟机。
Web客户端程序与Servlet之间通过http通信,Servlet处理客户端程序的请求并返回一系列结果,动态地生成Web页面,因此可以将它称之为“小服务程序”。
Servlet与Web服务器的关系类似于Applet与Web浏览器的关系(这也是为什么Servlet技术被称为Servlet的原因),我们可以将Servlet想象成没有前端界面(faceless)的Applet。
与Applet不同的是,由于Servlet运行在Web服务器端,因此它是一个可信赖的程序,不受到Java安全性的限制,拥有和普通Java应用程序一样的本地(也即对服务器)访问权限。
(2)Servlet的特点及与CGI的对比
●高效:
在传统的CGI中,每个请求都要启动一个新的进程,如果CGI程序本身的执行时间较短,启动进程所需要的开销很可能反而超过实际执行时间。
而在Servlet中,每个请求由一个轻量级的Java线程处理(而不是重量级的操作系统进程,因此是多线程处理。
但如果一个Servlet实现了SingleThreadModel接口,这样的Servlet只会响应同一时间的一个请求)。
在传统CGI中,如果有N个并发的对同一CGI程序的请求,则该CGI程序的代码在内存中重复装载了N次;而对于Servlet,处理请求的是N个线程,只需要一份Servlet类代码。
在性能优化方面,Servlet也比CGI有着更多的选择,比如缓冲以前的计算结果,保持数据库连接的活动,等等。
●方便:
Servlet提供了大量的实用类,例如自动地解析和解码HTML表单数据、读取和设置HTTP头、处理Cookie、跟踪会话状态等。
●功能强大:
在Servlet中,许多使用传统CGI程序很难完成的任务都可以轻松地完成。
例如,Servlet能够直接和Web服务器交互,而普通的CGI程序不能。
Servlet还能够在各个程序之间共享数据,使得数据库连接池之类的功能很容易实现。
Servlet还可利用Sockets与其他的Servlet或Applet进行通讯,因此可以实现更为复杂的Web应用
●可移植性好:
Servlet用Java编写,Servlet API具有完善的标准。
因此,为I-Planet Enterprise Server写的Servlet无需任何实质上的改动即可移植到Apache、Microsoft IIS或者WebStar。
几乎所有的主流服务器都直接或通过插件支持Servlet。
●节省投资:
不仅有许多廉价甚至免费的Web服务器可供个人或小规模网站使用,而且对于现有的服务器,如果它不支持Servlet的话,要加上这部分功能也往往是免费的(或只需要极少的投资)。
(3)Servlet的主要作用:
Servlet可完成如下功能。
●创建并返回一个包含基于客户请求性质的动态内容的完整的HTML页面。
●创建可嵌入到现有HTML页面中的一部分HTML页面(HTML片段)。
●与其它服务器资源(包括数据库和基于Java的应用程序)进行通信。
●可以实现对多个客户机处理连接,接收多个客户机的输入,并将结果广播到多个客户机上。
例如,Servlet可以是多参与者的游戏服务器。
2、JSP和Servlet到底在应用上有什么区别:
SUN首先发展出Servlet,其功能比较强劲,体系设计也很先进,只是,它输出HTML语句还是采用了老的CGI方式,是一句一句输出,所以,编写和修改HTML非常不方便。
后来SUN推出了类似于ASP的镶嵌型的JSP,把JSP标签镶嵌到HTML语句中,这样,就大大简化和方便了网页的设计和修改。
新型的网络语言如ASP,PHP,JSP都是镶嵌型的SCRIPT语言。
从网络三层结构的角度看,一个网络项目最少应该分为三层:
数据层、商业业务层和表示层。
当然也可以更复杂。
Servlet用来写商业业务层是很强大的,但是对于写表示层就很不方便。
JSP则主要是为了方便写表示层而设计的。
当然也可以写商业业务层。
写惯了ASP,PHP,CGI的朋友,经常会不自觉的把表示层和商业业务层混在一起。
JSP中应该仅仅存放与表示层有关的内容,也就是说,只放输出HTML网页的部份。
而所有的数据计算、数据分析、数据库连接等处理,统统是属于商业业务层,应该放在JavaBean或者Servlet中。
通过在JSP页面中调用JavaBean或者Servlet,实现两层的整合。
实际上,微软的DNA技术,简单说,就是ASP+COM/DCOM技术。
与JSP+JavaBeans完全类似,所有的表示层由ASP完成,所有的商业业务层由COM/DCOM完成。
通过调用,实现整合。
为什么要采用这些组件技术呢?
纯SCRIPT语言将表示层和商业业务层混在一起,造成修改不方便,并且代码不能重复利用。
如果想修改一个地方,经常会牵涉到十几页代码,采用组件技术就只需要修改组件就可以了。
JavaServlet的最大缺点就在于没有把网站的逻辑和页面的输出分开,导致整个Servlet代码混乱不堪。
为了解决JavaServlet的这种缺点,SUN推出了JavaServerPages—JSP。
综上所述,Servlet是一个早期的不完善的产品,写商业业务层很好,写表示层则不方便。
所以,推出JSP+JavaBean,用JSP写表示层,用JavaBean写商业业务层。
从而可以在此模式下,用JSP来部分替代Servlet。
虽然JSP技术是基本的Servlet技术的继承,但是JSP在Servlet的基础上有所创新,他们可以互相协作,互相补充对方的不足。
在上图所示,是一种把JSP与Servlets联合使用来实现动态内容服务的方法。
它吸取了两种技术各自的突出优点,用JSP生成表达层的内容,让Servlets完成深层次的处理任务。
在这里,Servlets充当控制者的角色,负责管理对请求的处理,创建JSP页需要使用的bean和对象,同时根据用户的动作决定把那个JSP页传给请求者。
特别要注意,在JSP页内没有处理逻辑;它仅负责检索原先由Servlets创建的对象或Beans,从Servlet中提取动态内容插入静态模板。
这是一种有代表性的方法,它清晰地分离了表达和内容,明确了角色的定义以及开发者与网页设计者的分工。
事实上,项目越复杂,使用该体系结构的好处就越大。
3、JSP与Servlet的各自的分工
Servlet是运行在服务器端的程序,处理数据接收的能力很出色,是一个多线程的设计。
在服务器端的功能十分强大。
一般作为商业业务层,特别是与后台数据库的连接、Socket网络通讯。
JSP是从Servlet上分离出来的一小部分,简化了开发,加强了界面设计,同时在JSP并没有增加任何本质上不能用Servlet实现的功能。
JSP定位在交互网页的开发。
运用Java语法,但功能较Servlet弱了很多,并且高级开发中只充当用户界面部分(表示层),从而不必再用println语句来输出每一行HTML代码。
如果建立的HTML页面的内容比较多而且要使用某些高级的HTML元素如表格等;专门有一个开发组设计Web页面,而另一个开发组编程Java代码;HTML代码经常需要修改,但Java代码则相对稳定等的应用场合下,应该使用JSP页面。
注:
JSP引擎将HTTPServlet这个类的一些对象自动进行初始化好让用户使用,而用户不用再去操心复杂的创建工作。
同时这个引擎又引入了*、<%@等一系列的特别语法,使用这些语法来进行一些特定的操作,如引用文件、URL转向、JavaBean引用等这样的操作,这些都是由引擎自动帮助完成初始化的工作。
二、Servlet技术
1、Servlet容器:
支持JSP、Servlets、jar等程序的一个软件平台(比如:
Tomcat、Weblogic等)。
容器负责处理客户的请求并把请求传送给Servlet,然后Servlet将处理的结果返回给容器服务器,服务器再发回给客户以完成对客户请求的响应。
不同的容器程序对Servlet标准的实际实现可能有所不同,但容器与Servlet之间的接口是由ServletAPI定义好的,这个接口定义了Servlet容器在Servlet上要调用的方法及传递给Servlet的对象类。
2、Servlet的生命周期(对比Applet):
●Servlet容器创建Servlet的一个实例
ServletEngine负责实例化和加载Servlet,这个过程可以在ServletEngine加载时执行(如果已配置自动装入选项,则在启动服务器时自动装入),可以在Servlet响应请求时执行,也可以在两者之间的任何时候执行。
●容器调用该实例的init()方法(Servlet有很多方法是由Servlet容器调用)
ServletEngine加载好Servlet后,必须要初始化它。
初始化时Servlet可以从数据库里读取初始数据,建立JDBCConnection,或者建立对其它有价值的资源的引用。
在初始化阶段,init()方法被调用。
这个方法在javax.servlet.Servlet接口中定义。
init()方法以一个Servlet配置文件(ServletConfig型)为参数。
ServletConfig类的对象由ServletEngine实现,可以让Servlet从中读取一些name-value对的参数值。
ServletConfig对象还可以让Servlet获得一个ServletContext对象。
●如果容器对该Servlet有请求,则调用此实例的公有的service()方法
Servlet被初始化以后,就处于能响应请求的就绪状态。
每个对Servlet的请求由一个ServletRequest对象代表。
Servlet给客户端的响应由一个ServletResponse对象代表。
当客户端有一个请求时,ServletEngine将ServletRequest和ServletResponse对象都转发给Servlet,这两个对象以参数的形式传给Service方法。
这个方法由javax.servlet.Servlet定义、并由具体的Servlet实现。
共有的service()方法将ServletRequest和ServletResponse对象构建成HttpServletRequest
和HttpServletResponse,并调用Servlet受保护的Service方法
受保护的Service方法根据Http请求的类型调用doGet或doPost或其他方法
service()方法从"请求"对象获得请求信息、处理该请求并用"响应"对象的方法以将响应传回客户机。
service()方法可以调用其它方法来处理请求,例如doGet()、doPost()或其它的方法。
●容器在销毁本实例(当服务器不再需要Servlet,或重新装入Servlet的新实例时)前调用它的destroy()方法销毁并标记该实例以供作为垃圾收集
注意:
●一旦请求了一个Servlet,就没有办法阻止容器执行一个完整的生命周期。
●容器在Servlet首次被调用时创建它的一个实例,并保持该实例在内存中,让它对所有的请求进行处理。
容器可以决定在任何时候把这个实例从内存中移走。
在典型的模型中,容器为每个Servlet创建一个单独的实例,容器并不会每接到一个请求就创建一个新线程,而是使用一个线程池来动态的将线程分配给到来的请求,但是这从Servlet的观点来看,效果和为每个请求创建一个新线程的效果相同。
●ServletEngine可以随时随意使用或释放Servlet。
因此,你不能依赖Servletclass或其成员存储信息。
3、与Servlet相关的API(所涉及的包):
javax.servlet和javax.servlet.http。
其中在javax.servlet包中的接口和类的命名主要以Servlet开头(见下面的左图),而在javax.servlet.http包中的接口和类的命名主要以Http开头(见下面的右图)。
4、Servlet的编程格式
(1)Servlet程序的框架
Servlet模型设计的目的是:
使可重用的小服务程序能够处理各种客户端请求,并有效地返回响应。
它将根据客户端发送的http请求类型指派一个具体的Servlet方法处理该响应。
(2)Servlet编程格式的要求
●在将请求发送给Web服务器后,请求行将被解析以便确定所期望的操作。
然后将HTTP方法映射到相关的Servlet方法。
因为所有的用户的HTTPservlet都必须扩展HttpServlet类,所以Servlet可以保证具有合适的方法处理HTTP操作。
●编程的步骤:
读取请求数据、写响应标题、获取响应的记录器或输出流对象、写响应数据
●
在Servlet中进行页面跳转
RequestDispatcherdispatch=getServletContext().getRequestDispatcher(/NetShop/info1.htm);
dispatch.forward(request,response);
注意:
在写响应数据之前,一个比较好的习惯是设置响应的内容类型(contenttype),指出响应的格式。
另一个习惯尽量使用请求对象设置Content-Length标题来通知容器文档的大小。
该信息将使Servlet容器能够使用持久的连接返回响应,有助于改善性能。
(3)程序例:
//基于HTTP协议的Servlet必须引入javax.servlet(要用到HttpServlet类)和javax.servlet.http包(要用到HttpServletRequest和HttpServletResponse接口)。
importjavax.servlet.*;
importjavax.servlet.http.*;
importjava.io.*;//java.io.*提供了所需的IOException对象
importjava.util.*;
publicclassServlet1extendsHttpServlet
{
staticfinalprivateStringCONTENT_TYPE="text/html;charset=GBK";
publicvoidinit(ServletConfig config)throwsServletException
{//在重载Servlet的init()方法后,一般应该调用super.init();
super.init();
}
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException
{
//doGet()方法可以扔出两个异常:
ServletException(在servlet遇到麻烦的时候即可扔出异常)和//IOException(在发生I/O问题的时候扔出)。
response.setContentType(CONTENT_TYPE);
//setContentType()方法指定servlet发回客户机的响应对象的内容(MIME)类型,setContentType()还可以用来指定字符集编码(charset=GBK所示)
PrintWriterout=response.getWriter();
//getWriter()返回PrintWriter对象out,你可以通过它发送HTML内容到客户机中。
out.println("");
out.println("
Servlet1");
out.println("
");
out.println("
TheservlethasreceivedaGET.Thisisthereply.
");
out.println("");
}
publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException
{
response.setContentType(CONTENT_TYPE);
PrintWriterout=response.getWriter();
out.println("");
out.println("
Servlet1");
out.println("
");
StringclientIPAddress=request.getRemoteAddr();
out.println("
Hello,Youcomefrom"+clientIPAddress+"
");
out.println("");
}
publicvoiddestroy()
{
}
}
(4)执行Servlet
为了从浏览器调用(也就是运行)Servlet,可以采用如下方式:
●为