




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第7章Web服务器端编程与JavaServlet7.1Web服务器端编程概述
7.2客户端数据的提交和服务器端的提取7.3Web程序中数据的分类7.4Web数据传输协议——HTTP7.5Servlet的提出和工作原理7.6Servlet的设计和实现
7.7ServletAPI常用接口和类7.8Servlet应用实例习题
7.1Web服务器端编程概述
Web服务器端编程负责完成在服务器端运行的程序的设计和编码,这些程序的主要功能一般是进行业务逻辑的处理。通常的做法是数据的存储使用数据库系统及文件系统,通过使用数据库访问接口访问数据库系统中存储的数据,根据应用系统业务逻辑对这些数据进行处理,然后把相关处理结果发送到客户端,或者存储到文件或数据库系统中。Web服务器端编程模型如图7.1所示。图7.1Web服务器端编程模型根据以上模型可知,开发Web系统首要的工作就是系统模块划分。从逻辑层次上可以将系统模块划分为如下三层:
(1)界面层:主要用于界面展示、客户输入数据。该部分用HTML(HyperTextMarkupLanguage)格式的文件作为客户端软件解析、显示的数据文件,即通常所说的网页。在HTML文件中可以包含在客户端浏览器环境下解释执行的客户端脚本(如受浏览器支持的广泛使用的JavaScript脚本)、用来控制显示样式的CSS(CascadingStyleSheets)文件、用来绘制动态图形和完成简单客户端功能的JavaApplet等。
(2)应用逻辑处理层:也称为业务处理层,主要完成系统数据处理,是系统的核心。数据是业务在计算机中的表示,根据系统业务流程设计出程序流程图,进而去编码实现。根据服务器支持的运行环境,可选用不同的开发脚本语言。如果服务器端具备Java运行环境,可以使用JSP(JavaServerPages)脚本、Servlet程序;如果具备PHP(HypertextPreprocessor)运行环境,可以使用PHP脚本。当今可以选用的开发脚本语言多达十多种,在制定系统方案时,可以根据系统应用环境和成本、开发难度,选取一种开发脚本语言来作为系统开发脚本语言。
(3)数据存储层:用来存储数据,依据系统设计阶段设计的数据字典,将系统数据存储在数据库系统文件中,然后通过数据库访问接口访问该数据库系统中的数据。数据库的系统维护和管理由数据库系统管理员负责,数据库数据的访问通过脚本程序进行,这就实现了数据库的透明访问,提高了系统的安全性和可靠性。
该种划分法从逻辑层次到物理实现的映射可用图7.2来表示。系统设计和分析人员通常根据这种逻辑划分来分析和定义系统模块。程序设计的流程按照数据的读取、保存和处理来分别进行。由于采用了数据库系统,故数据的读取和保存变得容易,使程序设计者能够把主要精力放在业务流程对应的数据处理上。系统和用户的交互界面一般是浏览器支持的GUI图形界面,即由文本、图片、表单构成的页面,程序设计者应该站到系统界面的角度去设计页面,与传统的主要用来展示文本内容的网页区分开来。图7.2Web应用程序从逻辑层次到物理实现的映射7.2客户端数据的提交和服务器端的提取
客户端用户向服务器端程序提交数据主要通过表单来进行。关于表单的标准理论请参考网上文档,网址为/TR/html401/interact/forms.html#h-17.1。表单(Form)是对客户端浏览器软件向服务器端程序提交的数据进行封装的控件。提供给编程人员的接口是表单和表单项。表单项的名称用来关联数据项名称,在软件中常把这种方法叫做“Key-Value”,即键—值对,键即表单项名称,值即填入表单控件中的文本。服务器端程序提取数据时主要通过表单项来获取对应值,然后使用这些数据进行处理。表单通过如下形式
定义:
<formname=“login”action=“forward.jsp”method=“get”>
<inputtype=“text”name=“username”value=“liuyongping”>
</form>
或
<formname=“form1”action=“process.jsp”method=“post”>
</form>
其中,action和method属性非常关键。action属性定义了该表单信息和哪个文件相关联,即由哪个服务器端程序来提取和处理该表单数据。如在此例中由process.jsp这个程序来处理该表单数据。method属性定义了该表单信息的传送(传输)方式,可选post和get中的任意一种。采用post方式时,表单的数据是被客户端浏览器封装在请求消息体中来进行传送的,故保密性强。而采用get方式时,表单的数据是附在URL之后,以问号“?”隔开,数据以name=value对的形式出现的,多个数据对使用符号“&”隔开。get方式常用于少量数据传送(<1KByte),由于发送时数据显示在浏览器地址栏中,容易被看到和记录,故保密性差。
【例7.1】以get方式向服务器提交表单数据,该表单完成用户名和密码的提交,如图7.3所示。请注意观察图7.4的URL地址栏内容。图7.3登录界面源文件login_get_method.html内容如下:
<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01
Transitional//EN”“/TR/html4/loose.dtd”>
<html>
<head>
<metahttp-equiv=“Content-Type”content=“text/html;
charset=gb2312”>
<title>登录模块</title>
</head>
<bodybgcolor=“FFFFFF”>
<h1align="center"><b>欢迎登录系统</b></h1>
<formaction=“forward.jsp”method=“get”>
<!--指定由forward.jsp来处理该表单,提交数据方式为post-->
<p></p>
<!--以2行2列的表格来布局-->
<tablewidth=“52%”border=“2”align=“center”>
<trbgcolor=“#FFFFCC”>
<tdalign=“center”width=“43%”><divalign=“center”>用户名:
</div></td>
<tdwidth=“57%”><divalign=“left”>
<inputtype=“text”name=“username”>
</div></td>
</tr>
<trbgcolor=“#CCFF99”>
<tdalign=“center”width=“43%”><divalign=“center”>密码:</div></td>
<tdwidth=“57”><divalign=“left”>
<inputtype=“password”name=“password”>
</div></td>
</tr>
</table>
<!--以段的形式来组织两个按钮-->
<palign=“center”>
<inputtype=“reset”name=“Reset”value=“重置”>
<inputtype=“submit”name=“Submit2”value=“提交”>
</p>
</form>
</body>
</html>
源文件forward.jsp内容如下:
<%@pagelanguage=“java”contentType=“text/html;
charset=gb2312”
pageEncoding="gb2312"%>
<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01
Transitional//EN”“/TR/html4/loose.dtd”>
<html>
<head>
<metahttp-equiv=“Content-Type”content=“text/html;
charset=gb2312”>
<title>loginforward</title>
</head>
<body>
<%
Stringusername=null;
Stringpassword=null;
request.setCharacterEncoding(“gb2312”);
username=request.getParameter(“username”);
password=request.getParameter(“password”);
if(!username.equals(“”)&&!password.equals(“”))
{
%>
<jsp:forwardpage=“login_ok.jsp”>
<jsp:paramname=“username”value=‘<%=username%>’/>
<jsp:paramname="username"value='<%=password%>'/>
</jsp:forward>
<%
}
else
{
%>
<jsp:forwardpage=“error.jsp”>
<jsp:paramname=“username”value=‘<%=username%>’/>
<jsp:paramname=“username”value=‘<%=password%>’/>
</jsp:forward>
<%
}
%>
</body>
</html>
其中,login_ok.jsp和error.jsp文件源代码请参考9.6.1小节的例9.1中这两个文件的源代码。该实例运行结果如图7.4所示。图7.4处理数据界面
1.表单数据的填入
当表单中的输入控件项获得焦点时,用户输入或者选择数据。表单中可使用的控件有文本输入控件、密码输入控件、单选控件、复选控件等。
【例7.2】以post方式向服务器提交表单数据,该表单发送某单位工作人员的周小结给部门经理,供部门经理阅读,界面如图7.5所示。注意与例7.1的以get方式提交数据进行比较。图7.5表单界面源文件weeklog.html内容如下:
<!DOCTYPEhtmlPUBLIC“-//W3C//DTDXHTML1.0Strict//EN”
“/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<htmlxmlns=“/1999/xhtml”>
<head><metahttp-equiv=“Content-Type”content=“text/html;
charset=gb2312”>
<title>工作周志</title></head>
<body>
<formaction=“process.jsp”method=“post”>
<div><center>
<label>姓名<inputtype=“text”name=“username”
size=“10”/>
</label><br/><br/><label>周小结<br/>
<textareaname=“weeklog”rows=“5”
cols=“60”></textarea>
</label><br/>
完成情况
<label>
<inputtype=“radio”name=“boxgroup1”value
=“非常好”/>非常好
</label>
<label>
<inputtype=“radio”name=“boxgroup1”value
=“完成”/>完成
</label>
<label>
<inputtype=“radio”name=“boxgroup1”value
=“未完成”/>未完成
</label><br/><br/>
<inputtype=“submit”name=“doit”value=“提交”/>
</center></div>
</form>
</body>
</html>
其中,<metahttp-equiv=“Content-Type”content=“text/html;charset=gb2312”>中的meta标签的charset属性指定请求信息的编码方式为支持中文字符的gb2312编码方式,如果不指定其编码方式,在服务器端获取中文时可能出现乱码。
当表单中的控件获得输入焦点后,用户输入数据,点击“提交”按钮,客户端浏览器软件完成表单数据的封装和发送。
2.表单数据的传送
表单数据被客户端软件封装后通过网络传送到服务器端,传送的方式由表单的method属性指定。如果选择的是post方式,数据放在HTTP请求消息体中;如果选择的是get方式,数据放在HTTP请求消息头中。服务器如Tomcat把HTTP请求消息用Java语言封装成HttpServletRequest对象。
3.表单数据的提取
服务器软件接收到传送来的请求消息后,先进行消息解析,然后根据流程进行处理,最后将处理结果通过响应消息返回给客户端软件。如果由JSP引擎来接收消息,该引擎将消息封装成HttpServletRequest类型的对象并提供给JSP程序访问,通过调用HttpServletRequest类型的对象request的方法getParameter(Stringname)来完成数据的提取。该方法的原型为ObjectgetParameter(Stringname),如提取例7.1和例7.2中的用户名和周小结数据,可使用如下语句:
Stringstr_Username=request.getParameter(“username”);
Stringstr_Weeklog=request.getParameter("weeklog");
【例7.3】提取表单数据示例。提取例7.2中的表单数据并显示在页面上,显示结果如图7.6所示。
源文件process.jsp代码如下:
<%@pagelanguage=“java”contentType=“text/html;
charset=gb2312”
pageEncoding=“gb2312”%>
<html><head>
<metahttp-equiv=“Content-Type”content=“text/html;
charset=gb2312”>
<title>提取表单数据</title></head>
<body>
<%
request.setCharacterEncoding(“gb2312”);
response.setContentType(“text/html;charset=gb2312”);
out.println(request.getParameter(“username”));
out.println(request.getParameter(“weeklog”));
out.println(request.getParameter(“boxgroup1”));
%>
</body></html>图7.6处理数据界面
7.3Web程序中数据的分类
Web应用程序对大量数据进行处理时,这些数据的表示方式、存储方式、使用范围和使用时限各不相同,为此,需要分类来进行表示。按数据的使用范围可将Web应用程序中的数据分为全局数据、页面内数据和方法体内数据,如图7.7所示。图7.7Web应用程序中数据的划分
1.全局数据
模块(多个文件)之间需要通过全局数据来交换信息,这类型的数据由系统开辟一块公共存储区进行存放,供各文件访问。JSP系统提供了application、session、servletcontext等全局数据对象,开发者可以方便地使用这些对象完成模块之间的数据交换。
在实际应用中,需要记录和跟踪用户访问系统的情况,此时需要使用全局数据对象session。用户在访问不同的页面并完成一次与系统的交互后,相关信息可以保存到session对象中,通过调用session对象提供的getSession和setSession方法完成从ession对象中读取数据和向session对象中写入数据。session数据区示意图如图7.8所示。图7.8session数据区示意图
2.页面内数据
页面内数据的可见范围为页面,有效期为页面初始化到页面执行结束,它为页面内不同方法之间进行数据交换提供了途径。JSP系统定义的页面内数据对象有page、pageContext、out、request、response、exception等,开发者可以采用类似<%!Stringstr=null;%>的语法定义各种类型的对象。一个页面被Servlet翻译成一个Servlet对象,页面内数据被Servlet翻译成Servlet类的公共数据,供Servlet的各个方法相互访问。
3.方法体内数据
方法体内数据即局部变量,其可见范围为Java类的方法体内。JSP系统在脚本<%%>中定义的对象即属于局部对象,如果数据只在方法内使用,则定义为方法体内数据。
在一个具体的应用系统中,用户的鉴权、认证、跟踪一般是必需的,Web系统广泛采用的是cookie和session两种机制。cookie用来在客户端记录信息,session用来在服务器端记录信息。cookie是客户端通过开辟一个文件供服务器端程序动态地写入和读出的信息集合体,服务器端程序生成cookie内容并填入响应消息的特定字段,再传输到客户端,由客户端写入文件保存。客户端向服务器端传输请求信息时,可以把cookie内容传输到服务器端,供服务器程序处理。
【例7.4】通过session对象保存用户名和密码,记录和跟踪系统用户信息。登录界面如图7.9所示,登录成功后的界面如图7.10所示,使用系统业务功能界面如图7.11所示。图7.9登录界面源文件firstlogin.html内容如下:
<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01
Transitional//EN”“/TR/html4/loose.dtd”>
<html>
<head>
<metahttp-equiv=“Content-Type”content=“text/html;
charset=gb2312”>
<title>登录模块</title>
</head>
<bodybgcolor=“FFFFFF”>
<h1align="center"><b>欢迎登录系统</b></h1>
<formaction=“savelogin.jsp”method=“post”>
<!--指定由savelogin.jsp来处理该表单,提交数据方式为post-->
<p></p>
<!--以2行2列的表格来布局-->
<tablewidth=“52%”border=“2”align=“center”>
<trbgcolor=“#FFFFCC”>
<tdalign=“center”width=“43%”><divalign=“center”>用户名:</div></td>
<tdwidth=“57%”><divalign=“left”>
<inputtype="text"name="username">
</div></td>
</tr>
<trbgcolor=“#CCFF99”>
<tdalign=“center”width=“43%”><divalign=“center”>密码:</div></td>
<tdwidth=“57”><divalign=“left”>
<inputtype=“password”name=“password”>
</div></td>
</tr>
</table>
<!--以段的形式来组织两个按钮-->
<palign=“center”>
<inputtype=“reset”name=“Reset”value=“重置”>
<inputtype=“submit”name=“Submit2”value=“提交”>
</p>
</form>
</body>
</html>图7.10登录成功后的界面源文件savelogin.jsp内容如下:
<%@pagelanguage=“java”contentType=“text/html;
charset=gb2312”
pageEncoding=“gb2312”%>
<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01Transitional//EN”
“/TR/html4/loose.dtd”>
<html>
<head>
<metahttp-equiv=“Content-Type”content=“text/html;
charset=gb2312">
<title>Savelogininformation</title>
</head>
<body>
<%!Stringurl=null;%>
<%
Stringusername=null;
Stringpassword=null;
request.setCharacterEncoding(“gb2312”);
response.setContentType(“text/html;charset=gb2312”);
username=request.getParameter("username");
password=request.getParameter(“password”);
session.setAttribute(“username”,username);
session.setAttribute(“password”,password);
url=response.encodeURL(“business.jsp”);
%>
<ahref=‘<%=url%>’>usesystem!</a>
</body>
</html>图7.11使用系统业务功能界面源文件business.jsp内容如下:
<%@pagelanguage=“java”contentType=“text/html;
charset=gb2312”
pageEncoding=“gb2312”%>
<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01
Transitional//EN”
“/TR/html4/loose.dtd”>
<html>
<head>
<metahttp-equiv=“Content-Type”content=“text/html;
charset=gb2312">
<title>Usesystem</title>
</head>
<body>
<%
Stringusername;
Stringpassword;
username=(String)session.getAttribute(“username”);
password=(String)session.getAttribute(“password”);
out.println(“Currentuser[<fontcolor=red>”+username+“</font>]”);
%>
</body>
</html>
【例7.5】写入cookie信息和从cookie中读出信息,用于客户端跟踪和验证。写入cookie信息界面如图7.12所示,读出cookie信息界面如图7.13所示。图7.12写入cookie信息界面源文件writecookie.jsp内容如下:
<%@pagelanguage=“java”contentType=“text/html;charset=ISO-8859-1”
pageEncoding=“ISO-8859-1”%>
<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01
Transitional//EN”“/TR/html4/loose.dtd”>
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html;charset=ISO-8859-1">
<title>writecookie</title>
</head>
<body>
<divalign=“center”>writecookie</div>
<%
Cookiecook=newCookie(“KeyName”,“Iamakeyvalue”);
cook.setMaxAge(30*60);
response.addCookie(cook);
out.print(“Finishingwritecookie”);
%>
<br>
<br>
<ahref=“readcookie.jsp”>readcookie
</body>
</html>图7.13读出cookie信息界面源文件readcookie.jsp内容如下:
<%@pagelanguage=“java”contentType=“text/html;charset=ISO-8859-1”
pageEncoding=“ISO-8859-1”%>
<!DOCTYPEhtmlPUBLIC“-//W3C//DTDHTML4.01Transitional//EN”
“/TR/html4/loose.dtd”>
<html>
<head>
<metahttp-equiv=“Content-Type”content=“text/html;
charset=ISO-8859-1">
<title>readcookie</title>
</head>
<body>
<%
Cookiecookies[]=request.getCookies();
CookiesCookie=null;
StringstrValue=null;
StringstrKeyName=null;
if(cookies==null)
{
out.println("nocookierecord");
}
else
{
out.println(“<br>thenumberofcookie:”+cookies.length);
for(inti=0;i<cookies.length;i++)
{
sCookie=cookies[i];
strKeyName=sCookie.getName();
strValue=sCookie.getValue();
out.println(“<br>cookiekeyname:”+strKeyName+“,
thevalueof:”+strValue);
}
7.4Web数据传输协议——HTTP
Web服务器软件和客户端软件之间的通信一般使用HTTP或HTTPS协议。HTTP(HypertextTransferProtocol,超文本传输协议)主要用来在网络上传输文本内容,采用请求/响应的模式来工作,如图7.14所示。图7.14HTTP协议示例图
HTTP协议包括两种类型的消息,分别是请求消息和响应消息。请求消息用来发送请求内容,响应消息用来携带返回服务器端的处理结果内容。响应消息经常返回一个服务器的资源文件,如HTML文件等。
两种类型的消息字段如图7.15所示。图7.15HTTP消息示例下面是一个HTTP请求消息的例子。
Get/sample.jspHTTP/1.1
Accept:image/gif,image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozilla/4.0(compatible;MSIE5.01;WindowsNT5.0)
Accept-Encoding:gzip,deflate
Username=liuyongping&password=liuyongping
HTTP请求消息一般包含如下三部分:
第一部分:请求方法URI协议/版本。上面的请求消息示例第一行即指名请求方法为Get,请求的文件为 /sample.jsp,协议为HTTP,版本号为1.1。其中HTTP1.1支持get、post、head、put、delete、trace、options请求方法,如表7.1所示。其中get和post是最常用的请求方法。该部分的URI完整地指定了要访问的网络资源,通常只要给出相对于服务器的根目录的相对目录即可,因此总是以“/”开头。紧接着是协议名称,最后以“/”分割后面的版本号说明,即所使用的HTTP的版本。
get方法通常只用于请求指定服务器上的资源,这种资源可以是静态的HTML页面或其他文件,也可以是由CGI程序生成的结果数据。使用get方法请求文件也可以向服务器传送一些数据,例如:
get/login.jsp?name=liuyongping&password=***HTTP/1.1
以post方法提交的数据是通过消息体的形式进行传送的,提交的数据量一般比较大,而且比较安全,例如:
<formname="form1"method="post"action="showdata.jsp">第二部分:请求头。该部分包含许多客户端环境信息和请求体的重要信息,具体可包含Accept、Accept-Language、Use-Agent、Ua-Cpu、Accept-Encoding、Host、Connnection、Cookie等字段。上面的请求消息示例从第二行到“Accept-Encoding:gzip,deflate”行结尾部分都为请求头部分。
第三部分:请求正文。上面的请求消息示例的请求头下面隔一个空行后即为正文部分,或称为请求消息体。该部分可以包含客户提交的查询字符串信息等。请求头部分和请求正文部分的分割是一个空行。响应消息也由三部分组成:第一行为第一部分,如“HTTP/1.1200OK”,其中HTTP是协议说明,1.1是版本号,200是响应码,“OK”是响应码说明;第二部分为响应消息头,包含Server、Date、Content-Type、Last-Modified、Content-Length等字段,这些字段用来说明响应信息内容的重要属性,如内容的类型(编码方式)、内容的长度等,客户端软件可根据此处理消息体内容;第三部分为消息内容体,若响应头Content-Type字段为text/html,则该部分消息内容为超文本字符。消息头和消息体之间通过一个空行分隔。下面是一个HTTP响应消息的例子,显示结果如图7.16
所示。图7.16HTTP响应体内容显示
HTTP/1.1200OK
Server:ApacheTomcat/6.0.10
Date:Mon,6Oct200313:13:33GMT
Content-Type:text/html
Last-Modified:Mon,6Oct200313:23:42GMT
Content-Length:112
<html>
<head>
<title>HTTPresponseexample</title>
</head>
<body>
ThisisHTTPresponsebodycontent.
</body>
</html>
【例7.6】使用Java语言实现一个简单的Web服务器。该Web服务器的服务端口为1000,用户使用浏览器和该服务器交互。在浏览器地址栏中输入“http://localhost:1000/”,服务器接收到该命令请求后,在控制台上打印该HTTP请求信息内容,并向客户端返回一个只有文本“SimpleWebServer”的页面。源程序文件SimpleWebServer.java如下:
packagecom.test.java;
importjava.io.*;
import.*;
import.ssl.*;
publicclassSimpleWebServer
{
publicstaticvoidprocess()throwsIOException
{
ServerSocketServSock=newServerSocket(1000);
//在1000端口上监听客户端请求
while(true)
{
try
{
Socketsock=ServSock.accept(); OutputStreamout=sock.getOutputStream();
//关联输出字节流,用来写数据
BufferedReaderin=new
BufferedReader(newInputStreamReader(sock.getInputStream()));
//关联输入字节流,将字节流转化为字符流,封装为
带缓冲的字符流,一次读
//取一个文本行数据
//读取请求并显示到页面上
Stringline=null;
while(((line=in.readLine())!=null)&&
(!("".equals(line)))) {
System.out.println(line);
}
System.out.println(“”);
//构造响应消息
StringBufferbuffer=newStringBuffer();
buffer.append(“<head><title>SimpleWebServer
</title></head>\n");
buffer.append("<body>\n");
buffer.append("SimpleWebServer\n"); buffer.append(“</body>\n”);
buffer.append(“</html>\n”);
//求取发送内容的长度
Stringstr=buffer.toString();
byte[]data=str.getBytes();
out.write(“HTTP/1.0200OK\n”.getBytes());
out.write(newString(“Content-Length:”+
data.length+"\n").getBytes());
out.write("Content-Type:text/html\n".getBytes()); out.write(data);
out.flush();
//关闭流和端口
out.close();
in.close();
sock.close();
}
catch(Exceptione)
{
e.printStackTrace(); }
}
}
publicstaticvoidmain(String[]args)throwsIOException
{
process();
}
}
执行时控制台打印出的HTTP请求消息内容如下:
GET/HTTP/1.1
Accept:image/gif,image/jpeg,image/pjpeg,image/pjpeg,
application/vnd.ms-excel,application/vnd.ms-powerpoint,
application/msword,application/x-silverlight,application/x-shockwave-flash,*/*
Accept-Language:zh-cn
User-Agent:Mozilla/4.0(compatible;MSIE8.0;WindowsNT5.1;Trident/4.0)
UA-CPU:x86
Accept-Encoding:gzip,deflate
Host:localhost:1000
Connection:Keep-Alive
GET/favicon.icoHTTP/1.1
Accept:*/*
UA-CPU:x86
Accept-Encoding:gzip,deflate
User-Agent:Mozilla/4.0(compatible;MSIE8.0;WindowsNT5.1;Trident/4.0)
Host:localhost:1000
Connection:Keep-Alive
客户端浏览器的结果如图7.17所示。图7.17客户端浏览器页面请使用网络协议分析器Ethereal(已更名为Wireshark,可到网站下载)安装并捕获分组、分析分组以及HTTP协议内容和工作过程。Wireshark工作台主界面如图7.18所示。图7.18Wireshark工作台主界面
7.5Servlet的提出和工作原理
在Web层次模型中,Web服务器端程序的核心功能是业务逻辑数据的处理。当服务器接收到客户端通过网络传输的HTTP、HTTPS请求数据后,需要按照设计的业务数据处理流程进行处理,处理完成之后构造响应消息返回给客户端。客户端是Web系统的输入、输出界面。业务逻辑数据的处理可以通过定义Servlet来完成。
Servlet对业务流程数据按业务流程进行处理,其中业务数据可能来自请求,也可能来自公共存储区对象,处理结果数据可以更新公共存储区对象,也可以构造响应消息返回给客户端。最常见的输出是通过响应消息输出到客户端,输出数据利用输出流来缓存,数据主要是文本。
开发Servlet时要重点把握数据的来源(输入)、处理、输出,可以简单总结为“分析请求消息”、“处理消息”、“构造响应消息”三个步骤。一般将每个步骤的执行代码分别放在不同的方法体内,这样Servlet运行环境在调用Servlet方法时可以根据不同的步骤调用不同的方法。
Servlet是用Java语言编写的特殊的类,该类对象的创建(为对象分配内存)、初始化和方法调用由服务器软件负责,开发人员只需要搞清楚调用时刻和调用参数,再通过直接继承javax.servlet.http.HttpServlet,覆盖Servlet的部分方法(函数)就可以快速定义和实现一个Servlet。这些方法有doGet()、doPost()等,用于处理HTTP请求。
Servlet对象和Servletr容器的通信主要通过参数传递进行,由Servlet容器来判断Servlet对象的调用时刻和调用方法。Servlet对象的生命过程如图7.19所示。Servlet容器负责管理Servlet对象,它装入(创建)对象、初始化Servlet(调用init()方法)、调度Servlet的方法、销毁Servlet对象(释放内存)。图7.19Servlet对象的生命过程
Servlet容器响应Web客户请求的工作过程如下:
(1) Web客户向Web服务器发出HTTP请求。
(2) Web服务器解析该请求。
(3) Servlet容器创建一个封装HTTP请求消息的HttpRequest对象。
(4)Servlet容器创建一个HttpResponse对象,该对象是HTTP响应消息的封装。HttpRequest对象和HttpResponse对象是容器调用Servlet的service方法传入的参数对象引用(Reference)。Servlet处理HttpRequest对象的结果写入HttpResponse对象,Servlet容器从HttpResponse对象数据获取Servlet的处理结果。
(5)Servlet容器调用HttpServlet的service方法,把HttpRequest和HttpReponse对象作为service方法的参数传递给HttpServlet对象。
(6) HttpServlet调用HttpRequest的相关方法,获取HTTP请求信息。
(7) HttpServlet调用HttpResponse的相关方法,构造生成响应消息数据。
(8) Web服务器将HttpServlet的响应结果传给Web客户。
关于Servlet的功能和工作过程可以参考Servlet规范的制定者Sun公司在网站上发表的文章,地址为/pub/a/onjava/2003/05/14/java_webserver.html。7.6Servlet的设计和实现
Servlet的设计主要是继承javax.servlet.http.HttpServlet类,覆盖doGet()、doPost()方法。在方法体中分析请求消息javax.servlet.http.HttpServletrequest对象request,处理消息,最后构造响应消息javax.servlet.http.HttpServletResponse对象response,将结果数据输出到界面。
在分析request对象中的数据时,常使用的方法是:
java.lang.StringgetParameter(java.lang.String
name)
java.util.EnumerationgetParameterNames()
java.lang.String[]getParameterValues(java.lang.String
name)在构造响应消息数据时,通常需要建立PrintWriter类型对象的输出流,向该流中写数据。在每个Servlet文件编辑完成之后,还需要在Servlet注册管理文件web.xml中注册每个Servlet,这样Web应用程序才能寻找到Servlet的代码,进而调用其方法。
Servlet由容器调用执行,容器根据web.xml配置文件来定位和装载Servlet的代码,进而生成该类的实例。
Servlet的实现步骤是:
(1)通过编辑web.xml注册Servlet。主要修改web.xml中的<servlet>…</servlet>和<servlet-mapping>…</servlet-mapping>这两个数据项中的内容。
<servlet>数据项中有很多数据子项,一般最常用的是<servlet-name>和<servlet-class>数据项,这两个数据项用来定义Servlet的名称和Servlet的类代码。<servlet-mapping>中的两个数据子项为<servlet-name>和<url-pattern>,其中<servlet-name>数据项对应<servlet><servlet-name>中的数据项,<url-pattern>为该Servlet被访问时的URL定义。
当使用Eclipse+Lomboz插件开发的时候,以上4个数据项的内容会由模板自动生成,开发人员可以查看、编辑修改web.xml文件的内容。
(2)客户端去请求该Servlet,触发容器调用Servlet。7.7ServletAPI常用接口和类
JavaServletAPI是一组接口和类,以包的形式提供给开发人员使用。JavaServletAPI提供了两个包:
(1) javax.servlet包。该包实现了未定义通信协议的Servlet接口和类。
(2) javax.servlet.http包。该包实现了使用HTTP协议通信的Servlet接口和类。
API的详细说明文档如表7.2所示。读者可以到Sun公司网站查阅和下载,网址为/products/servlet/2.5/docs/servlet-2_5-mr2/index.html。
ServletAPI接口和类一览表如表7.3所示。最常用的接口是Servlet、ServletConfig、ServletRequest、ServletResponse、HttpServletRequest、HttpServletResponse、HttpSession,其中HttpServletRequest继承ServletRequest,HttpServletResponse继承ServletResponse。最常用的类是GenericServlet、HttpServlet以及异常类ServletException、UnavailableException。这些常用接口和类提供了创建Servlet、创建请求消息和响应消息对象的类型。
Servlet接口的常用方法如下:
voiddestroy()
ServletConfiggetServletConfig()
java.lang.StringgetServletInfo()
voidinit(ServletConfigconfig)
voidservice(ServletRequsetreq,ServletResponseres)
关于方法的说明请参考相关文档。
GenericServlet类是一个抽象类,它实现了Servlet接口,具有Servlet的所有方法。该类的声明为:
publicabstractclassGenericServlet
extendsjava.lang.Object
implementsServlet,ServletConfig,java.io.Serializable
该类最重要的抽象方法是:
abstractvoidservice(ServletRequestreq,ServletResponseres)
继承该类,必须实现该抽象方法。该抽象方法的两个最重要的参数是req和res,实参由Servlet容器传入,该方法负责修改实参对象数据,通过res参数将处理结果传回Servlet容器。
GenericServlet类的常用方法如下:
java.lang.String getInitParameter(java.lang.String
name)
java.util.Enumeration getInitParameterNames()
ServletConfig getServletConfig()
ServletContext getServletContext()
java.lang.String getServletInfo()
java.lang.String getServletName()
void init()
void init(ServletConfig
config)
abstract
void service(ServletRequest
req,ServletResponse
res)
HttpServlet类是设计和开发Servlet的人员直接继承的最常用的顶层Servlet,该类继承了GenericServlet类。如果Servlet类继承了HttpServlet类,通常不直接实现service方法,因为该类已经实现了service方法。在service方法中,根据不同的请求方式调用不同的方法,开发人员主要实现这些不同的请求处理方法。
请求处理方法和请求类型的对应关系如表7.5所示。7.8Servlet应用实例
【例7.7】实现一个向客户端输出简单文本的Servlet。
分析:该Servlet不需要分析请求消息数据,只需要构造一个响应消息数据,向响应消息输出流写入数据,即可向客户端输出简单文本。
操作:先建立代码框架,然后实现方法,并在web.xml中注册。
在Eclipse环境中的操作步骤如下:
(1)在前面建立的工程中添加Servlet,在工程视图栏(ProjectExplorer)的目录中选定存放Servlet源代码的目录(JavaResources:src),如图7.20所示。图7.20选定存放Servlet源代码目录的界面
(2)在该目录下添加一个Servlet。选中JavaResources:src目录,单击鼠标右键,弹出【New】菜单,在【New】菜单下选择【Other…】,如图7.21所示。图7.21选择添加Servlet
(3)在弹出的如图7.22所示界面中添加Web项内容,选择【Web】下的【Servlet】。图7.22选择Web的子项Servlet
(4)定制Servlet的名称(Classname),定义或者选择包名(在Javapackage项后的文本框中填写),如图7.23所示。填好后单击【Next】按钮。图7.23定制Servlet名称和存储目录
(5)在出现的如图7.24所示界面中,定制web.xml中关于Servlet的配置项。如果不定义初始参数,可以选择默认,直接单击【Next】按钮。图7.24定制web.xml中关于该Servlet的配置项
(6)定制Servlet的修饰符及方法。一般选择不作任何改动。单击【Finish】按钮,完成Servlet源代码模板的创建,如图7.25所示。图7.25定制Servlet的方法和修饰符
(7)单击【Finish】按钮后,生成Servlet源代码框架模板和web.xml配置文件。在此文件中添加处理代码,最后的结果如下:
① HelloWorld.java文件:
packageservlet.web;
importjava.io.IOException;
importjava.io.PrintWriter;//输出字符流,用来写文本
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServletRequest;
//请求消息信息类,请求消息对象的类型,请求消息被作为doXXX的参数之一
importjavax.servlet.http.HttpServletResponse;
//响应消息信息类,响应消息对象的类型,响应消息被作为doXXX的参数之一
publicclassHelloWorldextendsjavax.servlet.http.HttpServletimplementsjavax.servlet.Servlet{
publicHelloWorld(){
super();
}
//一般只修改此方法即可,此方法的功能是分析请求消息数据,构造响应消息数据。
//对该题不需要分析请求消息数据,只需要构造响应消息 protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
//该题只构造响应消息
response.setContentType("text/html;charset=gb2312");
//用来设置响应消息的MIME类型:此处为text/html,客户端将该响应消息的
//正文(Body)数据按text/html格式解析。字符集编码方式为gb2312
PrintWriterout=response.getWriter();
//创建字符输出流对象,该字符输出流可以把任意类型的数据按字符的方式写入
//这样响应消息正文(Body)中的数据都按文本的方式对待。注意此处的out对象为
//PrintWriter类型的对象的引用名,可以用其他名称代替,不是System.out中
//的System数据成员out,不要混淆。程序员只需要向响应消息提供的这个流对象
//中写数据即可,最后流中的数据是被服务器以响应消息的形式发往客户端浏览器,
//最终被浏览器软件解析并显示出来的
//以下用来构造响应消息正文,即向流对象中写入一个简单文本。这部分需要熟悉
//html各标签的含义及页面的写法
out.println(“<html>”);
out.println(“<head><title>HelloWorld</title></head>”);
out.println(“<bodybgcolor=\”FFFFFF\“>”);
out.println(“<center><H1>HelloWorld!
</H1></center>");
out.println("</body>"); out.println(“</html>”);
}
protectedvoiddoPost(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,
IOException{
}
}
② web.xml文件:
<?xmlversion=“1.0”encoding=“UTF-8”?>
<web-appid=“WebApp_ID”version=“2.4”
xmlns="/xml/ns/j2ee"
xmlns:xsi=/2001/XMLSchema-instance
xsi:schemaLocation=“/xml/ns/j2ee
/xml/ns/j2ee/web-app_2_4.xsd”>
<display-name>WebExample</display-name>
<servlet>
<description></description>
<display-name>HelloWorld</display-name>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>servlet.web.HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
该web.xml文件从<servlet>开始到</servlet-mapping>部分属于Servlet配置项内容。
(8)运行该Servlet。在Porject视图栏中选中该Servlet,单击鼠标右键,选择在服务器上运行,如图7.26所示。图7.26运行Servlet
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年陪诊师考试高效学习路径与试题及答案
- 2024年监理工程师考试复习试题及答案
- 投资咨询工程师目标设定试题及答案
- 2024计算机二级考试攻关试题及答案
- 宠物殡葬中涉及的生物学常识试题及答案
- 黑龙江生态工程职业学院《法医学基础实验》2023-2024学年第二学期期末试卷
- 黑龙江省双鸭山市名校2025届高中毕业班阶段性测试(四)化学试题含解析
- 黑龙江省大庆十中2024-2025学年高三适应性联合考试数学试题试卷含解析
- 黑龙江省孙吴县第一中学2025年高三下学期质量监控(二模)生物试题试卷含解析
- 黑龙江省绥化市青冈县2024-2025学年高三第二次质量调研(二模)化学试题含解析
- (2025)新《公司法》知识竞赛题库(附含参考答案)
- 大象版小学科学四年级下册全册教案(教学设计)及反思
- DB37T5299-2024建设工程文明施工标准
- iso28000-2022供应链安全管理手册程序文件表单一整套
- 成都市绿色建筑施工图设计与审查技术要点及附表(2024版)
- 《预应力装配式混凝土框架结构技术标准》JGJT502-2024-知识培训
- T-CSUS 69-2024 智慧水务技术标准
- DBJ-T15-224-2021 广东省城市轨道交通公共卫生管理规范
- 妇联选举主持词
- 07K103-2 防排烟系统设备及附件选用及安装
- 新版高中物理必做实验目录及器材-(电子版)
评论
0/150
提交评论