Download - 第十一章 Servlet 程序设计

Transcript
Page 1: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版)

1

第十一章 Servlet 程序设计

郑莉

Page 2: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

2

目录• 11.1 Java 网络程序设计的基本概念• 11.2 Servlet 基础• 11.3 Servlet 的生命周期• 11.4 与客户端交互• 11.5 客户端跟踪• 11.6 协作与通讯• 11.7 程序举例 • 11.8 本章小结

Page 3: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

3

• 网络将世界联系在一起,使世界变得更加丰富多彩。同时网络互连是一个内容丰富而复杂的主题,所以这方面的程序设计涉及面很广且不易掌握

• 与其他语言相比, Java 语言在网络应用程序方面具有一定的优势。 Java 提供了很多内置的网络功能,使得基于Internet 和 Web 的应用开发变得更加容易

11.1 Java 网络程序设计的基本概念

Page 4: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

20

11.1.5 Servlet

•Servlet▫是用 java 技术来实现 CGI ( Common

Gateway Interface, 通用网关接口)功能的编程

▫介于浏览器(或其他 HTTP 客户端)与服务器之间,起到桥梁的作用。具体作用为: 读取客户端发送的数据 获取客户请求( request )中所包含的信息 产生响应结果,并将结果包含到一个文件中,比如

HTML 文件中 设置 HTTP 响应参数,比如告诉浏览器,文件类

型为 HTML 将文件返回给客户端

11.1 Java 网络程序设计的基本概念

Page 5: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

21

• Servlet 具有很多优点▫ 高效率

通过 Servlet , Java 虚拟机用轻量级的 Java 线程处理每个请求。同时有 N 个请求的情况下, CGI 程序需要被调入到服务器内存 N次;对于 Servlet 将开启 N 个线程,但仅仅调入一个 Servlet 实例到内存中

▫ 应用方便 Servlet 在解析和译码 HTML 数据,读取设置 HTML 标题,操作

Cookie 等很多方面,应用更加方便。继承自 java 的特点,其可靠性与复用性好

▫ 功能强大 Servlet 可以直接与 Web 服务程序对话;多个 Servlet 可以共享

数据; Servlet 与数据库的连接也比较简单等

11.1 Java 网络程序设计的基本概念

11.1.5 Servlet( 续 )—— 优点

Page 6: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

22

▫ 便携性好 Servlet 用 Java 语言编写,遵循标准的 API 。因此 Servlet

编写的程序可以无任何修改的在 Apache , Microsoft Internet Information Server(IIS) , IBM WebSphere ,或者 StarNine WebStar 上运行。同样具有一次编译,到处运行移植性好的特点

▫ 安全 基于 Java 语言的安全特性, Servlet 的安全性也比较可靠

▫ 成本低 有很多免费或相对比较便宜的 Web 服务器,适合做个人的或

者小容量的网站。而且很多商业级的 Web 服务器相对也比较便宜。而且使一个服务器支持 Servlet 所需的额外花费也很少

11.1 Java 网络程序设计的基本概念

11.1.5 Servlet( 续 )—— 优点

Page 7: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

23

11.2 Servlet 基础

• 本节内容包括▫ Servlet 容器、web 服务器、应用服务器▫ Web 应用程序▫ Servlet API

▫ Servlet 的基本结构▫ Servlet 编译和安装

Page 8: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

24

• Servlet 容器▫ 也称为 Servlet引擎▫ 是一个编译好的可执行程序,它是 web 服务器与 servlet

间的媒介▫负责将请求翻译成 Servlet 能够理解的形式传递给 servlet ,

同时传给 servlet 一个对象使之可以送回响应▫负责管理 servlet 的生命周期

11.2 Servlet 基础

11.2.1 Servlet 容器、Web 服务器和应用服务器

Page 9: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

25

• web 服务器▫ 能够处理 Http 请求的服务器▫ 可以提供静态页面、图像等▫ 有的 web 服务器也支持动态页面的生成,支持

JSP 、 Servlet 等,具有 JVM• 应用服务器

▫ 可以处理基于多种协议的请求,当然也包括Http 协议▫ 可以支持 servlets 和 JSP ,以及所有其他 J2EE 服务,

包括 JNDI 、 EJBs 、 JMS 等

11.2 Servlet 基础

11.2.1 Servlet 容器、Web 服务器和应用服务器

Page 10: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

26

• servlet 容器可以与 web 服务器协作提供对 servlet 的支持• 一些 servlet 容器(如 Apache Tomcat )自己也可以作为独立的 web 服

务器运行• 随着 servlet 和 JSP 的流行,一些主要的 Web 服务器和应用程序服务器都

