1、 响应:Servlet模块接受请求后,调用相应的服务(service()对请求进行处理,然后将处理结果返回给Servlet引擎。 HTTP响应:Servlet引擎将结果发送给客户端。Servlet看起来像是通常的Java程序。Servlet导入特定的属于Java ServletAPI的包。因为是对象字节码,可动态地从网络加载,可以说Servlet对Server就如同Applet对Client一样,但是,由于Servlet运行于Server中,它们并不需要一个图形用户界面。从这个角度讲,Servlet也被称为FacelessObject。一个servlet就是Java编程语言中的一个类,它被用来
2、扩展服务器的性能,服务器上驻留着可以通过“请求-响应”编程模型来访问的应用程序。虽然servlet可以对任何类型的请求产生响应,但通常只用来扩展Web服务器的应用程序。7.1.3 Servlet的特点 高效在传统的CGI中,每个请求都要启动一个新的进程,如果CGI程序本身的执行时间较短,启动进程所需要的开销很可能反而超过实际执行时间。而在Servlet中,每个请求由一个轻量级的Java线程处理(而不是重量级的操作系统进程)。在传统CGI中,如果有N个并发的对同一CGI程序的请求,则该CGI程序的代码在内存中重复装载了N次;而对于Servlet,处理请求的是N个线程,只需要一份Servlet类代
3、码。在性能优化方面,Servlet也比CGI有着更多的选择,比如缓冲以前的计算结果,保持数据库连接的活动等。 方便Servlet提供了大量的实用工具例程,例如自动地解析和解码HTML表单数据、读取和设置HTTP头、处理Cookie、跟踪会话状态等。 功能强大在Servlet中,许多使用传统CGI程序很难完成的任务都可以轻松地完成。例如,Servlet能够直接和Web服务器交互,而普通的CGI程序不能。Servlet还能够在各个程序之间共享数据,使得数据库连接池之类的功能很容易实现。 可移植性好Servlet用Java编写,Servlet API具有完善的标准。因此,为I-Planet Ente
4、rprise Server写的Servlet无需任何实质上的改动即可移植到Apache、Microsoft IIS或者WebStar。几乎所有的主流服务器都直接或通过插件支持Servlet。节省投资不仅有许多廉价甚至免费的Web服务器可供个人或小规模网站使用,而且对于现有的服务器,如果它不支持Servlet的话,要加上这部分功能也往往是免费的(或只需要极少的投资)。7.2 Servlet基本结构Servlet模块是用Servlet API编写的Servlet API包含两个包:javax.servlet和javax.servlet.http。javax.servlet包中的类与http协议无关
5、;javax.servlet.http包中的类与http协议相关,该包中的部分类继承了javax.servlet包中的部分类和接口下面介绍编写Servlet类时要继承的超类和父类。即GenericServlet和HttpServlet。7.2.1 GenericServlet类GenericServlet类在javax.servlet包中,它提供了servlet接口的基本实现,该类包含三个重要的方法,它们是init()、destroy()和service()方法。service()是抽象方法,所有子类都应当实现这个方法。7.2.2 HttpServlet类HttpServlet类在javax.
6、servlet.http包中,它扩展了GenericServlet类。HttpServlet类定义了两个service()方法和六个doXXX()方法。(1) 两个service()方法public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException /方法代码本方法是公有方法。该方法接收客户端请求包后,创建request对象和response对象,并分别转换为 HttpServletRequest/ HttpServletResponse类型的对
7、象,然后调用下面的保护service()方法。protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException该方法接收HttpServletRequest/ HttpServletResponse类型的对象后,根据http请求方法的类型,本方法调用下面6个doXXX()方法之一,进行逻辑处理并响应客户。(2) doXXX()方法doXXX()方法有6个:doGet(), doPost(),doDelete(),doPut()
8、,doTrace(),doOption()。它门分别对应Form表单中的method属性。get方法提交的数据量不能超过2kB, 否则提交失败,post提交没有容量限制。下面是doGet()方法和doPost()方法。protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException /具体要处理的逻辑代码写在此处 ,或者在此处调用被覆盖的doPost()方法。protected void doPost(HttpServletReq
9、uest request, HttpServletResponse response) throws ServletException, IOException /具体要处理的逻辑代码写在此处,或者在此处调用被覆盖的doGet()方法。程序员自定义的Servlet类都必须扩展HttpServlet类在扩展类中,覆盖service()、doPost()或doGet()方法实现逻辑处理。7.2.3 编写Servlet类的步骤下面是程序员编写Servler类时的一般步骤:(1)扩展HttpServlet类(2)覆盖HttpServlet类中的三个方法service()、doPost()或doGet(
10、),将要处理的逻辑代码写在以上三个方法的任一个中。Servlet模块执行service()方法时,会自动调用doPost()或doGet()这两个方法,实现servlet逻辑处理功能。7.2.4 Servlet的基本结构下面的代码显示了一个简单Servlet的基本结构。该Servlet处理的是GET请求,所谓的GET请求,如果你不熟悉HTTP,可以把它看成是当用户在浏览器地址栏输入URL、点击Web页面中的链接、提交没有指定METHOD的表单时浏览器所发出的请求。Servlet也可以很方便地处理POST请求。POST请求是提交那些指定了METHOD=“POST”的表单时所发出的请求,具体请参见
11、稍后几节的讨论。import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class SomeServlet extends HttpServlet public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException / 使用“request”读取和请求有关的信息(比如Cookies)和表单数据 / 使用“response”指定HTTP应答状态代码
12、和应答头(比如指定内容类型,设置Cookie) PrintWriter out = response.getWriter(); / 使用 out把应答内容发送到浏览器 如果某个类要成为Servlet,则它应该从HttpServlet 继承,根据数据是通过GET还是POST发送,覆盖doGet、doPost方法之一或全部。doGet和doPost方法都有两个参数,分别为HttpServletRequest 类型和HttpServletResponse 类型。HttpServletRequest提供访问有关请求的信息的方法,例如表单数据、HTTP请求头等等。HttpServletResponse除
13、了提供用于指定HTTP应答状态(200,404等)、应答头(Content-Type,Set-Cookie等)的方法之外,最重要的是它提供了一个用于向客户端发送数据的PrintWriter 。对于简单的Servlet来说,它的大部分工作是通过println语句生成向客户端发送的页面。注意doGet和doPost抛出两个异常,因此你必须在声明中包含它们。另外,你还必须导入java.io包(要用到PrintWriter等类)、javax.servlet包(要用到HttpServlet等类)以及javax.servlet.http包(要用到HttpServletRequest类和HttpServle
14、tResponse类)。最后,doGet和doPost这两个方法是由service方法调用的,有时你可能需要直接覆盖service方法,比如Servlet要处理GET和POST两种请求时。7.2.5 简单Servlet应用示例下面给出两个简单的Servlet应用示例,通过这两个例子,让读者来了解Servlet运行的整个流程。下面是一个输出纯文本的简单Servlet。例7-1 Servlet示例。FirstServlet.java package test; import java.io.*; import javax.servlet.*; import javax.servlet.http.*
15、; public class FirstServlet extends HttpServlet public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException PrintWriter out = response.getWriter(); out.println(This is my first servlet!);在Tomcat7.0下,Servlet应该放到Web应用的WEB-INFclasses目录下的相应的包中,而调用Serv
16、let的URL是http:/host/servlet/ServletName。在其他的服务器上,安装和调用Servlet的方法可能略有不同。将编译后的FirstServlet.class文件部署到ch7WEB-INFclassestest目录中,并在WEB-INF目录下的web.xml配置文件中做如下配置: descriptionThis is the description of my J2EE componentdisplay-nameThis is the display name of my J2EE componentservlet-nameFirstServletservlet-c
17、lasstest.FirstServlet/servletservlet-mappingurl-pattern/servlet/FirstServlet/servlet-mapping其中nheadtitle用Servlet输出Html代码/head );bodyh2欢迎来到 Servlet世界!/h2/body/html运行的结果如图7-3所示:图7-3 用Servlet输出Html代码7.3 处理表单数据如果你曾经使用过Web搜索引擎,或者浏览过在线书店、股票价格、机票信息,或许会留意到一些古怪的URL,比如“http:/host/path?user=Marty+Test&origin =
18、bwi&dest=lax”。这个URL中位于问号后面的部分,即“user=Marty+Test&origin= bwi&dest=lax”,就是表单数据,这是将Web页面数据发送给服务器程序的最常用方法。对于GET请求,表单数据附加到URL的问号后面(如上例所示);对于POST请求,表单数据用一个单独的行发送给服务器。以前,从这种形式的数据提取出所需要的表单变量是CGI编程中最麻烦的事情之一。首先,GET请求和POST请求的数据提取方法不同:对于GET请求,通常要通过QUERY_STRING环境变量提取数据;对于POST请求,则一般通过标准输入提取数据。第二,程序员必须负责在“&”符号处截断变
19、量名字-变量值对,再分离出变量名字(等号左边)和变量值(等号右边)。第三,必须对变量值进行URL反编码操作。因为发送数据的时候,字母和数字以原来的形式发送,但空格被转换成加号,其他字符被转换成“%XX”形式,其中XX是十六进制表示的字符ASCII(或者ISO Latin-1)编码值。例如,如果HTML表单中名为“users”的域值为“test, gates, and mcnealy”,则实际向服务器发送的数据为“users=%7Etest%2C+%7Egates%2C+and+%7Emcnealy”。最后,即第四个导致解析表单数据非常困难的原因在于,变量值既可能被省略(如“param1=val
20、1param2=param3=val3”),也有可能一个变量拥有一个以上的值,即同一个变量可能出现一次以上(如“param1=val1param2=val2param1=val3”)。Java Servlet的好处之一就在于所有上述解析操作都能够自动完成。只需要简单地调用一下HttpServletRequest的getParameter方法、在调用参数中提供表单变量的名字(大小写敏感)即可,而且GET请求和POST请求的处理方法完全相同。getParameter方法的返回值是一个字符串,它是参数中指定的变量名字第一次出现所对应的值经反编码得到得字符串(可以直接使用)。如果指定的表单变量存在,但
21、没有值,getParameter返回空字符串;如果指定的表单变量不存在,则返回null。如果表单变量可能对应多个值,可以用getParameterValues来取代getParameter。getParameterValues能够返回一个字符串数组。最后,虽然在实际应用中Servlet很可能只会用到那些已知名字的表单变量,但在调试环境中,获得完整的表单变量名字列表往往是很有用的,利用getParamerterNames方法可以方便地实现这一点。getParamerterNames返回的是一个Enumeration,其中的每一项都可以转换为调用getParameter的字符串。下面是一个简单的例
22、子,它读取三个表单变量param1、param2和param3,并以HTML列表的形式列出它们的值。请注意,虽然在发送应答内容之前必须指定应答类型(包括内容类型、状态以及其他HTTP头信息),但Servlet对何时读取请求内容却没有什么要求。另外,我们也可以很容易地把Servlet做成既能处理GET请求,也能够处理POST请求,这只需要在doPost方法中调用doGet方法,或者覆盖service方法(service方法调用doGet、doPost、doHead等方法)。在实际编程中这是一种标准的方法,因为它只需要很少的额外工作,却能够增加客户端编码的灵活性。如果你习惯用传统的CGI方法,通过
23、标准输入读取POST数据,那么在Servlet中也有类似的方法,即在HttpServletRequest上调用getReader或者getInputStream,但这种方法对普通的表单变量来说太麻烦。然而,如果是要上载文件,或者POST数据是通过专门的客户程序而不是HTML表单发送,那么就要用到这种方法。注意用第二种方法读取POST数据时,不能再用getParameter来读取这些数据。例7-3处理表单数据示例。ThreeParams.javapackage test;import java.util.*;public class ThreeParams extends HttpServlet
24、 public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException response.setContentType(text/html String title = 读取三个请求参数; out.println(ServletUtilities.headWithTitle(title) + BODY +H1 ALIGN=CENTER + title + /H1ULLIparam1: + request.getParameter(param1) + param2:param2param3:param3/UL/BODY/HTML public void doPost(HttpServletRequest request, HttpServletResponse r
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1