【文档说明】Java语言程序设计-Servlet程序设计解析课件.ppt,共(92)页,832.502 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-45175.html
以下为本文档部分文字说明:
1第十一章Servlet程序设计JAVA语言程序设计2目录⚫11.1Java网络程序设计的基本概念⚫11.2Servlet基础⚫11.3Servlet的生命周期⚫11.4与客户端交互⚫11.5客户端跟踪⚫11.6协作与通讯⚫11.7
程序举例⚫11.8本章小结311.1Java网络程序设计的基本概念⚫网络将世界联系在一起,使世界变得更加丰富多彩。同时网络互连是一个内容丰富而复杂的主题,所以这方面的程序设计涉及面很广且不易掌握⚫与其他语言相比,Java语言在网络应用程序方面具有一定的优势。
Java提供了很多内置的网络功能,使得基于Internet和Web的应用开发变得更加容易411.1.1协议⚫所有使用或实现某种Internet服务的程序都必须遵从一个或多个网络协议,这种协议很多,而I
P、TCP、UDP是最为根本的三种协议,是所有其它协议的基础–IP(InternetProtocol,Internet协议)⚫是最底层的协议⚫定义了数据按照数据报(Datagram,一种自带寻址信息的、独立地从数据源走到终点的数据
包)传输的格式和规则–TCP(TransportControlProtocol,传输控制协议)⚫建立在IP之上,定义了网络上程序到程序的数据传输格式和规则,提供了IP数据包的传输确认、丢失数据包的重新请求、将
收到的数据包按照它们的发送次序重新装配的机制⚫是面向连接的协议,在开始数据传输之前,必须先建立明确的连接–UDP(UserDatagramProtocol,用户数据报协议)⚫与TCP相似,比TCP具有更好的传输效率。⚫不可靠的,不保证数据的传输,
也不提供重新排列次序或重新请求功能,是一种无连接协议Java网络程序设计的基本概念5⚫HTTP协议(HyperTextTransferProtocol)–是Internet众多协议中的一种,表示超文本传输
协议,它构成了WWW的基础–具有简单快速、灵活、无状态、无连接等特点–基于请求(Request)/响应(Response)模式。其工作过程如下⚫首先客户端与服务器建立连接⚫然后客户端发送一个请求给服务器⚫服务器接到请求后,给予相应的
响应信息;最后关闭连接,完成一次操作11.1.1协议(续)——HTTP协议Java网络程序设计的基本概念6⚫客户端发送给服务器的请求–有很多类型,被称为方法,其中最常用的是GET、POST–GET方法⚫用来从服
务器读取信息,比如从服务器读取文件、表格、数据库查询结果等–POST方法⚫用来向服务器传送信息,比如把信用卡号、表格、存储于数据库的数据等传送到服务器–HEAD方法⚫用来读取服务器响应头(ResponseHead);得到诸如文件大小,文件最后修改时间
,服务器类型等信息–PUT方法⚫将文件直接传到服务器–DELETE方法⚫将文件直接从服务器删除–TRACE方法⚫用来协助程序调试–OPTIONS方法⚫用来查询服务器所支持的方法11.1.1协议(续)——HTTP
协议中客户端发送给服务器的请求Java网络程序设计的基本概念711.1.2关于URI⚫URI(UniformResourceIdentifier,统一资源标志符)–HTTP协议用URI标识定位网络上的数据–如果知道了公布在网络上的某个HTML文件的URI,不管文件位于什么地方,都
可以通过HTTP访问该文档–通常所说的URL是URI的一种Java网络程序设计的基本概念8⚫URL类–Java语言提供了URL类让我们能在源代码层使用URL–有六个构造函数,其中最简单的是URL(Stringurl)。每个URL对象
都封装了资源的标识符和协议处理程序,可以调用URL的方法来提取URL的组件–把URL对象作为AppletContext接口的showDocument方法的参数,就可以使执行applet的浏览器显示URL所指定的资源11.1.2关于URI(续)——URL类Java网络程序设计的基
本概念9⚫applet浏览指定URL举例:ShowDocument.javaimportjava.net.*;importjava.util.*;importjava.awt.*;importjava.awt.
event.*;importjava.applet.AppletContext;importjavax.swing.*;importjavax.swing.event.*;publicclassSho
wDocumentextendsJApplet{publicvoidinit(){JButtongoButton=newJButton("Linktowww.sohu.com");ContainermyContainer=getContentPane();myContainer.add(n
ewJLabel("LinktoSOHU"),BorderLayout.NORTH);myContainer.add(goButton,BorderLayout.SOUTH);goButton.addActionL
istener(newButtonListener());}11.1.2关于URI(续)——例11_1Java网络程序设计的基本概念10classButtonListenerimplementsActionListener{public
voidactionPerformed(ActionEvente){try{URLnewDocument=newURL("http://www.sohu.com");AppletContextbrowser=getAppletContext();b
rowser.showDocument(newDocument);}catch(ExceptionURLException){}}}}11.1.2关于URI(续)——例11_1Java网络程序设计的基本概念1111.1.3基于套接字的有连接通信⚫基于套接字(socke
t)的有连接通信–使用TCP协议–一个socket必须在发送数据之前与目的地的socket取得连接–一旦连接建立了,sockets就可以使用一个流接口完成打开-读-写-关闭,所有的发送的信息都会在另一端以同样的顺序被接收–面向连接的操作比无连接的操作效率低,但
是数据的安全性高Java网络程序设计的基本概念12⚫用Java建立简单的服务器程序需要五个步骤–Step1:创建ServerSocket对象ServerSocketmyServer=newServerSocket(intport,intbackl
og);⚫Port指定一个可用的端口号,用来定位服务器上的服务器应用程序⚫backlog指定能够连接到服务器的最多客户数。连接客户达到由backlog指定的最大客户数量时,服务器将拒绝客户连接–Step2:通过ServerSocket的accept方法监听客户连接,服务器无限期的监听
客户连接Socketconnection=myServer.accept();⚫有一个客户连接时,将产生并返回一个socket11.1.3基于套接字的有连接通信(续)——服务器端Java网络程序设计的基本概念13–Step3:通过Socket的方法getInputStrea
m和getOutputStream获取InputStream和OutputStream对象;通常将其他流类型和它们联系起来,如:ObjectInputStreaminput=newObjectInputStream(connection.getInputStream());
ObjectOutputStreamoutput=newObjectOutputStream(connection.getOutputStream());–Step4:客户和服务器通过OutputStream和InputStream对象进行通信–
Step5:通信传输完毕,服务器通过调用流和套接字的close方法关闭连接11.1.3基于套接字的有连接通信(续)——服务器端Java网络程序设计的基本概念14⚫在客户端建立简单连接的思路类似,可分为四步–Step1:建立一个Soc
ket,实现与服务器的连接Socketconnection=newSocket(InetAddressaddress,intport);⚫address:服务器IP地址。port:端口号⚫连接成功,将返回一个Socket,否则产生异常–
Step2:通过getInputStream和getOutputStream分别获取Socket的InputStream和OutputStream的引用。同样,也可以将其他流类型与InputStream和OutputStream联系起
来–Step3:客户与服务器通过InputStream和OutputStream进行通信–Step4:传输完毕后,通过调用流和套接字的close方法关闭连接11.1.3基于套接字的有连接通信(续)——客户端Java网络程序设计的基本概念1511.4数据报通
信⚫数据报通信(DatagramCommunication)–使用用户数据报协议(UserDatagramProtocol,UDP)⚫与TCP不同的一种协议⚫不能保证数据会被成功地送达,也不保证数据抵达的次序与送出的次序相同,所以也被称为“不可靠的通信协议”,虽然可靠性不高,
但是它的速度很快,所以有些场合也有很大的用处–服务器通过DatagramSocket接收或发送信息,这些信息以DatagramPackets的形式存在DatagramSocketmySocket=newDatagramSocket(intport);⚫port表示端口,上述语句将
服务器绑定到一个可以从客户端接收packet的端口上,如果绑定失败,将产生SocketException异常Java网络程序设计的基本概念16⚫客户端应用程序的工作流程–Step1:通过创建一个DatagramSocket对象来建立数据报通讯的Socke
t。有如下两种构造方法publicDatagramSocket()⚫构造一个数据报socket,并使其与本地主机任一可用的端口连接。若打不开socket则抛出SocketException异常。publicDatagramSocket(intport)⚫
构造一个数据报socket,并使其与本地主机指定的端口连接。若打不开socket或socket无法与指定的端口连接则抛出SocketException异常11.1.4数据报通信(续)——客户端Java网络程序设计的基本概念17–Step2:用DatagramPacket类来创建一个数据报包
,用来实现无连接的包传送服务⚫DatagramPacket对象封装了数据报包的数据(bufferedarray[],包长度(length),目标地址(address),目标端口(port);length必须小于等于bufferedarry.lengthDatagr
amPacket(bytebufferedarray[],intlength,InetAddressaddress,intport)⚫DatagramPacket类提供了四个方法来获取信息–publicbyte[]getData()返回
一个字节数组,包含收到或要发送的数据报中的数据–publicintgetLength()返回发送或接收到的数据的长度–publicInetAddressgetAddress()返回一个发送或接收此数据报包文的机器的IP地址–publicintgetPort()返回发送或接收数据报的远程主机的端
口号11.1.4数据报通信(续)——客户端Java网络程序设计的基本概念18–Step3:调用DatagramSocket对象的send(DatagramPacketp)方法发送数据报文包–Step4:调用DatagramSocket对
象的receive(DatagramPacketp)方法接收从服务器返回的结果数据报文包⚫该DatagramPacket对象用到另一种构造方法,只需指明存放接收的数据报的缓冲区和长度DatagramPacket(bytebufferedarray[],intlength)⚫re
ceive方法会一直阻塞,直到收到一个数据报文包,此时DatagramPacket的缓冲区中包含的就是接收到的数据,也包含发送者的IP地址,发送者机器上的端口号等信息–Step5:处理接收缓冲区内的数据,获取服务结果–Step6:通
讯完成后,使用DatagramSocket对象的close()方法来关闭数据报通讯Socket11.1.4数据报通信(续)——客户端Java网络程序设计的基本概念19⚫服务器端应用程序的工作流程–与客户端应用程序的通讯过程使非常相似⚫建立数据报通讯Datagram
Socket⚫构建数据报文包DatagramPacket⚫接收数据报和发送数据报,处理接收缓冲区内的数据⚫通讯完毕后,关闭数据报通讯Socket–不同的是,服务器应用程序要面向网络中的所有计算机,所以服务器应
用程序收到一个包文后要分析它,得到数据报的源地址信息,这样才能创建正确的返回结果报文给客户机11.1.4数据报通信(续)——服务器端Java网络程序设计的基本概念2011.5Servlet⚫Servlet–是用java技术来实现CGI(CommonGatewayInterface,通
用网关接口)功能的编程–介于浏览器(或其他HTTP客户端)与服务器之间,起到桥梁的作用。具体作用为:⚫读取客户端发送的数据⚫获取客户请(request)中所包含的信息⚫产生响应结果,并将结果包含到一个文件中,比如HTML文件中⚫设置
HTTP响应参数,比如告诉浏览器,文件类型为HTML⚫将文件返回给客户端–Servlet的应用并不限于处理HTTP请求的网页或者应用程序服务中,还可以置入到邮件或FTP服务程序中Java网络程序设计的基本概念21⚫与传统的CGI相比,Servlet
具有很多优点–高效率⚫通过Servlet,Java虚拟机用轻量级的Java线程处理每个请求。同时有N个请求的情况下,CGI程序需要被调入到服务器内存N次;对于Servlet将开启N个线程,但仅仅调入一
个Servlet实例到内存中–应用方便⚫Servlet在解析和译码HTML数据,读取设置HTML标题,操作Cookie等很多方面,应用更加方便。继承自java的特点,其可靠性与复用性好–功能强大⚫Servlet可
以直接与Web服务程序对话;多个Servlet可以共享数据;Servlet与数据库的连接也比较简单等11.1.5Servlet(续)——优点Java网络程序设计的基本概念22–便携性好⚫Servlet用Java语言编写,遵循标准的API。因此Servlet编写的程序可以无任何修改
的在Apache,MicrosoftInternetInformationServer(IIS),IBMWebSphere,或者StarNineWebStar上运行。同样具有一次编译,到处运行移植性好的特点–安全⚫基于Java语言的安全特性,Servlet的安全性
也比较可靠–成本低⚫有很多免费或相对比较便宜的Web服务器,适合做个人的或者小容量的网站。而且很多商业级的Web服务器相对也比较便宜。而且使一个服务器支持Servlet所需的额外花费也很少11.1.5Servlet(续)——优点Java网络程序设计的基本概念2311.2Servlet基
础⚫本节内容包括–Servlet容器、web服务器、应用服务器–Web应用程序–ServletAPI–Servlet的基本结构–Servlet编译和安装2411.2.1Servlet容器、Web服务器和应用服务器⚫Se
rvlet容器–也称为Servlet引擎–是一个编译好的可执行程序,它是web服务器与servlet间的的媒介–负责将请求翻译成Servlet能够理解的形式传递给servlet,同时传给servlet一个对象使之可以送回响应–负责管理servl
et的生命周期Servlet基础25⚫web服务器–能够处理Http请求的服务器–可以提供静态页面、图像等–有的web服务器也支持动态页面的生成,支持JSP、Servlet等,具有JVM⚫应用服务器–可以处理基于多种协议的请求,当然也包括Http
协议–可以支持servlets和JSP,以及所有其他J2EE服务,包括JNDI、EJBs、JMS等11.2.1Servlet容器、Web服务器和应用服务器(续)Servlet基础26⚫servlet容器可以与web
服务器协作提供对servlet的支持⚫一些servlet容器(如ApacheTomcat)自己也可以作为独立的web服务器运行⚫随着servlet和JSP的流行,一些主要的Web服务器和应用程序服务器都直接或者通过插件支持servlet和JSP。如:–SunONEAppl
icationServer–LotusDominoGoWebServer–BEAweblogicTengahServer–WebSphere应用服务器–Jigsaw–NetForge–AcmeServer–MotBaysJetty11.2.1Servlet容器、Web服务器和应用服务
器(续)Servlet基础27⚫ApacheTomcat5–是servlet2.4和JSP2.0规范的官方参考实现–完全免费,并且提供完整的源代码–可以到http://jakarta.apache.org/tomcat/下载最新版本⚫初始设置–
设置JAVA_HOME。假设JDK安装在C:\j2sdk1.4.2,可以仿照path和classpath的设置方法,新建一个环境变量:JAVA_HOME=C:\j2sdk1.4.211.2.1Servlet容器、Web服务器和应用服务器(续)——
ApacheTomcat5服务器及其初始设置Servlet基础28⚫为方便调试,还可进行如下设置–启动servlet重新载入功能(所请求servlet类文件发生变化后,自动重新载入到服务器内存)。打开install_dir/conf/server
.xml,在注释<!--Definepropertiesforeachwebapplication-->后插入语句<DefaultContextreloadable=“true”/>–开启servlet调用器invokerservlet(可以不修改Web应用的web.xml文件即可运行
servlet)。打开install_dir/conf/web.xml,将servlet-mapping元素取消注释<servlet-mapping><servlet-name>invoker</servlet-name><url-pattern>/servlet/*</url-pat
tern></servlet-mapping>11.2.1Servlet容器、Web服务器和应用服务器(续)——ApacheTomcat5服务器及其初始设置Servlet基础2911.2.2Web应用程序⚫Web应
用程序–组成部分包括servlet、JSP及其支持文件–这些组成部分需要进行部署–通常部署在Tomcat的webapps子目录中。一般其目录结构包括根目录(contextroot)和几个子目录,也可以把子目录捆绑到一个类型为war的存档文件中Servlet基础3011.2.2Web应用程序(续)
⚫webapps子目录一般包括,–WEB-INF⚫包含Web应用程序的部署描述文件(web.xml)⚫在web.xml文件中配置Web应用程序。可以制订各种配置参数:调用servlet的名称、servlet的描述、servlet的完全的类名和servlet容器调用servlet的
路径⚫修改web.xml的部署描述符后,需要重新启动Tomcat服务器–WEB-INF/classes⚫包括Web应用程序中所使用的servlet和实用工具类文件。如果类文件是包的组成部分,则包的目录结构从该目录开始–WEB-INF
/lib⚫包含Java存档文件(JAR文件),是servlet和实用工具类文件Servlet基础3111.2.2Web应用程序(续)DirectoryDescriptioncontextrootThisistherootdirectoryfortheWe
bapplication.ThenameofthisdirectoryischosenbytheWebapplicationdeveloper.AlltheJSPs,HTMLdocuments,servletsandsupportingfilessuchasi
magesandclassfilesresideinthisdirectoryoritssubdirectories.ThenameofthisdirectoryisspecifiedbytheWebapplicationcreator.Toprovidestr
uctureinaWebapplication,subdirectoriescanbeplacedinthecontextroot.Forexample,ifyourapplicationusesmanyimages,youmightplaceanimagessubdirectoryi
nthisdirectory.TheexamplesofthischapterandChapter10useadvjhtp1asthecontextroot.WEB-INFThisdirectorycontainstheWebappl
icationdeploymentdescriptor(web.xml).WEB-INF/classesThisdirectorycontainstheservletclassfilesandothersupportingclas
sfilesusedinaWebapplication.Iftheclassesarepartofapackage,thecompletepackagedirectorystructurewouldbeginhere.WEB-INF/
libThisdirectorycontainsJavaarchive(JAR)files.TheJARfilescancontainservletclassfilesandothersupportingclassfilesusedinaWebapplication.Servlet基础32
11.2.3ServletAPI⚫ServletAPI–开发servlet和JSP程序,需要参考ServletAPI文档–包含javax.servlet和javax.servlet.http两个包中–所有servl
et须实现javax.servlet.Servlet接口,通常继承如下两个类中的一个⚫GenericServlet⚫HttpServletServlet基础ServletGenericservletHttpservletMys
ervlet33⚫Servlet接口–所有servlets必须实现这一接口–Servlet接口的所有方法都是被自动调用的⚫HttpServlet类–覆盖了javax.servlet.Servlet接口的service方法⚫service方法由servlet容器调用,对客户端的请求作出响应。它
会根据请求类型的不同自动调用doGet或doPost等方法–能够处理两个最普通的HTTP请求类型⚫doGet方法响应get请求⚫doPost方法响应post请求Servlet基础11.2.3ServletAPI(续)3411.2.3ServletAPI(续)⚫HttpServletRequ
est接口–由Web服务器创建该接口的一个对象,并将其传递给servlet的service方法–该类对象含有来自于客户端的请求⚫HttpServletResponse接口–由Web服务器创建该接口的一个对象,并将其传送给servlet的service方法–通过该类对
象服务器端可以对客户端发出响应信息Servlet基础35MethodDescriptionStringgetParameter(Stringname)Obtainsthevalueofaparametersenttot
heservletaspartofagetorpostrequest.Thenameargumentrepresentstheparametername.EnumerationgetParameterName
s()Returnsthenamesofalltheparameterssenttotheservletaspartofapostrequest.String[]getParameterValues(Stringname)Foraparameterw
ithmultiplevalues,thismethodreturnsanarrayofStringscontainingthevaluesforaspecifiedservletparameter.Cookie[]getCookies()Return
sanarrayofCookieobjectsstoredontheclientbytheserver.Cookiescanbeusedtouniquelyidentifyclientstotheservlet.HttpSessiongetSession(booleancrea
te)ReturnsanHttpSessionobjectassociatedwiththeclient’scurrentbrowsingsession.AnHttpSessionobjectcanbecre
atedbythismethod(trueargument)ifanHttpSessionobjectdoesnotalreadyexistfortheclient.HttpSessionobjectscanbeusedinsimilarwa
ystoCookiesforuniquelyidentifyingclients.11.2.3ServletAPI(续)——HttpServletRequest接口Servlet基础3611.2.3ServletAPI(续)——HttpServletResponse接口MethodDescr
iptionvoidaddCookie(Cookiecookie)UsedtoaddaCookietotheheaderoftheresponsetotheclient.TheCookie’smaximumageandwhetherCookies
areenabledontheclientdetermineifCookiesarestoredontheclient.ServletOutputStreamgetOutputStream()Obtainsabyte-basedoutputstreamforsendingbinarydatato
theclient.PrintWritergetWriter()Obtainsacharacter-basedoutputstreamforsendingtextdatatotheclient.voidsetContentType(String
type)SpecifiestheMIMEtypeoftheresponsetothebrowser.TheMIMEtypehelpsthebrowserdeterminehowtodisplaythedata(orpossiblywhatotherapplicationtoexe
cutetoprocessthedata).Forexample,MIMEtype"text/html"indicatesthattheresponseisanHTMLdocument,sothebrowserdisplaystheHTMLpage.FormoreinformationonServ
let基础3711.2.4Servlet的基本结构⚫Servlet的基本结构–一般扩展自HttpServlet–复写doGet或者doPost方法⚫doGet或doPost都接收两个类型的参数:HttpServletRequest和Htt
pServletResponse⚫通过HttpServletRequest,可以得到所有的输入数据,比如表单数据、HTTP请求报头等客户信息⚫通过HttpServletResponse可以指定输出信息⚫由于doG
et和doPost方法可能生成异常,必须在方法名称后声明抛出异常或者用try-catch语句处理异常Servlet基础38⚫GET请求是WEB浏览器请求的常见类型,用来请求Web页面。本例中通过doGet方法
处理GET请求。在doGet方法中通过HttpServletResponse对象得到PrintWriter,然后将一个文档发给客户。最终在客户端生成一个网页importjava.io.*;importjavax.serv
let.*;importjavax.servlet.http.*;publicclassMyServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestreq,HttpServletResponseres)throwsServletEx
ception,IOException{res.setContentType("text/html");PrintWriterout=res.getWriter();out.println("<HTML>");o
ut.println("<HEAD><TITLE>MyFirstServlet</TITLE></HEAD>");out.println("<BODY>");out.println("<B>FirstServlet</B>");out.println("</BODY></HTML>");
}}11.2.4Servlet的基本结构(续)——例11_2Servlet基础3911.2.5Servlet编译和安装⚫编译——在设置好path和classpath的前提下,servlet的编译和普通的java
程序完全相同–可以通过javac.exe编译,比如可以在Dos环境下输入:javacMyServlet.java–也可以通过集成开发环境(IDE)编译⚫复制——编译成功之后,将生成的类文件复制到相应的目录下即可。在Tomcat服务器上,此目录可能是install_dir\webapps\ROOT
\WEB-INF\classes\⚫运行——启动Tomcat服务器,在地址栏输入http://localhost:8080/servlet/MyServletServlet基础4011.3Servlet的生命周期⚫首先服务器仅创建ser
vlet的一个实例–创建servlet实例时,它的init方法都会被调用⚫针对每个客户端的每个请求,都会创建一个线程–该线程调用servlet实例的service方法–Service方法根据收到HTTP请求得类型,调用doGet,doPost或者其他方法–多个并发请求,一般会导致多个
线程同时调用service方法,通过单线程模式(SingleThreadModel)也可以规定任何时间仅允许一个线程运行⚫最后,卸载servlet–服务器调用servlet的destroy方法4111.3Servlet的生命周期(
续)——Servlet生命周期示意图服务器服务器Servlet代码服务器客户端客户端装载Servlet代码卸载Servlet代码处理客户端请求Servlet的生命周期4211.3.1初始化⚫servlet的初始化–服务器启动,s
ervlet被用户首次调用,服务器构造servlet实例之后,即立刻调用init(ServletConfig)方法,执行servlet实例的初始化工作–ServeletConfig对象包含servlet初始化所需的很多参数,比如计数器、默认值等–init方法都会在s
ervlet处理客户请求(request)之前被调用–一旦init方法被调用,只有服务器通过destroy方法销毁servlet之后,init方法才能再次被调用Servlet的生命周期4311.3.1初始化(续)⚫init方法的定义publicvoidinit(ServletConf
igconfig)throwsServletException{super.init(config);Stringgreeting=getInitParameter("greeting");//Initializationc
ode…}Servlet的生命周期4411.3.2销毁⚫servlet的销毁–服务器卸载servlet实例之前,需要先调用servlet的destroy方法⚫释放servlet所获得的资源⚫使servlet有机会关闭数据库连接、停止后台运行的线程
、将cookie列表和点击数写入到磁盘⚫执行其他清理活动Servlet的生命周期4511.4与客户端交互⚫HTTPservlet与客户端的交互–通过service方法处理客户端的请求–service方法根据请求(request)类型的不同,调用不同的方法⚫对于GET请求,调用doGet
()方法进行处理⚫对于POST请求,调用doPost()方法进行处理4611.4.1提取Servlet信息⚫注册的servlet都有相关的很多初始化参数–这些初始化参数写在web.xml中,具体语法格式请参阅To
mcat文档–getInitParameter()方法⚫可以得到servlet初始化的一些参数⚫返回一个指定参数的值(String类型)⚫如果指定参数不存在,则返回null–getInitParameterName
s()方法⚫可以得到初始化参数名称⚫返回String类型的Enumeration类型数据⚫如果不存在初始化参数,则返回一个null的Enumeration与客户端交互47⚫通过servlet初始化参数建立一个数据库连接的程
序段如下java.sql.Connectioncon=null;publicvoidinit(ServletConfigconfig)throwsServletException{super.init(config);Stringhost=getIn
itParameter("host");intport=Integer.parseInt(getInitParameter("port"));Stringdb=getInitParameter("db");Stringuser=getIn
itParameter("user");Stringpassword=getInitParameter("password");Stringproxy=getInitParameter("proxy");con=establishConnection(host,port,
db,user,password,proxy);}11.4.1提取Servlet信息(续)——通过初始化建立数据库连接与客户端交互48⚫输出全部初始化参数名称importjava.io.*;importjava.util.*;importjavax.servlet.*
;publicclassPrintInitParaNamesextendsGenericServlet{publicvoidservice(ServletRequestreq,ServletResponseres)throwsServletExcep
tion,IOException{res.setContentType("text/plain");PrintWriterout=res.getWriter();out.println("InitParametersAsFollowing:");Enumerationenum=ge
tInitParameterNames();while(enum.hasMoreElements()){Stringname=(String)enum.nextElement();out.println(name":"+getInitParameter(name));}}}11.4
.1提取Servlet信息(续)——PrintInitParaNames.java与客户端交互4911.4.2提取服务器信息⚫servlet可以得到很多服务器相关的信息,同时可以将这些信息发送到客户端–getServerName()返回服务器名称–getServer
Port()返回服务器监听端口–getServerInfo()输出服务器程序和版本,之间用“/”分开–getAttribute()返回服务程序的属性–得到路径相关的信息⚫publicStringHttpServletRequest.getPathInfo(
)⚫publicStringHttpServletRequest.getPathTranslated()与客户端交互50⚫提取服务器信息举例importjava.io.*;importjava.util.*;importjavax.s
ervlet.*;publicclassServerSnoopextendsGenericServlet{publicvoidservice(ServletRequestreq,ServletResponseres)throw
sServletException,IOException{res.setContentType("text/plain");PrintWriterout=res.getWriter();out.println("req.getServerName()o
utput:"+req.getServerName());out.println("req.getServerPort()output:"+req.getServerPort());out.println("getServl
etContext().getServerInfo()output:"+getServletContext().getServerInfo());out.println("getServletContext().getAttribute(\"attribute\")ou
tput:"+getServletContext().getAttribute("attribute"));}}11.4.2提取服务器信息(续)——例11_3与客户端交互5111.4.3提取客户端信息⚫服务器可以从reques
t得到很多客户端的信息–getRemoteAddr():得到IP地址–getRemoteHost():得到客户端机器的名称–利用InetAddress.getByName()方法可以将IP地址或客户端机器名称转换成一个java.net.InetAddress类型的对象InetAddressremo
teInetAddress=InetAddress.getByName(req.getRemoteAddr());⚫通过获取客户端的地址,并判断是否隶属某个范围,可以限制某个地区的用户访问你的网站与客户端交互5211.4.3提取客户端信
息(续)⚫服务器可以得到客户想做的事情–客户请求表现为表单数据,由“名/值”对组成。当提交某一个网页的时候常常在浏览器地址栏中看到类似格式的数据格式name/value,每对之间用&隔开,表达式为param1=value1¶m2
=value2¶m3=value3…–request.getParameter:得到表单参数的值–request.getParameterValues:得到多次出现的参数值–reques.getParameterNames:得到当前请求中所有参数的完整列表,调用
形式如下⚫publicStringServletRequest.getParameter(Stringname)⚫publicString[]ServletRequest.getParameterValues(Stringname)与
客户端交互53⚫书本查询的一个HTML网页!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN"><HTML><HEAD><TITLE>ASam
pleFormforQueryaBook</TITLE></HEAD><BODYBGCOLOR="#FDF5E6"><FORMMETHOD=GETACTION="/Chapter11/QueryServlet">Booktolookup:<INPUTTYPE="TEX
T"NAME="Book"VALUE="JavaServletProgramming"><!--Thedefaultbooktobelookedupis:《JavaServletProgramming
》.--><INPUTTYPE=SUBMIT></FORM></BODY></HTML>11.4.3提取客户端信息(续)——Query.html与客户端交互54⚫获取客户端信息的servletimportjava.io.*;importjava.net.*;importjavax.servl
et.*;importjavax.servlet.http.*;publicclassQueryServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestreq,HttpServletRes
ponseres)throwsServletException,IOException{res.setContentType("text/html;charset=UTF-8");StringqueryBookValue=req.get
Parameter("Book");PrintWriterout=res.getWriter();out.println("Thebookyouwantedis:"+queryBookValue);out.close();}}11.4.3提取客户
端信息(续)——QueryServlet.java与客户端交互5511.4.3提取客户端信息(续)——query.html与QueryServlet运行结果与客户端交互5611.4.4发送HTML信息⚫Web服务器响应(response)的构成–状态行⚫由http版本(HTTP/1.1),一
个状态代码(200)和一段对应状态代码的简短消息(OK)组成–一些响应报头、⚫Content-Type:text/html指定后面文档MIME类型,后面的其他报头可选。常用MIME类型有:text/html:HTML文档text/plain:纯文本text/xml:XMLimage
/jpeg:JEPG图像application/msword:MicrosoftWord文档application/pdf:crobat文件application/zip:Zip档案–一个空行和响应的文档与客户端交互57HTTP/1.1200OK//状态行Content-Type:text/htm
l//报头Header2:……HeaderN:…//空行<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0Transitional//EN">//文档<HTML><HEAD>headcode</HEA
D><BODY>…</BODY></HTML>11.4.4发送HTML信息(续)与客户端交互58⚫向客户端输出一个简单网页,显示“HelloWorld!”importjava.io.*;importjavax.servlet.*;importjavax.servlet.htt
p.*;publicclassHelloWorldextendsHttpServlet{publicvoiddoGet(HttpServletRequestreq,HttpServletResponseres)throwsServletExceptio
n,IOException{res.setContentType("text/html");PrintWriterout=res.getWriter();out.println("<HTML>");out.println("<HEAD><TITLE>HelloWorl
d</TITLE></HEAD>");out.println("<BODY>");out.println("<BIG>HelloWorld!</BIG>");out.println("</BODY></HTML>");}}11.4.4发
送HTML信息(续)——例11_4与客户端交互59⚫程序说明–HelloWorld继承了HttpServlet,然后重写doGet方法–在doGet方法中,首先将HTTPContent-Type响应报头设置
为text/html,即指定响应的类型为HTML文档;然后通过getWriter()得到PrintWriter类型的一个对象out,按照HTML格式输出一个简单网页⚫运行结果11.4.4发送HTML信息(续)——例11_4运行结果与客户端交互6011.5客户端跟踪⚫客户端
跟踪–HTTP是无状态协议,服务器不能自动维护客户连接的上下文信息–许多情况下,Web服务器必须要能够跟踪用户的状态⚫比如购物网站和电子邮件网站,当用户登录以后,其身份和一系列的操作状态都需要被跟踪并保持–servletAPI提供了两种可以跟踪客户端状态的方法⚫Cook
ie⚫Session6111.5.1使用Cookie⚫Cookie–是Web服务器保存在用户硬盘上的一段文本,Web服务器将它发送到浏览器–之后,当再次访问同一网络时,浏览器将它原封不动的返回–其中的信息片断以‘名/值’对(name-valuepairs)的形式储存–使用这种方法,
网站可以维护客户的连接。这种用途可以体现在如下几点⚫在电子商务中标识用户,实现短期跟踪用户⚫记录用户名和用户密码,允许用户下次自动登陆⚫定制站点,记录用户的偏好⚫定向广告,记录用户感兴趣的主题,并显示与之相关的广告客户端跟踪62⚫调用Cookie的构造函数可创建一个cookie–构造方法
接受两个字符串参数⚫cookie名称⚫cookie的值–例如创建一个名为CookieName,值为John的cookie,可以使用下面的语句Cookielogin=newCookie(“CookieName”,”John”);客户端跟踪11.5.1使用Cookie(续)——创建Cookie对象6
3⚫创建了一个名为login的cookie之后,可通过很多现有的方法设置cookie的值和属性–可通过如下语句设置cookie的注释:login.setComent(“YoucangetUserNameformthiscookie”);–创建cookie并将它发送到浏览器后,
默认情况下,它是会话级的cookie,仅仅存储在浏览器内存中,用户退出浏览器后,cookie将被删除;如果希望将cookie存储在磁盘上,则需要设定MaxAge,给出一个以秒为单位的生命周期,如下可以将生命设置为一天login.set
MaxAge(60*60*24)//oneday–setPath(),setValue(),setVersion(),setDomain(),setSecure()等,相关的具体用法请查看servletAPI11.5.
1使用Cookie(续)——设置Cookie属性客户端跟踪64⚫刚创建的cookie存在于服务器内存中。必须将它发送到客户端,cookie才能真正的发挥作用。发送cookie需要使用HttpServletResponse的addCookie方法,将cook
ie插入到一个HTTP响应报头。发送的语句如下publicvoiddoGet(HttpServletRequestreq,HttpServletResponseres)throwsServletException,IOExcep
tion{Cookielogin=newCookie(“UserName”,”John”);login.setComent(“YoucangetUserNameformthiscookie”);res.addCookie(login);//...}客户端跟踪11
.5.1使用Cookie(续)——发送Cookie到客户端65⚫从客户端读取你感兴趣的cookie,需要两个步骤–首先调用request.getCookies得到一个Cookie对象的数组–然后调用每个cookie的getName方法,从数组中寻找所需的cookieStringna
meString=“UserName”Cookie[]cookies=request.getCookies();for(inti=0;i<cookies.length;i++){Cookiecookie=cookies[i];if(nameString.equals(cookie.getNa
me())){//dosomething…//cookies.setMaxAge(0);}}⚫找到感兴趣的cookie之后,便可以操作此cookie,如通过getValue方法得到相关cookie的值,设置MaxAge等客户端跟踪11.5.1
使用Cookie(续)——从客户读取Cookie6611.5.2使用Session⚫Session–一段时间内,单个客户与web服务器的一连串的交互过程–在一个Session中客户可能会多次请求访问同一个网页,也有可能请求访问各种不同的服务器
资源,其间用户的状态需要跟踪并保持–存在于服务器端,不在网络上传送–它的好处是可以用来记录客户端私有的信息,并且在时间范围内不会消失客户端跟踪6711.5.2使用Session(续)⚫Session的使用可以分为三个步骤–获得一个session–存储数据到session或从session
读取数据–销毁session客户端跟踪68⚫通过调用httpServletRequest的getSession方法可以得到一个sessionHttpSessionsession=request.getSession();⚫为了保持正确的会话,必须在发
送任何文档到客户程序之前获得一个sessionpublicclassSessionServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestrequest,Htt
pServletResponseresponse)throwsServletException,IOException{//Gettheuser'ssessionHttpSessionsession=request.getSession(true);//...out=res
ponse.getWriter();//...}}客户端跟踪11.5.2使用Session(续)——获得一个Session69⚫SessionID–Servlet容器为HttpSession分配的一个唯一标识符–作为Co
okie保存在客户的浏览器中⚫sessioncookie–每次客户发出HTTP请求时,Servlet容器可以从HttpRequest对象中读取SessionID,然后根据SessionID在服务器端找到相应的HttpSession对象,从而获取客户的
状态信息,这样的cookie叫做sessioncookie–存储于浏览器内存中的,并不写到硬盘上的–针对某一次会话而言,会话结束也就随着消失了客户端跟踪11.5.2使用Session(续)——存储或读取数据70⚫URL
重写–浏览器不支持Cookie,或者将浏览器设置为不接受Cookie的情况,可通过URL重写来实现会话管理–向URL连接添加参数,并把sessionID作为值包含在连接中。为servlet响应部分的每个连
接添加sessionID,可以使用一对方法⚫response.encodeURL():使URL包含sessionID⚫response.encodeRedirectURL():使用重定向客户端跟踪11.5.2使用Session(续)——存储或读取数据71⚫
从Session中读取数据–session.getAttribute(“name”)⚫查找以前存储的值⚫如果不存在则返回null⚫在调用此方法返回的对象前,一定要检查它是否为null⚫向session中设置相关信息–setAttribute⚫替换掉此前设定的任何值–removeAttribut
e⚫移除而不是替换某个值客户端跟踪11.5.2使用Session(续)——存储或读取数据72publicclassSessionServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestrequest,HttpServletResp
onseresponse)throwsServletException,IOException{//Gettheuser'ssessionHttpSessionsession=request.getSession(true);SomeClassscl=(Some
Class)session.getAttribute("name1“);//IftheuserhasnoSomeClassobject,createanewoneif(scl==null){scl=newSomeClass()
;session.putAttribute("name1",scl);}//...}}11.5.2使用Session(续)——SessionServlet.java客户端跟踪73⚫销毁Session–意味着从系统删除session对象及其值–自动销毁⚫在一段时间(时间长短依赖与Web服务器的设
定)没有request的情况下,Web服务器会自动销毁session–手动销毁⚫通过调用session的invalidate方法可以手动的销毁session–logout⚫在支持servlet2.4的服务器中,可调用logout将客户从Web
服务器中注销,同时废弃所有与该用户相关联的会话⚫需要注意的是,这个动作会影响到此servlet之外的其他servlet,因此一定要与网站的其他开发人员协调使用11.5.2使用Session(续)——销毁Session客户端跟踪741
1.6协作与通信⚫协作与通信–为了更好的响应客户端的请求,servlet有时需要和网络上的其他资源进行通讯,比如⚫HTML网页⚫其他servlet⚫JSP网页–Servlet协作通讯的第一步是获得分发器(dispatcher),即RequestDispatcher接口的一个对象75⚫
RequestDispatcher接口–产生一个RequestDispatcher接口的对象⚫RequestDispatcherdispatcher=getServletContext().getRequestDispatcher("/SomePa
th/SomeString");⚫通过设置字符串参数,可以获得servlet,HTML网页,JSP网页等“资源”–forward方法⚫将本servlet的request请求传递给“其他资源”响应⚫通过利用此方法可实现:servlet先预处理request,然后将处理后的requ
est传递给“其他资源”处理–include方法⚫引入“其他资源”来响应客户端的请求11.6.协作与通信(续)——RequestDispatcher接口协作与通信76⚫MyServlet1获取另外一个servlet(MyServlet2),并用它来响应用户的请求importjava
.io.*;importjavax.servlet.*;importjavax.servlet.http.*;publicclassMyServlet1extendsHttpServlet{publicvoiddoGet(H
ttpServletRequestreq,HttpServletResponseres)throwsServletException,IOException{res.setContentType("text/html");RequestDispatchersummary=getServletCo
ntext().getRequestDispatcher("/servlet/MyServlet2");协作与通信11.6.协作与通信(续)——MyServlet1.java77if(summary!=null){try{summary.include(req,res);
}catch(IOExceptione){}catch(ServletExceptione){}}elseif(summary==null){PrintWriterout=res.getWriter();out.println("<HTML>")
;out.println("<HEAD><TITLE>Error</TITLE></HEAD>");out.println("<BODY>");out.println("<BIG>SummaryisNull</BIG>");out.println("</BODY></HTML>");}}}协作与
通信11.6.协作与通信(续)——MyServlet1.java78importjava.io.*;importjavax.servlet.*;importjavax.servlet.http.*;publicclassMyServ
let2extendsHttpServlet{publicvoiddoGet(HttpServletRequestreq,HttpServletResponseres)throwsServletException,IOException{r
es.setContentType("text/html");PrintWriterout=res.getWriter();out.println("<HTML>");out.println("<HEAD><TITLE>MYsec
ondServlet</TITLE></HEAD>");out.println("<BODY>");out.println("<tableborder=2><tr><td>name</td><td>Bu
sh</td>");out.println("<td>Sex</td><td>Male</td></tr><tr><td>City</td>");out.println("<td>NewYork</t
d><td>Country</td><td>U.S.A</td></tr>");out.println("</BODY><HTML>");}}协作与通信11.6.协作与通信(续)——MyServlet2.java7911.6.1Applet与Servlet的通
信⚫Applet与Servlet的通讯–用户用Applet发送消息到服务器–对于动态网页,Applet与Servlet的通讯尤为重要–比如在一个聊天系统中,当一个用户输入了某些语句时,聊天室内的所有其他用户都可以看到。此功能可能的实现步骤是⚫用户先把消息发给服务器⚫然后服务器发送给聊天
室内的所有用户⚫Applet和Servlet通讯的方式有多种–通过socket直接建立网络连接–通过远程方法调用(RemoteMethodInovation)通讯–通过CORBA通讯协作与通信80⚫Socket通讯–服务器端的操作⚫首先创建一个ServerSocket对象,在指定端口监听
客户端的request⚫在接收到request后,accept()方法返回一个Socket对象⚫通过socket对象创建输入输出流对象,并实现与客户端的交互⚫交互完毕后,关闭输入输出流和socket,最后关闭ServerSocker
–客户端的操作⚫首先创建socket对象,建立与服务器的连接⚫然后通过socket对象创建输入输出流,实现与服务器的交互⚫最后关闭输入输出流和socket协作与通信11.6.1Applet与Servlet的通信(续)——So
cket通讯81⚫RMI通讯–RemoteMethodInvocation的简写,即远程方法调用–通过存在于远程机器上的对象,可以发消息给远程的机器,且可以取得远程机器程序执行的结果。整个调用过程类似于此对象存在于本地机器,无疑这大大简化了通讯过程–当大量的数据是由服务器端的对象动态提供时使
用RMI通讯是非常合适的–如何使用RMI⚫先定义一个继承自java.rmi.Remote的公用接口。在该接口中定义要求在服务器上运行的方法⚫接下来是实现远程接口,远程接口的实现类应该实现:定义远程对象的构造方法,创
建和安装安全管理器,创建一个或多个远程对象实例,并注册至少一个远程对象协作与通信11.6.1Applet与Servlet的通信(续)——RMI通讯82⚫通过CORBA通讯–即公用对象请求代理体系(CommonObjectRequestBrokerArchitecture),是OMA定义的一套和语言
无关的分布式对象交换标准框架(Standardframeworkofobjectinteroperability)–CORBA的主要功能是RPC(RemoteProcedureCall)式的支持,它使得本机对象可以调用远端对象的函数–使用方法类似于RMI⚫定义接口⚫创建类实现接
口⚫在服务器上注册后客户就可以像本地对象一样访问远程对象了11.6.1Applet与Servlet的通信(续)——通过CORBA通讯协作与通信83⚫CORBA和RMI的主要区别–CORBA使用一种语言中立的接口定义语言(IDL)来定义接口,IDL是一种可用于混合语言环境的更为广泛的
协议集–RMI让Java对象之间可以进行RPC–CORBA则让任何语言实现出来的对象之间进行RPC11.6.1Applet与Servlet的通信(续)——CORBA和RMI的主要区别协作与通信8411.6.2Servlet间的信息共享⚫servlet间的信息共享–通过方法调用–通过共享
类对象–利用java语言的Properties列表⚫Properties列表包含系统的很多信息,比如java.version,path,separater,应用程序相关的很多属性等⚫可通过如下的方法添加一个属性到此列表System.getProperties().put("key","va
lue");⚫运行在同一个JVM上的其他servlet可调用属性Stringvalue=System.getProperty("key");⚫也可以通过如下语句删除列表中的某项属性:System.getPropertie
s().remove("key");协作与通信8511.7程序举例——例11_7⚫通过会话跟踪,实现对客户访问次数记数的功能importjava.io.*;importjavax.servlet.*;importjavax.se
rvlet.http.*;importjava.net.*;importjava.util.*;publicclassTrackSessionextendsHttpServlet{publicvoiddoGet(
HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{Stringheading;Integercount;response.setConten
tType("text/html");HttpSessionsession=request.getSession(true);count=(Integer)session.getAttribute("count");86if(count==null){co
unt=newInteger(0);heading="Firstvisiting";}else{heading="WelcomeBack";count=newInteger(count.intValue
()+1);}session.setAttribute("count",count);PrintWriterout=response.getWriter();StringdocType="<!DOCTYRPHTMLPUBLIC\"-//W3C
//DTDHTML4.0"+"Transitional//EN\">\n";out.println(docType+"<BODYBGCOLOR=\"#FDF5E6\">\n"+"<H1ALIGN=\"CENTER\">"+heading+"</H1>\
n"+"<TABLEBORDER=1ALIGN=\"CENTER\">\n"+"<TRBGCOLOR=\"#FFAD00\">\n"+"<TH>NAME<TH>VALUE\n"+"<TR>\n"+"<TD>ID:\n"+"<TD>"+session.getId()+"\n
"+"<TR>\n"+"<TD>CreationTime:\n"+"<TD>"+newDate(session.getCreationTime())+"\n"+"<TR>\n"+"<TD>LastAccessTime
:\n"+"<TD>"+newDate(session.getLastAccessedTime())+"\n"+"<TR>\n"+"<TD>Count:\n"+"<TD>"+count+"\n"+"</TABLE>\n"+"</BODY></HTML>“);}publicvoid
doPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{doGet(request,resp
onse);//doPost方法直接调用doGet}}11.7程序举例——例11_7程序举例8711.7程序举例——例11_7运行结果程序举例88⚫利用cookie的servlet同样也可以实现记录用户访问次数的功能importjava
.io.*;importjavax.servlet.*;importjavax.servlet.http.*;importjava.net.*;publicclassAccessCountsextendsHttpServlet{publicvoiddoGet(Htt
pServletRequestreq,HttpServletResponseres)throwsServletException,IOException{StringcookieName,numString;c
ookieName="numString";numString="1";Cookie[]cks=req.getCookies();if(cks!=null){for(inti=0;i<cks.length;i++){CookietempCk=cks[i];if(cook
ieName.equals(tempCk.getName()))numString=tempCk.getValue();}}11.7程序举例——例11_8程序举例89intnum=0;try{num=Integer.parseInt(numString);}catch(NumberForma
tExceptione){}CookiemyCookie=newCookie("numString",String.valueOf(num+1));myCookie.setMaxAge(60*60*24);res.addCookie(
myCookie);res.setContentType("text/html");PrintWriterout=res.getWriter();Stringtitle="UserAccessCount";StringdocType="<
!DOCTYRPHTMLPUBLIC\"-//W3C//DTDHTML4.0"+"Transitional//EN\">\n";out.println(docType+"<html>\n"+"<head><title>"+title+"</title></head>"
+"<body>\n"+"<h1>AccessCountis:"+num+"</h1>"+"</body></html>");}}11.7程序举例——例11_8程序举例90程序举例11.7程序举例——例11_8运行结果91⚫例11_7使用Session的servle
t–重启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结果分析9211.8本章小结⚫本章内容–Java网络程序设计的基本概念–servlet的基础知识,包括servlet的基本结
构和生命周期–servlet与客户端交互的技术以及客户端跟踪技术–servlet与其它网络资源的交互⚫本章要求–了解基于TCP协议的有连接通讯和基于UDP协议的数据报通讯的含义–熟悉servlet的常用API以及servlet的编程方法