文章目录
- 第 2 章 Servlet 编程
- 2.1 Servlet 简介
- 2.2 Servlet 基础
- 2.2.1 用记事本写一个 Servlet
- 2.2.2 Servlet 体系结构
- 2.2.3 Servlet 接口
- 2.2.4 Servlet 生命周期
- 2.2.5 Servlet 生命周期示例
- 2.3 Servlet API编程常用接口和类
- 2.3.1 GenericServlet 类
- 2.3.2 HttpServlet类
- 2.3.3 ServletConfig 接口
- 2.3.4 HttpServletRequest 接口
- 2.3.5 HttpServletResponse接口
- 2.3.6 ServletContext 接口
第 2 章 Servlet 编程
Java Servlet是运行在Web服务器或应用服务器上的程序,它是来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。使用Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。本章主要内容有: (1) Servlet简介; (2) Servlet 基础;(3) Servlet API编程常用接口和类;(4) Servlet处理表单数据: (5) Servlet重定向和请求转发; ( 6) Servlet数据库访问; ( 7) Servlet异常处理;(8)异步Servlet。
2.1 Servlet 简介
Servlet在Web服务器的地址空间内执行。这样,其没有必要再创建一个单独的进程来处理每个客户端请求。在传统的CGI中,每个请求都要启动一个新的进程,如果CGI程序本身的执行时间较短,则启动进程所需要的开销很可能反而超过了实际执行时间。而在Servlet中,每个请求由一个轻量级的Java线程(而不是重量级的操作系统进程)处理。
在传统CGI中,如果有N个并发的对同一CGI程序的请求,则该CGI程序的代码在内存中重复装载了N次;而对于Servlet,处理请求的是N个线程,只需要一份Servlet类代码。在性能优化方面,Servlet 也比CGI有着更多的选择。
Servlet是独立于平台的,因为它们是用Java编写的。
Java类库的全部功能对Servlet来说都是可用的。
Servlet对请求的处理和响应过程可分为以下几个步骤。
(1)客户端发送请求至服务器端。
(2)服务器将请求信息发送至Servlet。
(3) Servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求。
(4)服务器将响应返回给客户端。
-
Servlet 的存在就是要为客户端服务
Servlet的任务是得到一个客户端的请求,再发回一个响应。请求可能很简单一“ 请给我一个欢迎页面。”,也可能很复杂一“ 为我的购物车结账。”这个请求携带着一些重要的数据,Servlet 代码必须知道怎么找到和使用这个请求。响应也携带着些一信息,浏览器需要这些信息来显示一个页面,Servlet 代码必须知道怎么发送这些信息。 -
Servlet 3.0
Servlet 3.0作为JavaEE 6规范体系中的一员,随着Java EE6规范起一发布。该版本在前版本(Servlet2.5)的基础上提供了若干新特性,以用于简化Web应用的开发和部署。
(1)异步处理支持:有了该特性,Servlet 线程不再需要一直阻塞, 直到业务处理完毕才能再输出响应,最后才能结束该Servlet线程。在接收到请求之后,Servlet 线程可以将耗时的操作委派给另一个线程来完成,自已在不生成响应的情况下返回至容器。针对业务处理较耗时的情况,这将大大减少服务器资源的占用,并且提高并发处理速度。
(2)新增的注解支持:该版本新增了若干注解,用于简化Servlet、过滤器(Filter) 和监听器(Listener) 的声明,这使得Web.xml部署描述文件从该版本开始不再是必选的了。
- Servlet 与Tomcat版本支持
以目前主流的Web服务器Tomcat (包含Servlet容器)为例,Tomcat对Servlet版本的支持关系如表2-1所示。
表2-1 Servlet与Tomcat版本支持
Servlet 版本号 | Tomcat 版本号 | Servlet版本号 | Tomcat版本号 |
---|---|---|---|
Servlet2.4 | Tomcat5.x | Servlet3.0 | Tomcat7.x |
Servlet2.4 | Tomcat6.x | Servlet3.1 | Tomcat8.x |
2.2 Servlet 基础
2.2.1 用记事本写一个 Servlet
- 编写HelloServlet.java
使用记事本编写HelloServlet.java 文件,代码如下:
import javax.servlet.ServletException;
import java.io.*;
import javax.servlet.http.*;
public class HelloServlet extends HttpServlet
{
//重写了父类HttpServlet中的doGet()方法,用于对GET请求方法做出响应
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException,IOException
{
PrintWriter out = resp.getWriter(); //得到PrintWriter对象
out.println("Hello Servlet"); //向客户端发送字符数据
out.close();
}
}
- 编译HelloSerlet.java
把Tomcat自带的servlet-api.jar的路径加到classpath中,或者在命令行窗口中运行命令:
set classpath=%classpath%;D:\software\apache-tomcat-8.0.45\lib\servlet-api.jar
(这里,本书Tomcat的安装路径是E:\tormcat8。)
进入HelloServlet.java 所在目录,运行命令: javac HelloServlet.java 。 编译后得到HelloServlet.class字节码文件。
- 部署Servlet
在E:\tomcat8\webapps目录下,创建-一个文件夹hello,在hello目录下创建WEB-INF文件夹和Web.xml文件。Web.xml 代码如下(其中 部分表示注释):
<?xml version="1.0" encoding="UTF-8"?> <!--XML声明-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1"> <!--声明XML Schema的名称空间-->
<servlet>
<servlet-name>helloworld</servlet-name> <!--Servlet名称-->
<servlet-class>HelloServlet</servlet-class> <!--Servlet完全限定名-->
</servlet>
<servlet-mapping>
<servlet-name>helloworld</servlet-name> <!--Servlet名称-->
<url-pattern>/myhello</url-pattern> <!--Servlet的URL路径-->
</servlet-mapping>
</web-app>
在Web-INF目录下创建classes 文件夹,把前面编译得到的HelloServlet.class 复制至E:\tomcat8\webapps\hello\Web-INF\classes目录下。
在这里,hello 文件夹已成为一个Web应用,只不过是手工创建的。
- 访问HelloServlet
启动Tomcat服务器,在浏览器中输入: http://localhost:8080/hello/myhello (注意,这里通过调用中的值来找寻相应的Servlet。)
网页输出:
Hello Servlet
2.2.2 Servlet 体系结构
Servlet3.1 API有以下4个Java包。
①javax.servlet: 其中包含定义Servlet和Servlet容器之间契约的类和接口。
②javax.servlet.http: 其中包含定义HTTP Servlet和Servlet容器之间契约的类和接口。
③javax.servlet.annotation:其中包含标注Servlet、 Filter、 Listener 的标注。它还为被标注元件定义元数据。
④javax.servlet.descriptor:其中包含提供程序化登录Web应用程序的配置信息的类型。Servlet技术的核心是Servlet,它是所有Servlet类必须直接或间接实现的一个接口。Servlet接口定义了Servlet 与Servlet 容器之间的契约,Servlet 容器将Servlet 类载入内存,并在Servlet实例上调用具体的方法。用户请求致使Servlet容器调用Servlet的Service方法,并传入一个ServletRequest 实例和一个ServletResponse 实例。ServletRequest 中封装了当前的HTTP请求。ServletResponse则表示当前用户的HTTP响应,使得将响应发回给用户变得十分容易。
2.2.3 Servlet 接口
在Tomcat的有关Servlet API的文档中有关于Servlet接口的介绍。可以通过运行Tomcat服务器,在htp://localhost:8080/docs/servletapi/index.html页面看到。
javax.servlet.Servlet的定义如下:
public interface Servlet
该接口中定义了一下 5 种方法。
①(init): 在Servlet实例化后,Servlet 容器会调用该方法,初始化该对象。init0方法有一个类型为ServletConfig的参数, Servlet容器通过这个参数向Servlet传递配置信息。Servlet使用ServletConfig 对象从Web应用程序的配置信息中获取以名-值对形式提供的初始化参数。
②service(): 容器调用service0方 法来处理客户端的请求。
③destroy0: Servlet 的销毁方法。容器在终止Servlet服务前调用此方法。
④getServletConfig0: 该方法返回容器调用init(方 法时传递给Servlet 对象的ServletConfig对象,ServletConfig 对象包含了Servlet 的初始化参数。
⑤getServletInf(): 返回一个String类型的字符串,其中包括了关于Servlet的信息。例如,作者、描述信息等。
2.2.4 Servlet 生命周期
Servlet生命周期可被定义为从创建直到毁灭的整个过程。以下是Servlet遵循的过程。
(1) Servlet 通过调用init ()方法进行初始化。
(2) Servlet 调用service()方法来处理客户端的请求。
(3) Servlet通过调用destroy()方法终止(结束)。
(4) Servlet 是由JVM的垃圾回收器进行垃圾回收的。
1. init() 方法
init()方法被设计成只调用一一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。Servlet创建于用户第一次调用对应于该Servlet的URL时,但也可以指定Servlet在服务器第一次启动时被加载。
当用户调用一个Servlet时,就会创建一个Servlet实例,每一个用户请求都会产生一个新的线程,适当的时候移交给doGet()或doPost()方法。init0方法简 单地创建或加载- -些数据,这些数据将被用于Servlet的整个生命周期。
init 方法如下:
public void init(ServletConfig config) throws ServletExeption {
// 初始化代码...
}
2. service() 方法
service()方法是执行实际任务的主要方法。Servlet 容器调用service0方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回客户端。每次服务器接收到一个Servlet请求时,服务器会产生一个新的线程并调用服务。servic()方法检查HTTP请求类型(GET、POST、PUT、DELETE等),根据请求类型不同分别调用doGet、doPost、 doPut、 doDelete 等方法。
public void service (ServletRequest request, ServletResponse response)
throws ServletException, IOException {
}
service()方法由容器调用,只需要根据来自客户端的请求类型来重写doGet()或doPost()方法即可。doGet())和 doPost()方法是每次服务请求中最常用的方法。
3. doGet() 方法
GET请求来自一个URL的正常请求,或者来自一个未指定METHOD的HTML表单,它由doGet()方法处理。
public void doGet (HttpServletRequestrequest, HttpServletResponse response)
throws ServletException, IOException {
// Servlet代码
}
4. doPost()方法
POST请求来自一个特别指定了METHOD为POST的HTML表单,它由doPost()方法处理。
public void doPost (HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
// Servlet代码
}
5. destroy() 方法
destroy()方法只会被调用一-次,在Servlet 生命周期结束时被调用。destroy()方法可以让Servlet关闭数据库连接、停止后台线程、把Cookie列表或单击计数器写入磁盘中,并执行其他类似的清理活动。在调用destroy()方法之后,servlet 对象被标记为垃圾回收。destroy()方法定义如下所示:
public void destroy () {
//清理代码...
}
2.2.5 Servlet 生命周期示例
Servlet实质,上就是Java类,我们将使用Eclipse来开发Servlet,以进行Servlet 的学习。
1. 创建Dynamic Web Project
在Eclipse中选择“File-→New→Projet…“选项,在弹出的“New Project” 对话框中选择Web中的"Dynamic Web Project",如图2-1所示。在弹出的“New Dynamic Web Project"对话框中,设定工程名为“ServletDemo",如图2-2所示(此处所使用的Eclipse版本详见本书资源tools文件夹下 eclpse-jee-oxygen-R-win32.zip,将其解压缩后双击eclipse.exe即)。
在如图2-3所示的ServletDemo工程目录结构中,右击src 文件夹,创建Package 名为““ com.mialab.servlet demo”再在com.mialab.servlet demo包中创建Servlet。
2. 开发Servlet
我们在com.mialab.servlet_demo包中创建LifeServlet。右击com.mialab.servlet _demo包,选择“New- +Servlet"选项,弹出“Create Servlet"对话框,在此对话框中输入Servlet的名称"LifeServlet",如图2-4 所示。单击“Next”按钮后,选中“init"、 “destroy”等method,如图2-5所示。
如果servlet-api.jar未加入ClassPath (或者Java Build Path),便会出现如图2-6所示的错误。我们只需把鼠标指针移入代码错误处,如把鼠标指针移入“HttpServlet” 中,稍停片刻,便会弹出一个错误信息提示框,如图2-7所示,单击“Fix project setup…"超链接。
在弹出的"Project Setup Fixes” 对话框中,把E:tomcat8\lib 中的servlet-apijar 加入ServletDemo工程的Build Path,如图2-8所示。
LifsServlet.java 主要代码如下:
package com.mialab.servlet_demo;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class LifeServlet
*/
@WebServlet(asyncSupported = true, urlPatterns = { "/LifeServlet" })
public class LifeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public LifeServlet() {
super();
// TODO Auto-generated constructor stub
System.out.println(this.getClass().getName() + "的构造方法被调用");
}
/**
* @see Servlet#init(ServletConfig)
*/
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
System.out.println(this.getClass().getName() + "的init()方法被调用");
}
/**
* @see Servlet#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
System.out.println(this.getClass().getName() + "的destroy()方法被调用");
}
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
//protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
System.out.println(this.getClass().getName() + "的doGet()方法被调用");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
3. 部署并测试
在Eclipse中部署并运行LifeServlet.启动Eclipse中配置好的Tomcat,访问LifeServlet的URL为http://localhost:8080/ServletDemo/LifeServlet。
(可参见第1章: Eclipse 自动部署项目到 Tomcat 的 webapps 目录。也可以右击 LifeServlet.java ,在弹出的快捷菜单中选择“Run As→Run on Server”选项。)
Eclipse中的控制台将输出:
com.mialab.servlet_demo.LifeServlet的构造方法被调用
com.mialab.servlet_demo.LifeServlet的init()方法被调用
com.mialab.servlet_demo.LifeServlet的doGet()方法被调用
打开命令行窗口,在E:\tomcat8\bin路径下输入shutdown命令,关闭Tomcat服务器,如图2-9所示。
Eclipse中的控制台将输出:
2.3 Servlet API编程常用接口和类
2.3.1 GenericServlet 类
GenericServlet 类的部分源码如下:
package javax.servlet;
...
public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {
...
//用 transient 关键字标记的成员变量不参与序列化过程
private transient ServletConfig config;
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public ServletContext getServletContext() {
return getServletConfig().getServletContext();
}
@Override
public String getInitParameter (String name) {
return getServletConfig().getInitParameter(name) ;
}
@Override
public void init (ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
// NOOP by default
}
...
}
GenericServlet类是一个抽象类, 实现了Servlet 和ServletConfig接口,其作用如下。
(1)将init方法中的ServletConfig 赋给一个类中成员(ServletConfig config),以便可以通过调用get ServletConfig来获取。(关于transient关键字的说明: Java 的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient 型变量的值不包括在序列化的表示中,然而,非transient型的变量是被包括进去的。)
(2)为Servlet接口中的所有方法提供默认的实现。
(3)可以通过覆盖没有参数的init 方法来编写初始化代码,ServletConfig 则仍然由GenericServlet实例保存。
(4)开发者可以在不用获得ServletConfig 对象的情况下直接调用ServletConfig 的方法,如上述代码中的getServletContext()方法。
【示例】使用 GenericServlet 类
关于使用GenericServlet类的示例,可参见MyGenericServlet.java的代码(源码包资源第2章ServletDemo工程中的src/com.mialab.servlet_demo包),访问MyGenericServlet的URL是 http://ocalhost:8080/ServletDemo/generic。
2.3.2 HttpServlet类
HttpServlet类扩展了GenericServlet 类,其部分代码如下:
package javax .servlet.http;
...
public abstract class HttpServlet extends GenericServlet {
...
private static final String METHOD DELETE = "DELETE";
private static final String METHOD HEAD = "HEAD";
private static final String METHOD GET= "GET";
private static final String METHOD OPTIONS = "OPTIONS";
private static final String METHOD POST = "POST";
private static final String METHOD PUT = "PUT";
private static final String METHOD TRACE = "TRACE";
protected void doGet (HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
...
}
protected void doPost (HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
...
}
//添加新的Service方法
protected void service (HttpServletRequestreq, HttpServletResponseresp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
...
doGet (req, resp);
} else if (method.equals(METHOD_HEAD)) {
...
doHead (req, resp);
} else if (method.equals(METHOD_POST)) {
doPost (req, resp);
}else {...
}
}
//覆盖的Service方法
@Override
public void service (ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request F (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException ("non-HTTP request or response") ;
}
service request, response);
}
}
HttpServlet覆盖了GenericServlet 中的Service 方法,并添加了一个新Service 方法。
新Service方法接收的参数是HttpServletRequest 和HttpServletResponse,而不是Servlet-Request和ServletResponse。
原始的Service 方法将Servlet 容器的request 和response 对象分别转换成HttpServlet-Request和HtpServletResponse,并调用新的Service方法。
HttpServlet中的Service 方法会检验用来发送请求的HTTP方法(通过调用request.getMethod来实现)并调用以下方法之一 : doGet、 doPost、doHead、doPut、doTrace、doOptions和doDelete。在这7种方法中,doGet 和doPost是最常用的。所以,不再需要覆盖Service方法了,只须覆盖doGet或者doPost即可。
2.3.3 ServletConfig 接口
Tomcat初始化一个Servlet 时,会将该Servlet的配置信息封装到一个ServletConfig 对象中,通过调用init(ServletConfig config)方法将ServletConfig对象传递给Servlet。
ServletConfig接口的常用方法如表2-2所示。
表 2-2 ServletConfig 接口的常用方法
方法说明 | 功能描述 |
---|---|
ServletContext getServletContext() | 获取ServletContext对象 |
String getServletName() | 返回当前Servlet的名称 |
String getInitParameter(String name) | 根据初始化参数名称返回对应的初始化参数值 |
Enumeration getInitParameterNames() | 返回一个Enumeration对象,其中包含了所有的初始化参数名 |
【示例】 ServletConfig 接口的使用。
ServletConfigDemoServlet.java主要代码如下:
package com.mialab.servlet_demo;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletConfigDemoServlet extends HttpServlet {
private ServletConfig servletConfig;
@Override
public void init(ServletConfig config) throws ServletException {
this.servletConfig = config;
System.out.println("-----------" + servletConfig + "-----------");
}
@Override
public ServletConfig getServletConfig() {
return servletConfig;
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 使用ServletConfig对象获取初始化参数
ServletConfig servletConfig = getServletConfig();
System.out.println("-----------" + servletConfig + "-----------");
String poet = servletConfig.getInitParameter("poet");
String poem = servletConfig.getInitParameter("poem");
// 设置响应到客户端的文本类型为HTML
response.setContentType("text/html;charset=UTF-8");
// 获取输出流
PrintWriter out = response.getWriter();
out.print("<p>获取ServletConfigDenoServlet的初始化参数:");
out.println("</p><p>poet参数的值:" + poet);
out.println("</p><p>poem参数的值:" + poem + "</p>");
out.append("Served at:").append(request.getContextPath());
}
}
Web.xml中关于ServletConfigDemoServlet 的配置如下:
<servlet>
<servlet-name>myServletConfig</servlet-name>
<servlet-class>com.mialab.servlet_demo.ServletConfigDemoServlet</servlet-class>
<init-param>
<param-name>poet</param-name>
<param-value>纳兰容若</param-value>
</init-param>
<init-param>
<param-name>poem</param-name>
<param-value>我是人间惆怅客</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>myServletConfig</servlet-name>
<url-pattern>/myServletConfig</url-pattern>
</servlet-mapping>
访问 ServletConfigDemoServlet 的 URL:
http://localhost:8080/ServletDemo/myServletConfig
输出结果:
获取ServletConfigDemoServlet的初始化参数:
poet参数的值:纳兰容若
poem参数的值:我是人间惆怅客
Served at: /ServletDemo
最后报错不知道为什么,看到的大佬帮解答下 (_)/
2.3.4 HttpServletRequest 接口
HttpServletRequest接口继承自ServletRequest接口,专门用来封装HTTP请求消息。由于HTTP请求消息分为请求行、请求消息头和请求消息体3部分,故而在HttpServletRequest接口中定义了获取请求行、请求消息头和请求消息体的相关方法,以及存取请求域属性的方法。
1. 获取请求行信息
HTTP_请求报文的请求行由请求方法、请求URL和请求协议及版本组成。HttpServletRequest接口对请求行各部分信息的获取方法如表2-3所示。
表 2 - 3 获取请求的相关方法
方法说明 | 功能描述 |
---|---|
String getMethod() | 用于获取 HTTP 请求消息中的请求方式(如GET、POST等) |
String getRequestURI() | 用于获取请求行中资源名称部分,即位于URL的主机和端口之后、参数部分之前的部分 |
String getQueryString() | 用于获取请求行中的参数部分,也就是资源路径后面(? )以后的所有内容。其只对GET有效 |
String getProtocol() | 获取请求行中的协议名和版本 |
String getContextPath() | 获取请求URL中属于Web应用程序的路径。这个路径以“/"开头,表示整个Web站点的根目录,路径结尾不含 “/” |
String getServletPath() | 获取Servlet所映射的路径 |
String getRemoteAddr() | 用于获取请求客户端的IP地址 |
String getRemoteHost() | 用于获取请求客户端的完整主机名 |
String getScheme() | 用于获取请求的协议名,如 HTTP 等 |
StringBuffer getRequestURL() | 获取客户端发出请求时的完整URL,包括协议、服务器名、端口号、资源路径等信息,但不包括后面的查询参数部分 |
【示例】使用HttpServletRequest接口获取请求行信息。
关于使用 HttpServletRequest
接口获取请求行信息的示例,可参见RequestLineServet.java
的代码(源码包见本书资源第2章 ServletDemo
工程中的 src/com.mialab.servlet_demo
包),访问 RequestLineServlet
的 URL
是http://localhost:8080/ServletDemo/RequestLineServlet
2. 获取请求消息头
当请求Servlet时,需要通过请求头向服务器传递附加信息。HTTP常见的请求头如表2-4 所示。
表2-4 HTTP 常见的请求头
请求头名称 | 说明 |
---|---|
Host | 初始 URL 中的主机和端口 |
Connection | 表示是否需要持久连接 |
Accpet | 浏览器可以接收的 MIME 连接 |
Accpet-Charset | 浏览器发给服务器,声明浏览器支持的编码类型 |
Content-Length | Content-Length用于描述HTTP消息实体的传输长度。在HTTP协议中,消息实体长度和消息实体的传输长度是有区别的,例如,在GZIP压缩下,消息实体长度是压缩前的长度,消息实体的传输长度是GZIP压缩后的长度 |
Cache-Control | 指定请求和响应遵循的缓存机制 |
User-Agent | User Agent的中文名为用户代理,简称UA,它是一一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU类型、浏览器类型及版本、浏览器渲染引擎、浏览器语言、浏览器插件等 |
Cache-Type | 表示请求内容的MIME类型 |
Cookie | 表示客户端的 Cookie 信息,即告诉服务器,上次访问时,服务器写了哪些 cookie 到客户端 |
HttpServletRequest接口中定义的用于获取HTTP请求头字段的方法,如表2-5所示。
表 2- 5 获取请求消息头的方法
请求头名称 | 说明 |
---|---|
String getHeader(String name) | 用于获取一个指定头字段的值 |
Enumeration getHeaderNames() | 用于获取一个包含所有请求头字段的 Enumeration 对象 |
Enumeration getHeaders(String name) | 返回一个Enumeration 集合对象,该集合对象由请求消息中出现的某个指定名称的所有头字段值组成 |
int getIntHeader(String name) | 用于获取指定名称的头字段,并将其值转换为int 类型 |
Cookie[] getCookies() | 返回一个数组包含客户端请求的所有 Cookie 对象,如果没有发送任何信息,则这个方法返回 null |
String getContentType() | 用于获取 Content-Type 头字段的值 |
int getContentLength() | 用于获取 Content-Length 头字段的值 |
String getCharacterEncoding() | 用于返回请求消息的实体部分的字符集编码,通常是从 Content-Type 头字段中提取 |
【示例】使用HttpServletRequest接口获取请求头信息。
使用HttpServletRequest接口获取请求头信息的示例,可参见RequestHeadInfoServlet.java的代码(源码第2章ServletDemo 工程src.com.mialab.servlet demo 包),访问 RequestLineServlet 的 URL 是 http://locahost:8080/ServletDemo/RequestHeadInfoServlet。
3. 获取请求参数
在实际开发中,经常需要获取用户提交的表单数据。为了方便获取表单中的请求参数,在HttpServletRequest接口的父类ServletRequest 接口中定义了一系列获取请求参数的方法,如表2-6所示。
表 2 - 6 获取请求参数的方法
方法说明 | 功能描述 |
---|---|
String getParameter(String name) | 用于获取某个指定名称的参数值 |
Enumeration getParameterNames() | 返回一个包含请求消息中所有参数名的Enumeration对象 |
String[] getParameterValues(String name) | 根返回由name指定的用户请求参数对应的一组值 |
Map getParameterMap() | 用于将请求消息中的所有参数名和值装进一个 Map对象中返回 |
【示例】使用HttpServletRequest接口获取请求参数。
关于使用 HttpServletRequest 接口获取请求参数的示例,可参见 RequestParaServlet.java 和person_ info.html( 源码包见第2章的ServletDemo工程),先访问person_info.html,填写个人信息,再提交给RequestParaServlet处理。
2.3.5 HttpServletResponse接口
HttpServletResponse接口继承自ServletResponse 接口,专门用来封装HTTP响应消息。由于HTTP响应消息分为状态行、响应消息头、消息体三部分,于是在HttpServletResponse接口中也相应定义了向客户端发送响应状态码、响应消息头、响应消息体的方法。
1. 响应状态码
HTTP协议响应报文的响应行,由报文协议和版本,以及状态码和状态描述构成。
当Servlet向客户端回送响应消息时,需要在响应消息中设置状态码。常见的响应状态码如下: 200表示请求成功; 500 表示服务器内部错误; 404 表示请求的资源(网页等)不存在;302表示资源(网页等)暂时转移到其他URL等。
HttpServletResponse按口提供的设置状态码开生成啊应状态行的万法有以下儿种。
(1) setStatus(int status)方法: setStatus(int status)方法用于设置HTTP响应消息的状态码,并生成响应状态行。正常情况下,Web服务器会默认产生一个状态码为200的状态行。
(2) sendError(int sc)方法和sendError(int sc, String msg)方法:第1个方法只是发送错误信息的状态码;而第2个方法除了发送状态码外,还可以增加一条用于提示说明的文本信息,该文本信息将出现在发送给客户端的正文内容中。
要说明的是,在实际开发中,一般不需要人为地修改设置状态码,容器会根据程序的运行状况自动响应发送响应的状态码。
2. 响应消息头
HttpServletResponse接口中定义了-一些设置HTTP响应头字段的方法,如表2-8所示。
表 2 - 8 设置响应头字段的方法
方法 | 功能描述 |
---|---|
void setContentType(String type) | 设置Servlet输出内容的MIME类型 |
void setContentI ength(int len) | 设置响应消息的实体内容的大小,单位为字节 |
void setHeader(String name, String value) | 设置HTTP协议的响应头字段。name指定响应头字段的名称, value 指定响应头字段的值 |
void setCharacterEncoding(String charset) | 设置HTTP协议的响应头字段。name 指定响应头字段的名称, value 指定响应头字段的值 |
void addCookie(Cookie cookie) | 为Set-Cookie消息头增加-一个值,Set-Cookie 消息头表示应该记录下来的Cookie,即把Cookie发送给客户端 |
void setLocale(Locale loc) | 用于设置响应消息的本地化信息。对HTTP来说,就是设置Content-Language响应头字段和Content-Type头字段中的字符集编码部分 |
【示例】响应消息头
关于响应消息头示例,可参见ResponseHeadServlet.java的代码(源码见第2章ServletDemo工程的src/com.mialab.servlet _demo包),访问ResponseHeadServlet的URL是http://ocahost:.8080/ServletDemo/ResponseHeadServlet
3. 响应消息体
HttpServletResponse接口提供了两个获取不同类型输出流对象的方法,如表2-9所示。
表 2-9 HttpServletResponse 接口获取不同类型输出对象的方法
方法 | 功能描述 |
---|---|
ServletOutputStream getOutputStream() | 返回字节输出流对象 ServletOutputStream |
PrintWriter getWriter() | 返回字符输出流对象 |
【示例】响应消息体。
响应消息体示例,可参见ResponsePicServlet.java的代码(第2章ServletDemo 工程的src/com.mialab.servlet_demo包),访问 ResponsePicServlet 的 URL 是 http://localhost:8080/ServletDemo/ResponsePicServlet
没跑出来
2.3.6 ServletContext 接口
Servlet 容器在启动一个 Web 应用时,会为该应用创建一个唯一的 ServletContext 对象供该应用中的所有Servlet 对象共享。Servlet 对象可以通过 ServletContext 对象来访问容器中的各种资源。获得 ServletContext 对象可以使用以下两种方式。
① 通过 ServletConfig 接口的 getServletContext() 方法获得 ServletContext 对象。
② 通过GenericServlet 抽象类的 getServletContext() 方法获得 ServletContext 对象,实质上该方法也调用了ServletConfig 的 getServletContext() 方法。
该方法也调用了 ServletConfig 的 getServletContext() 方法。
1. 获取 Web 应用的初始化参数
ServletContext 接口中定义了获取 Web 应用范围的初始化参数的方法。
(1)方法声明: public String getInitParameter(String name)
。
作用:放回 Web 应用范围指定的初始化值。在 Web.xml 中使用 元素表示应用范围内的初始化参数。
(2)方法声明: public Enumeration getInitParaNames(String name)。
作用:返回 Web 应用范围内指定的初始化参数值。在 Web.xml 中使用 元素表示应用范围内的初始化参数。
作用:返回一个包含所有初始化参数名称的 Enumeration 对象。
【示例】使用 ServletConext 接口获取 Web 应用的初始化参数。