直接或者通过插件支持 servlet 和 JSP 。如:▫ Sun ONE Application Server▫ Lotus Domino Go WebServer▫ BEA weblogic Tengah Server▫ WebSphere 应用服务器▫ Jigsaw▫ NetForge▫ AcmeServer▫ Mot Bays Jetty

11.2 Servlet 基础

11.2.1 Servlet 容器、Web 服务器和应用服务器

Page 11: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

30

11.2.2 Web 应用程序

• Web 应用程序

▫组成部分包括 servlet 、 JSP 及其支持文件

▫ 这些组成部分需要进行部署

▫ 通常部署在 Tomcat 的 webapps子目录中。一般其目

录结构包括根目录 (context root) 和几个子目录,也

可以把子目录捆绑到一个类型为 war 的存档文件中

11.2 Servlet 基础

Page 12: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

32

11.2.3 Servlet API

• Servlet API

▫ 开发 servlet 和 JSP 程序,需要参考Servlet API 文档

▫ 包含 javax.servlet 和 javax.servlet.http

两个包中▫ 所有 servlet须实现

javax.servlet.Servlet 接口,通常继承如下两个类中的一个 GenericServlet

HttpServlet

Servlet

Generic servlet

Http servlet

My servlet

11.2 Servlet 基础

Page 13: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

33

• Servlet 接口▫ 所有 servlets 必须实现这一接口▫ Servlet 接口的所有方法都是被自动调用的

• HttpServlet 类▫ 覆盖了 javax.servlet.Servlet 接口的 service 方法

service方法由 servlet容器调用,对客户端的请求作出响应。它会根据请求类型的不同自动调用 doGet 或 doPost等方法

▫ 能够处理两个最普通的 HTTP 请求类型 doGet 方法 响应 get 请求 doPost 方法响应 post 请求

11.2.3 Servlet API( 续 )

11.2 Servlet 基础

Page 14: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

34

11.2.3 Servlet API( 续 )

• HttpServletRequest 接口▫ 由 Web 服务器创建该接口的一个对象,并将其传递给 servlet

的 service 方法▫该类对象含有来自于客户端的请求

• HttpServletResponse 接口▫ 由 Web 服务器创建该接口的一个 对象,并将其传送给

servlet 的 service 方法▫ 通过该类对象服务器端可以对客户端发出响应信息

11.2 Servlet 基础

Page 15: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

35

11.2.4 Servlet 的基本结构• Servlet 的基本结构

▫ 一般扩展自 HttpServlet▫ 复写 doGet 或者 doPost 方法

doGet 或 doPost都接收两个类型的参数:HttpServletRequest 和 HttpServletResponse

通过 HttpServletRequest ,可以得到所有的输入数据,比如表单数据、HTTP 请求报头等客户信息

通过 HttpServletResponse 可以指定输出信息 由于 doGet 和 doPost 方法可能生成异常,必须在方法名称后声明抛出异常或者用 try-catch 语句处理异常

11.2 Servlet 基础

Page 16: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

36

• GET 请求是 WEB 浏览器请求的常见类型,用来请求 Web页面。 本例中通过 doGet 方法处理 GET 请求。在 doGet 方法中通过HttpServletResponse 对象得到 PrintWriter ,然后将一个文档发给客户。最终在客户端生成一个网页import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class MyServlet extends HttpServlet {

public void doGet( HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

res.setContentType("text/html"); PrintWriter out = res. getWriter(); out.println("<HTML>"); out.println("<HEAD><TITLE>My First Servlet </TITLE></HEAD>"); out.println("<BODY>"); out.println("<B> First Servlet </B>"); out.println("</BODY></HTML>");}

}

11.2.4 Servlet 的基本结构 (续 )—— 例 11-2

11.2 Servlet 基础

Page 17: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

37

11.2.5 Servlet 编译和安装• 编译——在设置好 path 和 classpath 的前提下, servlet 的编译和普

通的 java 程序完全相同▫ 可以通过 javac.exe 编译,比如可以在 Dos环境下输入:

javac MyServlet.java▫ 也可以通过集成开发环境 (IDE) 编译

• 复制——编译成功之后,将生成的类文件复制到相应的目录下即可。在Tomcat 服务器上,此目录可能是 install_dir\webapps\ROOT\WEB-INF\classes\

• 运行——启动 Tomcat 服务器,在地址栏输入 http://localhost:8080/servlet/MyServlet

11.2 Servlet 基础

Page 18: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

38

11.3 Servlet 的生命周期• 首先服务器仅创建 servlet 的一个实例

▫创建 servlet 实例时,它的 init 方法都会被调用• 针对每个客户端的每个请求,都会创建一个线程

▫该线程调用 servlet 实例的 service 方法▫ Service 方法根据收到 HTTP 请求得类型,调用

doGet , doPost 或者其他方法▫ 多个并发请求,一般会导致多个线程同时调用 service 方法,通

