目录
HttpServlet中的doGet()和doPost()方法
3.4 ServletConfig和ServletContext
常见的动态Web开发技术:ASP、PHP、JSP和Servlet。
Sun公司:Servlet、JSP。
3.1 Servlet 概述
Servlet是使用Java语言编写的运行在服务器端的程序。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet主要用于处理客户端传来的HTTP请求,并返回一个相应,它能够处理的请求有doGet()和doPost()等方法。
Servlet由Servlet容器提供,所谓的Servelt容器是指提供了Servlet功能的服务器(本书中指Tomcat),Servlet容器将Servlet动态地加载到服务器上。与HTTP协议相关的Servlet使用HTTP请求和HTTP响应与客户端进行交互。因此,Servlet容器支持所有HTTP协议的请求和响应。Servlet应用程序的体系结构如下
在图3-1中,Servlet的请求首先会被HTTP服务器(如Apache)接收,HTTP服务器只负责静态HTML页面的解析,对于Servlet的请求转交给Servlet容器,Servlet容器会根据web.xml文件中的映射关系,调用相应的Servlet,Servlet将处理的及结果返回给Servlet容器,并通过HTTP服务器将响应传输给客户端。
Servlet技术具有如下特点:
- 方便:Servlet提供了大量的实用工具例程,如处理很难完成的HTML表单数据、读取和设置HTTP头,以及处理Cookie和跟踪会话等。
- 跨平台:Servlet用Java类编写,可以在不同操作系统平台和不同应用服务器平台下运行。
- 灵活性和可扩展性:采用Servlet开发的Web应用程序,由于Java类的继承性及构造函数等特点,使得应用灵活,可随意扩展。
- 功能强大、能够在各个程序之间数据共享、安全性强。
3.2 Servlet 开发入门
3.2.1 Servlet 接口及其实现类
针对Servlet技术的开发,SUN公司提供了一系列接口和类,其中,最重要的接口是javax.servlet.Servlet。Servlet接口的抽象方法如下
init()、service()、destroy()这3个方法可以表现Servlet的生命周期,它们会在某个特定的时刻被调用。另外,getServletInfo()方法用于返回Servlet的相关信息。getServletConfig()方法用于返回ServletConfig对象,该对象包含Servlet的初始化信息。需要注意的是,表中提及的Servlet容器指的是Web服务器。
针对Servlet的接口,SUN公司提供了两个默认的接口实现类:GenericServlet和HttpServlet。GenericServlet是一个抽象类,该类为Servlet接口提供了部分实现,它并没有实现HTTP请求处理。HttpServlet是GenericServlet的子类,他继承了GenericServlet的所有方法,并为HTTP请求中的POST、GET等类型提供了具体的操作方法。
通常情况下,编写的Servlet类都继承自HttpServlet,在开发中使用的具体的Servlet对象就是HttpServlet对象。HttpServlet的常用方法即其说明如下
3.2.2 实现第一个Servlet程序
(1)创建Servlet文件
package cn.itcast.firstapp.servlet;
import java.io.*;
import javax.servlet.*;
public class HelloWorldServlet extends GenericServlet {
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
//得到输出流PrinterWriter对象,Servlet使用输出流来产生响应
PrintWriter out = response.getWriter();
//使用输出流对象向客户端发送字符数据
out.println("Hello World");
}
}
HelloWorldServlet类继承GenericServlet后,只实现了service()方法。这是因为GenericServlet类除了Servlet接口的service()方法外,其他方法都已经实现。由此可见,继承GenericServlet类比实现Servlet接口更加简便。
(2)引入Servlet的JAR包
(3)编译Servlet
(4)将编译后的.class文件添加到服务器
(5)创建web.xml文件
在上面的配置信息中,元素<servlet>用于注册Servlet,它的两个子元素<servlet-name>和<servlet-class>分别用来指定Servlet名称及其完整类名。元素<servlet-mapping>用于映射Servlet对外访问的虚拟路径,它的子元素<servlet-name>的值必须和<servlet>元素中<servlet-name>相同,子元素<url-pattern>则是用于指定访问该Servlet的虚拟路径,该路径以正斜线(/)开头,代表当前Web应用程序的根目录。
(6)运行服务器,查看结果
3.2.3 Servlet的生命周期
1.初始化阶段
当客户端向Servlet容器发出HTTP请求要求访问Servlet时,Servlet容器首先会解析请求,检查内存中是否已经有了该Servlet对象,如果有直接使用该Servlet对象,如果没有就创建Servlet实例对象,然后通过调用init()方法实现Servlet的初始化工作。在Servlet的整个生命周期内,它的init()方法只被调用一次。
2.运行阶段
在这个阶段,Servlet容器会为这个请求创建代表HTTP请求的ServletRequest对象和代表HTTP响应的ServletResponse对象,然后将他们作为参数传递给Servlet的service()方法。service()方法从ServletRequest对象中获得客户请求信息并处理该请求,通过ServletResponse对象生成响应结果。在Servlet的整个生命周期内,对于Servlet的每一次访问请求,Servlet容器都会调用一次Servlet的service()方法,并且创建新的ServletRequest和ServletResponse对象,也就是说,service()方法在Servlet的整个生命周期中会被调用多次。
3.销毁阶段
当服务器关闭或Web应用被移出容器时,Servlet随着Web应用的销毁而销毁。在销毁Servlet之前,Servlet容器会调用Servlet的destory()方法,以便让Servlet对象释放它所占用的资源。在Servlet的整个生命周期中,destory()方法也只被调用一次。Servlet对象一旦创建就会驻留在内存中等待客户端的访问,直到服务器关闭,或Web应用被移除出容器时,Servlet对象才会被销毁。
<load-on-startup>元素是<servlet>元素的一个子元素,它用于指定Servlet被加载的时机和顺序。在<load-on-startup>元素中,设置的值必须是一个整数。如果这个值是一个负数,或者没有设定这个元素,Servlet容器将在客户端首次请求这个Servlet时加载它;如果这个值是正整数或0,Servlet容器将在Web应用启动时加载并初始化Servlet,并且<load-on-startup>的值越小,它对应的Servlet就越先被加载。
自动加载Servlet程序
当启动一个Web项目时,如果首先需要对数据库信息进行初始化。这时,只需要使用web.xml文件中<load-on-startup>元素,将初始化数据库的Servlet配置为随着Web应用启动而启动的Servlet即可。<load-on-startup>元素是<servlet>元素的一个子元素,它用于指定Servlet被加载的时机和顺序。在<load-on-startup>元素中,设置的值必须是一个整数。如果这个值是一个负数,或者没有设定这个元素,Servlet容器将在客户端首次请求这个Servlet时加载它;如果这个值是正整数或者0,Servlet容器将在Web应用启动时加载并初始化Servlet,并且<load-on-startup>的值越小,它对应的Servlet就越先被加载。
3.3 Servlet应用——HttpServlet类
由于大多数Web应用都是通过HTTP协议和客户端进行交互,因此,在Servlet接口中,提供了一个抽象类javax.servlet.http.HttpServlet,它是GenericServlet的子类,专门用于创建应用于HTTP协议的Servlet。HttpServlet类的源代码片段如下
通过分析HttpServlet的源代码片段,发现HttpServlet主要有两大功能。第一是根据用户请求方式的不同,定义相应的doXxx()方法处理用户请求。例如,与GET请求方式对应的doGet()方法,与POST方式对应的doPost()方法。第二是通过service()方法将HTTP请求和响应分别强转为HttpServletRequest和HttpServletReponse类型的对象。
由于HttpServlet类在重写的service()方法中,为每一种HTTP请求方式都定义了对应的doXxx()方法,因此,当定义的类继承HttpServlet后,只需根据请求方式,重写对应的doXxx()方法即可,而不需要重写service()方法。
HttpServlet中的doGet()和doPost()方法
(1)在目录“D:\cn\itcast\firstapp\servlet”下编写RequestMethodServlet类,并且通过继承HttpServlet类,实现doGet()和doPost()方法的重写,如文件3-3所示。
(2)在Tomcat中chapter03目录的web.xml中配置RequestMethodServlet的映射路径,配置信息如下所示。
(3)编译RequestMethodServlet.java文件,并将编译后生成的RequestMethodServlet.class文件拷贝到Tomcat安装目录下的webapps\chapter03\WEB-INF\classes文件中。
(4)采用GET方式访问RequestMethodServlet。启动Tomcat服务器,在浏览器的地址栏中输入地址“http://localhost:8080/chapter03/RequestMethodServlet”,浏览器显示的结果如图3-13所示。
(5)采用POST方式访问RequestMethodServlet。在目录webapps\chapter03下编写一个名为form.html的文件,并将表单的提交方式设置为POST,如文件3-4所示。
(6)启动Tomcat服务器,在浏览器的地址栏中输入地址“http://localhost:8080/chapter03/form.html”访问form.html文件,浏览器显示的结果如图3-14所示。
单击【提交】按钮,浏览器界面跳转到RequestMethodServlet,显示的结果如图3-15所示。
从图3-15中可以看出,浏览器显示出了“this is doPost method”语句。由此可见,采用POST方式请求Servlet时,会自动调用doPost()方法。
需要注意的是,如果GET和POST请求的处理方式一致,则可以在doPost()方法中直接调用doGet()方法,具体示例如下。
【任务3-2】实现Servlet虚拟路径的映射
【任务目标】
在web.xml文件中,一个<servlet-mapping>元素用于映射一个Servlet的对外访问路径,该路径也称为虚拟路径。例如HelloWorldServlet所映射的虚拟路径为“/HelloWorldServlet”。创建好的Servlet只有映射成虚拟路径,客户端才能对其进行访问。但是,在映射Servlet时,还有一些细节问题需要学习,比如Servlet的多重映射、在映射路径中使用通配符、配置缺省的Servlet等。
【实现步骤】
1.Servlet的多重映射
Servlet的多重映射指的是同一个Servlet可以被映射成多个虚拟路径。也就是说,客户端可以通过多个路径实现对同一个Servlet的访问。Servlet多重映射的实现方式有两种,具体如下。
(1)配置多个<servlet-mapping>元素
在浏览器的地址栏中输入地址“http://localhost:8080/chapter03/TestServlet01”访问TesstServlet01,浏览器的显示结果如下
地址“http://localhost:8080/chapter03/Test01”
(2)在一个<servlet-mapping>元素下配置多个<url-pattern>子元素
在web.xml文件中对TestServlet01虚拟路径的映射进行修改,修改后的代码如下所示
地址“http://localhost:8080/chapter03/TestServlet01”
地址“http://localhost:8080/chapter03/Test02”
2.Servlet映射路径中使用通配符
3.缺省Servlet
3.4 ServletConfig和ServletContext
3.4.1 ServletConfig接口
在Servlet运行期间,经常需要一些辅助信息,例如,文件使用的编码、使用Servlet程序的共享等,这些信息可以在web.xml文件中使用一个或多个<init-param>元素进行配置。当Tomcat初始化一个Servlet时,会将该Servlet的配置信息封装到一个ServletConfig对象中,通过调用init(ServletConfig config)方法将ServletConfig对象穿递给Servlet。ServletConfig定义了一系列获取配置信息的方法,如下
getInitParameter()方法的使用
(1)在chapter03项目的web.xml文件中为Servlet配置一些参数信息,具体的配置代码如下
(2)在cn.itcast.servlet包中编写TestServlet02类,用于读取web.xml文件中的参数信息,代码如下
(3)启动Tomcat服务器,在浏览器的地址栏中输入地址“http://localhost:8080/chapter03/TestServlet02”访问TestServlet02,结果如下
3.4.2 ServletContext接口
当Servlet容器启动时,会为每个Web应用创建一个唯一的ServletContext对象代表当前Web应用,该对象不仅封装了当前Web应用的所有信息,而且实现了多个Servlet之间数据的共享。ServletContext接口的不同作用如下
1.获取Web应用程序的初始化参数
在web.xml文件中,不仅可以配置Servlet的初始化信息,还可以配置整个Web应用的初始化信息。Web应用初始化参数的配置方式具体如下所示。
要想获取这些参数信息,可以使用ServletContext接口,该接口中定义的getInitParameterNames()和getInitParameter(String name)方法分别用来获取参数名和参数值。
接下来,通过一个案例来演示如何使用ServletContext接口获取Web应用程序的初始化参数。
(1)在chapter03项目的web.xml文件中,配置初始化参数信息和Servlet信息,代码如下
(2)在项目的cn.itcast.servlet包中,创建一个名称为TestServlet03的类,该类中使用ServletContext接口来获取web.xml中的配置信息,如下
(3)在Eclipse中启动Tomcat服务器,在浏览器的地址栏中输入地址“http://localhost:8080/chapter03/TestServlet03”访问TestServlet03,结果如下
2.实现多个Servlet对象共享数据
由于一个Web应用中的所有Servlet共享同一个ServletContext对象,因此,ServletContext对象的域属性可以被该Web应用中的所有Servlet访问。在ServletContext接口中定义了分别用于增加、删除、设置ServletContext域属性的4个方法,如下
在chapter03项目的cn.itcast.servlet包中创建两个Servlet类TestServlet04和TestServlet05,这两个Servlet类中分别使用了ServletContext接口中的方法设置和获取属性值,代码如下
首先在浏览器输入地址“http://localhost:8080/chapter03/TestServlet04”访问TestServlet04,将数据存入ServletContext对象,然后在浏览器的地址栏中输入地址“http://localhost:8080/chapter03/TestServlet05”访问TestServlet05,浏览器的显示结果如下
3.读取Web应用下的资源文件
在实际开发中,有时候可能会需要读取Web应用中的一些资源文件,比如配置文件、图片等。为此,在ServletContext接口中定义了一些读取Web资源的方法,这些方法是依靠Servlet容器来实现的。Servlet容器根据资源文件相对于Web应用的路径,返回关联资源的IO流、资源文件在文件系统的绝对路径等。ServletContext接口中用于获取资源路径的相关方法如下
(1)创建一个资源文件。
将创建的资源文件命名为itcast.properties,并且选择存放的目录为src目录。在创建好的itcast.properties文件中,输入如下所示的配置信息
(2)编写读取itcast.properties资源文件的Servlet。在cn.itcast.servlet包中创建一个名称为TestServlet06的Servlet类,该类的实现代码如下
使用ServletContext的getResourceAsStream(String path)方法获得了关联itcast.properties资源文件的输入流对象,其中path参数必须以正斜线“/”开始,表示itcast.properties文件相对于Web应用的相对路径。
(3)启动Tomcat服务器,在浏览器的地址栏中输入地址“http://localhost:8080/chapter03/TestServlet06”访问TestServlet06,结果如下
(4)有的时候,开发者需要获取的是资源的绝对路径。对文件TestServlet06.java进行修改,通过使用getRealPath(String path)方法获取资源文件的绝对路径,修改后的代码文件如下
(5)启动Tomcat服务器,在浏览器的地址栏中再次输入地址“http://localhost:8080/chapter03/TestServlet06”访问TestServlet06,同样可以看到图中显示的内容。