过单线程模式( SingleThreadModel )也可以规定任何时间仅允许一个线程运行

• 最后,卸载 servlet▫ 服务器调用 servlet 的 destroy 方法

Page 19: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

39

11.3 Servlet 的生命周期 (续 )——Servlet 生命周期示意图

Page 20: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

40

11.3.1 初始化• servlet 的初始化

▫ 服务器启动, servlet 被用户首次调用,服务器构造 servlet 实例之后,即立刻调用 init(ServletConfig) 方法,执行 servlet

实例的初始化工作▫ ServeletConfig 对象包含 servlet初始化所需的很多参数,比

如计数器、默认值等▫ init 方法都会在 servlet 处理客户请求 (request) 之前被调用▫ 一旦 init 方法被调用,只有服务器通过 destroy 方法销毁

servlet 之后, init 方法才能再次被调用

11.3 Servlet 的生命周期

Page 21: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

41

11.3.1 初始化 (续 )

• init 方法的定义public void init(ServletConfig config) throws

ServletException

{

super.init(config);

String greeting = getInitParameter("greeting");

// Initialization code…

}

11.3 Servlet 的生命周期

Page 22: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

42

11.3.2 销毁

• servlet 的销毁▫ 服务器卸载 servlet 实例之前,需要先调用 servlet 的

destroy 方法 释放 servlet 所获得的资源 使 servlet 有机会关闭数据库连接、停止后台运行的线程、将

cookie列表和点击数写入到磁盘 执行其他清理活动

11.3 Servlet 的生命周期

Page 23: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

43

11.4 与客户端交互

• HTTP servlet 与客户端的交互▫ 通过 service 方法处理客户端的请求

▫ service 方法根据请求 (request) 类型的不同,调用不同的方法 对于 GET 请求,调用 doGet( ) 方法进行处理 对于 POST 请求,调用 doPost( ) 方法进行处理

Page 24: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

44

11.4.1 提取 Servlet 信息• 注册的 servlet都有相关的很多初始化参数

▫ 这些初始化参数写在 web.xml 中,具体语法格式请参阅Tomcat 文档

▫ getInitParameter() 方法 可以得到 servlet初始化的一些参数 返回一个指定参数的值( String 类型) 如果指定参数不存在,则返回 null

▫ getInitParameterNames() 方法 可以得到初始化参数名称 返回 String 类型的 Enumeration 类型数据 如果不存在初始化参数,则返回一个 null 的 Enumeration

11.4 与客户端交互

Page 25: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

45

• 通过 servlet初始化参数建立一个数据库连接的程序段如下java.sql.Connection con = null;public void init(ServletConfig config) throws ServletException {

super.init(config);String host = getInitParameter("host");int port = Integer.parseInt(getInitParameter("port"));String db = getInitParameter("db");String user = getInitParameter("user");String password = getInitParameter("password");String proxy = getInitParameter("proxy");con = establishConnection(host, port, db, user, password, proxy);

}

11.4 与客户端交互

11.4.1 提取 Servlet 信息 (续 )—— 通过初始化建立数据库连接

Page 26: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

46

• 输出全部初始化参数名称import java.io.*;import java.util.*;import javax.servlet.*;public class PrintInitParaNames extends GenericServlet {

public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {

res.setContentType("text/plain"); PrintWriter out = res.getWriter(); out.println("Init Parameters As Following:"); Enumeration enum = getInitParameterNames(); while (enum.hasMoreElements()) { String name = (String) enum.nextElement(); out.println(name ": " + getInitParameter(name));

} }}

11.4 与客户端交互

11.4.1 提取 Servlet 信息 (续 )——PrintInitParaNames.java

Page 27: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

47

11.4.2 提取服务器信息

• servlet 可以得到很多服务器相关的信息,同时可以将这些信息发送到客户端▫ getServerName() 返回服务器名称▫ getServerPort() 返回服务器监听端口▫ getServerInfo()输出服务器程序和版本,之间用“ /”分开▫ getAttribute() 返回服务程序的属性▫ 得到路径相关的信息

public String HttpServletRequest.getPathInfo()

public String HttpServletRequest.getPathTranslated()

11.4 与客户端交互

Page 28: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

48

• 提取服务器信息举例 import java.io.*;import java.util.*;import javax.servlet.*;public class ServerSnoop extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { res.setContentType("text/plain"); PrintWriter out = res.getWriter(); out.println("req.getServerName() output: " +

req.getServerName()); out.println("req.getServerPort() output: " + req.getServerPort()); out.println("getServletContext().getServerInfo() output: "

+ getServletContext().getServerInfo() ); out.println("getServletContext().getAttribute(\"attribute\") output:

" + getServletContext().getAttribute("attribute") ); }}

11.4 与客户端交互

11.4.2 提取服务器信息 (续 )—— 例 11-3

Page 29: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

49

11.4.3 提取客户端信息• 服务器可以从 request 得到很多客户端的信息

▫ getRemoteAddr() :得到 IP地址▫ getRemoteHost() :得到客户端机器的名称▫利用 InetAddress.getByName() 方法可以将 IP地址或客户端

机器名称转换成一个 java.net.InetAddress 类型的对象InetAddress remoteInetAddress =

InetAddress.getByName(req.getRemoteAddr());

通过获取客户端的地址,并判断是否隶属某个范围,可以限制某个地区的用户访问你的网站

11.4 与客户端交互

Page 30: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

50

11.4.3 提取客户端信息 (续 )• 服务器可以得到客户想做的事情

▫ 客户请求表现为表单数据,由“名 /值”对组成。当提交某一个网页的时候常常在浏览器地址栏中看到类似格式的数据格式name/value ,每对之间用 & 隔开,表达式为param1=value1&param2=value2&param3=value3…

▫ request.getParameter :得到表单参数的值▫ request.getParameterValues :得到多次出现的参数值▫ reques.getParameterNames :得到当前请求中所有参数的完整列表,调用形式如下 public String ServletRequest.getParameter(String name) public String[] ServletRequest.getParameterValues(String

name)

11.4 与客户端交互

Page 31: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

51

• 书本查询的一个 HTML 网页!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01

Transitional//EN"><HTML><HEAD><TITLE> A Sample Form for Query a Book </TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><FORM METHOD=GET ACTION="/Chapter11/QueryServlet">Book to look up: <INPUT TYPE="TEXT" NAME="Book"

VALUE="Java Servlet Programming"><!-- The default book to be looked up is: 《 Java Servlet

Programming 》 . --><INPUT TYPE=SUBMIT></FORM></BODY></HTML>

11.4 与客户端交互

11.4.3 提取客户端信息 (续 )——Query.html

Page 32: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

52

• 获取客户端信息的 servletimport java.io.*;import java.net.*;import javax.servlet.*;import javax.servlet.http.*;public class QueryServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException { res.setContentType("text/html;charset=UTF-8"); String queryBookValue=req.getParameter("Book"); PrintWriter out = res.getWriter(); out.println("The book you wanted is:"+queryBookValue); out.close(); }}

11.4 与客户端交互

11.4.3 提取客户端信息 (续 )——QueryServlet.java

Page 33: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

53

11.4 与客户端交互

11.4.3 提取客户端信息 (续 )——Query.html 与 QueryServlet 运行结果

Page 34: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

54

11.4.4 发送 HTML 信息• Web 服务器响应 (response) 的构成

▫状态行 由 http 版本 (HTTP/1.1) ,一个状态代码 (200) 和一段对应状态代码的

简短消息 (OK)组成▫ 一些响应报头、

Content-Type: text/html 指定后面文档MIME 类型,后面的其他报头可选。常用 MIME 类型有:

text/html : HTML 文档 text/plain : 纯文本 text/xml : XML image/jpeg : JEPG图像 application/msword : Microsoft Word 文档 application/pdf : crobat 文件 application/zip : Zip档案

▫ 一个空行和响应的文档

11.4 与客户端交互

Page 35: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

55

HTTP/1.1 200 OK //状态行Content-Type: text/html //报头Header2: ……HeaderN: …

//空行<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0

Transitional//EN"> // 文档<HTML><HEAD> head code </HEAD><BODY>…</BODY></HTML>

11.4.4 发送 HTML 信息 (续 )

11.4 与客户端交互

Page 36: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

56

• 向客户端输出一个简单网页,显示“Hello World!” import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class HelloWorld extends HttpServlet { public void doGet( HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter out = res.getWriter(); out.println("<HTML>"); out.println("<HEAD><TITLE>Hello

World</TITLE></HEAD>"); out.println("<BODY>"); out.println("<BIG>Hello World!</BIG>"); out.println("</BODY></HTML>"); }}

11.4 与客户端交互

11.4.4 发送 HTML 信息 (续 )—— 例 11-4

Page 37: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

57

• 程序说明▫ HelloWorld 继承了 HttpServlet ,然后重写 doGet 方法▫ 在 doGet 方法中,首先将 HTTP Content-Type 响应报头设置为 text/html ,即指定响应的类型为 HTML 文档;然后通过 getWriter() 得到 PrintWriter类型的一个对象 out ,按照HTML格式输出一个简单网页

• 运行结果

11.4 与客户端交互客户端跟踪

11.4.4 发送 HTML 信息 (续 )—— 例 11-4 运行结果

Page 38: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

58

11.5 客户端跟踪• 客户端跟踪

▫ HTTP 是无状态协议,服务器不能自动维护客户连接的上下文信息

▫许多情况下, Web 服务器必须要能够跟踪用户的状态 比如购物网站和电子邮件网站,当用户登录以后,其身份和

一系列的操作状态都需要被跟踪并保持▫ servlet API 提供了两种可以跟踪客户端状态的方法

Cookie Session

Page 39: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

59

11.5.1 使用 Cookie

• Cookie▫是 Web 服务器保存在用户硬盘上的一段文本, Web

服务器将它发送到浏览器▫之后,当再次访问同一网络时,浏览器将它原封不动

的返回▫其中的信息片断以‘名 /值’对 (name-value

pairs) 的形式储存▫使用这种方法,网站可以维护客户的连接。这种用途

可以体现在如下几点 在电子商务中标识用户,实现短期跟踪用户 记录用户名和用户密码,允许用户下次自动登陆 定制站点,记录用户的偏好 定向广告,记录用户感兴趣的主题,并显示与之相关的广告

11.5 客户端跟踪

Page 40: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

60

• 调用 Cookie 的构造方法可创建一个 cookie

▫构造方法接受两个字符串参数 cookie名称 cookie 的值

▫ 例如创建一个名为 CookieName ,值为 John 的 cookie ,可以使用下面的语句Cookie login = new Cookie(“CookieName”, ”John”);

11.5 客户端跟踪

11.5.1 使用 Cookie( 续 )——创建 Cookie 对象

Page 41: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

61

• 创建了一个名为 login 的 cookie 之后,可通过很多现有的方法设置 cookie 的值和属性▫ 可通过如下语句设置 cookie 的注释:

login.setComent(“You can get UserName form this cookie”);

▫创建 cookie 并将它发送到浏览器后,默认情况下,它是会话级的 cookie ,仅仅存储在浏览器内存中,用户退出浏览器后, cookie 将被删除;如果希望将 cookie 存储在磁盘上,则需要设定 MaxAge ,给出一个以秒为单位的生命周期,如下可以将生命设置为一天login.setMaxAge(60*60*24) // one day

▫ setPath() , setValue() , setVersion() , setDomain() ,setSecure() 等,相关的具体用法请查看 servlet API

11.5 客户端跟踪

11.5.1 使用 Cookie( 续 )—— 设置 Cookie属性

Page 42: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

62

• 刚创建的 cookie 存在于服务器内存中。必须将它发送到客户端, cookie才能真正的发挥作用。发送 cookie 需要使用 HttpServletResponse 的addCookie 方法,将 cookie插入到一个 HTTP 响应报头。发送的语句如下public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ Cookie login = new Cookie(“UserName”, ”John”); login.setComent(“You can get UserName form this cookie”); res.addCookie(login); //...}

11.5 客户端跟踪

11.5.1 使用 Cookie( 续 )—— 发送 Cookie 到客户端

Page 43: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

63

• 从客户端读取你感兴趣的 cookie ,需要两个步骤▫首先调用 request.getCookies 得到一个 Cookie 对象的数组▫然后调用每个 cookie 的 getName 方法,从数组中寻找所需的

cookieString nameString = “UserName”Cookie[] cookies = request.getCookies();for ( int i=0; i<cookies.length; i++) {

Cookie cookie = cookies[i];if (nameString.equals( cookie.getName()) ){ // do something …

// cookies.setMaxAge(0);}

}• 找到感兴趣的 cookie 之后,便可以操作此 cookie , 如通过 getValue 方法得到相关 cookie 的值,设置 MaxAge 等

11.5 客户端跟踪

11.5.1 使用 Cookie( 续 )——从客户端读取 Cookie

Page 44: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

64

11.5.2 使用 Session

• Session

▫ 一段时间内,单个客户与 web 服务器的一连串的交互过程▫ 在一个 Session 中客户可能会多次请求访问同一个网页,也有可

能请求访问各种不同的服务器资源,其间用户的状态需要跟踪并保持

▫ 存在于服务器端,不在网络上传送▫它的好处是可以用来记录客户端私有的信息,并且在时间范围内不会消失

11.5 客户端跟踪

Page 45: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

65

11.5.2 使用 Session( 续 )

• Session 的使用可以分为三个步骤▫ 获得一个 session

▫ 存储数据到 session 或从 session 读取数据▫销毁 session

11.5 客户端跟踪

Page 46: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

66

• 通过调用 httpServletRequest 的 getSession 方法可以得到一个sessionHttpSession session = request.getSession();

• 为了保持正确的会话,必须在发送任何文档到客户程序之前获得一个sessionpublic class SessionServlet extends HttpServlet { public void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Get the user's session HttpSession session = request.getSession(true); //... out = response.getWriter(); // ... }}

11.5 客户端跟踪

11.5.2 使用 Session( 续 )—— 获得一个 Session

Page 47: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

67

• Session ID

▫ Servlet 容器为 HttpSession分配的一个唯一标识符▫ 作为 Cookie保存在客户的浏览器中

• session cookie

▫ 每次客户发出HTTP 请求时, Servlet 容器可以从HttpRequest

对象中读取 Session ID ,然后根据 Session ID 在服务器端找到相应的 HttpSession 对象,从而获取客户的状态信息,这样的cookie叫做 session cookie

▫ 存储于浏览器内存中的,并不写到硬盘上的▫ 针对某一次会话而言,会话结束也就随着消失了

11.5 客户端跟踪

11.5.2 使用 Session( 续 )—— 存储或读取数据

Page 48: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

68

• URL 重写

▫ 浏览器不支持 Cookie ,或者将浏览器设置为不接受 Cookie 的情况,可通过 URL 重写来实现会话管理

▫向 URL 连接添加参数,并把 session ID 作为值包含在连接中。为 servlet 响应部分的每个连接添加 session ID ,可以使用一对方法 response.encodeURL() :使 URL 包含 session ID

response.encodeRedirectURL() :使用重定向

11.5 客户端跟踪

11.5.2 使用 Session( 续 )—— 存储或读取数据

Page 49: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

69

• 从 Session 中读取数据▫ session.getAttribute(“name”)

查找以前存储的值 如果不存在则返回 null 在调用此方法返回的对象前,一定要检查它是否为 null

• 向 session 中设置相关信息▫ setAttribute

替换掉此前设定的任何值▫ removeAttribute

移除而不是替换某个值

11.5 客户端跟踪

11.5.2 使用 Session( 续 )—— 存储或读取数据

Page 50: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

70

public class SessionServlet extends HttpServlet { public void doGet (HttpServletRequest

request,HttpServletResponse response) throws ServletException, IOException { // Get the user's session HttpSession session = request.getSession(true); SomeClass scl =

(SomeClass)session.getAttribute( "name1“ ); // If the user has no SomeClass object, create a new one if (scl == null) { scl = new SomeClass(); session.putAttribute( "name1", scl ); } //... }}

11.5 客户端跟踪

11.5.2 使用 Session( 续 )——SessionServlet.java

Page 51: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

71

• 销毁 Session▫意味着从系统删除 session 对象及其值▫ 自动销毁

在一段时间(时间长短依赖与 Web 服务器的设定)没有request 的情况下, Web 服务器会自动销毁 session

▫手动销毁 通过调用 session 的 invalidate 方法可以手动的销毁

session

▫ logout 在支持 servlet2.4 的服务器中,可调用 logout 将客户从

Web 服务器中注销,同时废弃所有与该用户相关联的会话 需要注意的是,这个动作会影响到此 servlet 之外的其他

servlet ,因此一定要与网站的其他开发人员协调使用

11.5 客户端跟踪

11.5.2 使用 Session( 续 )——销毁 Session

Page 52: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

72

11.6 协作与通信• 协作与通信

▫ 为了更好的响应客户端的请求, servlet 有时需要和网络上的其他资源进行通讯,比如 HTML 网页 其他 servlet

JSP 网页

▫ Servlet 协作通讯的第一步是获得分发器 (dispatcher) ,即 RequestDispatcher 接口的一个对象

Page 53: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

73

• RequestDispatcher 接口▫ 产生一个 RequestDispatcher 接口的对象

RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(

"/SomePath/SomeString"); 通过设置字符串参数,可以获得 servlet , HTML 网页, JSP 网页等“资源”

▫ forward 方法 将本 servlet 的 request 请求传递给“其他资源”响应 通过利用此方法可实现: servlet先预处理 request ,然后将处理后的 request传递给“其他资源”处理

▫ include 方法 引入“其他资源”来响应客户端的请求

11.6 协作与通信 (续 )——RequestDispatcher 接口

Page 54: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

74

• MyServlet1 获取另外一个 servlet ( MyServlet2 ),并用它来响应用户的请求import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class MyServlet1 extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse

res) throws ServletException, IOException

{ res.setContentType("text/html"); RequestDispatcher summary= getServletContext().getRequestDispatcher(

"/servlet/MyServlet2");

11.6 协作与通信 (续 )——MyServlet1.java

Page 55: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

75

if (summary != null) { try { summary.include(req, res); }

catch (IOException e) { } catch (ServletException e) { } } else if (summary == null) {

PrintWriter out = res.getWriter(); out.println("<HTML>"); out.println("<HEAD><TITLE>Error</TITLE></HEAD>"); out.println("<BODY>"); out.println("<BIG>Summary is Null</BIG>"); out.println("</BODY></HTML>");

} } }

11.6 协作与通信 (续 )——MyServlet1.java

Page 56: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

76

import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class MyServlet2 extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter out = res.getWriter(); out.println("<HTML>"); out.println("<HEAD><TITLE> MY second Servlet

</TITLE></HEAD>"); out.println("<BODY>"); out.println(" <table border=2> <tr> <td> name </td><td> Bush

</td>"); out.println("<td> Sex </td> <td> Male

</td></tr><tr><td>City</td>"); out.println("<td>NewYork</td> <td>Country</td><td>U. S. A

</td></tr>"); out.println("</BODY><HTML>"); }}

11.6 协作与通信 (续 )——MyServlet2.java

Page 57: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

77

11.6.1 Applet 与 Servlet 的通信• Applet 与 Servlet 的通讯

▫ 用户用 Applet 发送消息到服务器▫ 对于动态网页, Applet 与 Servlet 的通讯尤为重要▫ 比如在一个聊天系统中,当一个用户输入了某些语句

时,聊天室内的所有其他用户都可以看到。此功能可能的实现步骤是 用户先把消息发给服务器 然后服务器发送给聊天室内的所有用户

• Applet 和 Servlet 通讯的方式有多种▫ 通过 socket 直接建立网络连接▫ 通过远程方法调用 (Remote Method Inovation) 通

讯▫ 通过 CORBA 通讯

11.6 协作与通信

Page 58: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

78

• Socket 通讯▫ 服务器端的操作

首先创建一个 ServerSocket 对象,在指定端口监听客户端的request

在接收到 request后, accept() 方法返回一个 Socket 对象 通过 socket 对象创建输入输出流对象,并实现与客户端的交互 交互完毕后,关闭输入输出流和 socket ,最后关闭

ServerSocker

▫ 客户端的操作 首先创建 socket 对象,建立与服务器的连接 然后通过 socket 对象创建输入输出流,实现与服务器的交互 最后关闭输入输出流和 socket

11.6 协作与通信

11.6.1 Applet 与 Servlet 的通信 (续 )——Socket 通讯

Page 59: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

79

• RMI 通讯▫ Remote Method Invocation 的简写,即远程方法调用▫ 通过存在于远程机器上的对象,可以发消息给远程的机器,且

可以取得远程机器程序执行的结果。整个调用过程类似于此对象存在于本地机器,无疑这大大简化了通讯过程

▫当大量的数据是由服务器端的对象动态提供时使用 RMI 通讯是非常合适的

▫ 如何使用 RMI 先定义一个继承自 java.rmi.Remote 的公用接口。在该接口中定义要求在服务器上运行的方法

接下来是实现远程接口,远程接口的实现类应该实现:定义远程对象的构造方法,创建和安装安全管理器,创建一个或多个远程对象实例,并注册至少一个远程对象

11.6 协作与通信

11.6.1 Applet 与 Servlet 的通信 (续 )——RMI 通讯

Page 60: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

80

• 通过 CORBA 通讯▫即公用对象请求代理体系( Common Object Request

Broker Architecture ),是 OMA 定义的一套和语言无关的分布式对象交换标准框架 (Standard framework of object interoperability)

▫ CORBA 的主要功能是 RPC(Remote Procedure Call)式的支持,它使得本机对象可以调用远端对象的方法

▫ 使用方法类似于 RMI 定义接口 创建类实现接口 在服务器上注册后客户就可以像本地对象一样访问远程对象了

11.6 协作与通信

11.6.1 Applet 与 Servlet 的通信 (续 )—— 通过 CORBA 通讯

Page 61: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

81

• CORBA 和 RMI 的主要区别

▫ CORBA 使用一种语言中立的接口定义语言( IDL )来定义接口,

IDL 是一种可用于混合语言环境的更为广泛的协议集

▫ RMI 让 Java 对象之间可以进行 RPC

▫ CORBA则让任何语言实现出来的对象之间进行 RPC

11.6 协作与通信

11.6.1 Applet 与 Servlet 的通信 (续 )——CORBA 和 RMI 的主要区别

Page 62: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

82

11.6.2 Servlet 间的信息共享• servlet 间的信息共享

▫ 通过方法调用▫ 通过共享类对象▫利用 java 语言的 Properties列表

Properties列表包含系统的很多信息,比如java.version , path , separater ,应用程序相关的很多属性等

可通过如下的方法添加一个属性到此列表 System.getProperties().put("key", "value"); 运行在同一个 JVM 上的其他 servlet 可调用属性 String value = System.getProperty("key"); 也可以通过如下语句删除列表中的某项属性: System.getProperties().remove("key");

11.6 协作与通信

Page 63: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

83

• 通过会话跟踪,实现对客户访问次数记数的功能import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.net.*; import java.util.*;public class TrackSession extends HttpServlet { public void doGet( HttpServletRequest request, HttpServletResponse

response) throws ServletException, IOException { String heading; Integer count; response.setContentType("text/html"); HttpSession session = request.getSession(true); count =(Integer)session.getAttribute("count");

11.7 程序举例——例 11-7

Page 64: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

84

if (count == null) { count = new Integer(0); heading = "First visiting";} else { heading = "Welcome Back"; count = new Integer(count.intValue() + 1);}session.setAttribute("count", count);PrintWriter out = response.getWriter();String docType = "<!DOCTYRP HTML PUBLIC \"- //W3C//DTD HTML 4.0" + "Transitional //EN\">\n";

out.println( docType +"<BODY BGCOLOR=\"#FDF5E6\">\n" +"<H1 ALIGN=\"CENTER\">" + heading + "</H1>\n" +"<TABLE BORDER=1 ALIGN=\"CENTER\">\n" +"<TR BGCOLOR=\"#FFAD00\">\n" +" <TH>NAME<TH>VALUE\n" +"<TR>\n" +" <TD>ID:\n" +" <TD>" + session.getId() + "\n" +"<TR>\n" +" <TD>Creation Time:\n" +" <TD>" +new Date(session.getCreationTime()) + "\n" +"<TR>\n" +"<TD>Last Access Time:\n" +"<TD>" +new Date(session.getLastAccessedTime()) + "\n" +"<TR>\n" + " <TD>Count:\n" +" <TD>" + count + "\n" +"</TABLE>\n" +"</BODY></HTML>“ );

} public void doPost( HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response); // doPost 方法直接调用 doGet }}

11.7 程序举例——例 11-7

Page 65: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

85

点击刷新按钮 2次后

关闭浏览器再

次打开后

11.7 程序举例——例 11-7 运行结果

Page 66: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

86

• 利用 cookie 的 servlet 同样也可以实现记录用户访问次数的功能import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import java.net.*;public class AccessCounts extends HttpServlet { public void doGet(HttpServletRequest req,HttpServletResponse

res) throws ServletException, IOException{ String cookieName, numString; cookieName = "numString"; numString = "1"; Cookie[] cks = req.getCookies(); if (cks != null) { for (int i=0; i<cks.length; i++) { Cookie tempCk = cks[i]; if(cookieName.equals(tempCk.getName())) numString = tempCk.getValue(); } }

11.7 程序举例——例 11-8

Page 67: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

87

int num = 0; try{ num = Integer.parseInt(numString); } catch(NumberFormatException e) {} Cookie myCookie = new

Cookie( "numString",String.valueOf(num+1) ); myCookie.setMaxAge(60*60*24); res.addCookie(myCookie); res.setContentType("text/html"); PrintWriter out = res.getWriter(); String title = "User Access Count "; String docType = "<!DOCTYRP HTML PUBLIC \"- //W3C//DTD HTML 4.0" + "Transitional

//EN\">\n";

out.println( docType+ "<html>\n"+ "<head><title>" + title + "</title></head>"+ "<body>\n"+ "<h1> Access Count

is: " + num + " </h1>"+ "</body></html>" ); }}

11.7 程序举例——例 11-8

Page 68: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

88

点击刷新按钮6次后

关闭浏览器再

次打开后

11.7 程序举例——例 11-8 运行结果

Page 69: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

89

• 例 11-7 使用 Session 的 servlet▫重启 Web 服务器后,计数将要重新从 0 开始;这是

因为 session 存在服务器内存中▫关闭浏览器再次打开后,上一次会话已经结束,计

数重新从 0 开始• 例 11-8 使用 cookie 的 servlet

▫重启 Web 服务器或关闭浏览器再次打开后,都可以正确计数,因为 Cookie 存在与客户端,且在程序中设计其生命为 1 天

▫当客户端删除存在的 cookie后,计数才会从 0 开始。对 IE 浏览器来说,可以在菜单“工具”下调出“ Internet选项”,然后选择“删除 Cookie(I)…” ,从而方便实现含有 Cookie 的 servlet 的调试

11.7 程序举例——例 11-7 和例 11-8 结果分析

Page 70: 第十一章  Servlet 程序设计

Java 语言程序设计(第 2 版),郑莉,清华大学

90

11.8 本章小结• 本章内容

▫ Java 网络程序设计的基本概念▫ servlet 的基础知识,包括 servlet 的基本结构和生命周期▫ servlet 与客户端交互的技术以及客户端跟踪技术▫ servlet 与其它网络资源的交互

• 本章要求▫ 了解基于 TCP 协议的有连接通讯和基于 UDP 协议的数据报通

讯的含义▫熟悉 servlet 的常用 API 以及 servlet 的编程方法