Edzy_Java

  BlogJava :: 首页 ::  ::  ::  :: 管理 ::
  58 随笔 :: 12 文章 :: 11 评论 :: 0 Trackbacks

1 Java Servlet简介

  Java Servlet是J S P技术的基础,而且大型的We b应用程序的开发需要Java Servlet和J S P配合才能完成,这里简单介绍S e r v l e t的相关知识,S e r v l e t的开发将在其它章节讲述。

  S e r v l e t这个名称大概源于A p p l e t,现在国内的翻译方式很多,本书为了避免误会,决定直接采用S e r v l e t而不做任何翻译,读者如果愿意,可以称之为“小服务程序”。S e r v l e t其实和传统的C G I程序和I S A P I、N S A P I等We b程序开发工具的作用是相同的,在使用Java Servlet以后,用户不必再使用效率低下的C G I方式,也不必使用只能在某个固定We b服务器平台运行的A P I方式来动态生成We b页面。许多We b服务器都支持S e r v l e t,即使不直接支持S e r v l e t的We b服务器也可以通过附加的应用服务器和模块来支持S e r v l e t。得益于J a v a的跨平台的特性, S e r v l e t也是平台无关的,实际上,只要符合Java Servlet规范, S e r v l e t是完全平台无关且是We b服务器无关的。由于Java Servlet内部是以线程方式提供服务,不必对于每个请求都启动一个进程,并且利用多线程机制可以同时为多个请求服务,因此Java Servlet效率非常高。

  但Java Servlet也不是没有缺点,和传统的C G I、I S A P I、N S A P I方式相同,Java Servlet是利用输出H T M L语句来实现动态网页的,如果用Java Servlet来开发整个网站,动态部分和静态页面的整合过程简直就是一场恶梦。这就是为什么S U N还要推出Java Server Pages的原因。

1.1 JSPServlet

  Servlet (服务器小程序)是一个与协议无关的跨平台的服务器组件。如同APPlet(小程序)被集成到web测览器中一样,它被集成到服务器中,可以实现网络远程动态加载。 最初,主要是把Servlet集成到支持HTTP协议的Web服务器上,但是随着它的不断改进 现在巳经集成到实现Java服务器API的任何服务上了。同时,Servlet也是实现智能代理的第一步。JSP主要关注于HTML(或者XML)与Java代码的结合,以及加入其中的JSP 标记。如果一个支持JSP的服务器遇到一个JSP页面,它首先查看该页面是否被编译成为一个Servlet。由此可见,JSP首先被编译成Servlet,即被转变为纯Java 然后被装载到服务器执行。当然,这一过程根据不同的JSP引擎而略有不同。下面是Servlet的一些应用范围:

(1)用于处理HTML表单。通过HTTP产生提交表本数据,包括买卖订单或信用卡数据。Servlet可以成为订单处理系统的一部分,和产品存货数据库一道工作,也可以用 在在线支付系统上。

(2)允许人们之间的合作。一个Servlet能并发处理多个请求,人们可以使用在诸如在线会议这样的同步请求支持系统。

(3)转送请求。Servlet可以转送请求给其他的服务器和Servlet。这就允许在镜像同样内容的几个服务器之间平衡负载。按照任务类型或组织范围,可以允许被用来在几个服务器中划分逻辑上的服务器。

(4)Servlet编写者们可以定义彼此之间共同工作的激活代理。每个代理者是一个Servlet,而且代理者能够在他们之间传送数据。

1.2 Java Servlet的优点

  Java Servlets比传统的CGI或其他CGI类似替代技术来说,只有工作效率更管使用更方便、功能更强大、更小巧也更便宜等优点。下面将具体介绍这些优点。

1.效率高

  传统CGI对每一个HTTP请求都要产生一个新的进程。即使某个CGI程序是一个执行非常快的操作,打开进程的时间也占用了大部分执行时间。而对Java Servlets来说,在 Java虚拟机上每一个请求由一个""Java线程(thread)响应,而不是一个"大"操作系统进程。类似地,传统CGI如果对同一个CGI程序有N个同时请求,这个CGI程序的代码将被导人内存N次。Java Servlets产生N个线程 但只有一个Java Servlets Class的Copy。同时Java Servlets比CGI有更多的优化选择,像预先计算、打开数据库连接等。

2.使用方便

  Java Servlets具有自动粘贴和解码HTML表单数据、读和设置HTTP头、处理 Cookies、 跟踪Session等其他大量功能。

3.功能强大

 Java Servlets可以很容易地实现对CGI来说不可能或很困难的事务。如Java Servlets 能直接和服务器进行通信,而CGI不能。

4.共享数据

  Java Servets之间能共享数据很容易实现数据库连接池。它能方便地实现管理Request 请求,简化Session和获取前一页面信息的操作。而在CGI之间通信则很差。由于每个CGI 程序的调用都开始一个新的进程;调用间通信通常要通过文件进行,因而相当缓慢。同一台服务器上的不同CGI程序之间的通信也相当麻烦。

5.调用时间短

  CGI程序是作为单独过程运行的,通常调用时间较长。这个进程在每次调用的时候都要发生,而在使用解释器的时候调用时间会更长。与此相比,内存中的Servlet可以非常迅速地加载。

6.安全

  有些CGI版本具有明显的安全弱点。即使是使用最新的标准利PERL等语言,系统也没有基本安全框架,要靠一组事实上的规则。而Java定义有完整的安全机制,包括SSL、CA认证和安全政策等规范。

7.小巧

  Java Servlets使用Java编写,遵循标准API。它能直接或借助插件在几乎所有Web 服务器上运行。

8. 价格低

  现在有很多都是免费软件或者共享软件。

1.3 Servlet的结构

  在具体掌握Servlet之前,需要对Java语言有所了解。下面的介绍需要用户了解Java基础,在Servlet API中最重要的是Servlet interface。所有的Servlet都执行这个interface(接口)其执行方式有两种:直接的执行方式或者通过扩展类(Class)的执行方式,如HttpServlet。这个Servlet interface提供安排Servlet与客户端联系的方法。Servlet编写者可以在开发Servlet程序时提供更多一些这样的方法。

  当一个servlet接收来自客户端的调用请求时,它接收两个对象类,一个是 ServletRequest,另外一个是ServletResPonse。ServletRequest类概括从客户端到服务器之间的联系,而ServletResPonse类概括从Servlet返回客户端的联系。

  ServletRequest接口可以获取到这样一些信息,如由客户端传送的阐述名称、客户端正在使用的协议、产生请求并且接收请求的服务器远端主机名等。它也提供获取数据流的Servlet和ServletInputstream.这些数据是客户端引用中使用HTTP POST和PUT方法递交的。一个 ServletRequest的子类可以让Servlet获取更多的协议特性数据,例如 HttpservletRequest包含获取HTTP-specific头部信息的方法。

  ServletResponse接口给出相应客户端的Servlet方法。它允许Servlet设置内容长度和回应的MIME(MultiPurpose Internet Mail Extensions)类型,并已提供输出流 Servletoutputstream 通过编写者可以发回相应数据。ServletResponse子类可以给出更多protocol-specific容量的信息例如HttpServletResponse包含允许Servlet操作HTTP-specific头部信息的方法。

  上面有关类和接口的描述构成了一个基本的Servlet框架。HTTP Servlet有一些附加的可以提供 Servlet-tracking capabilities的方法。Servlet编写者可以用这些API在有他人操作时维护Servlet与客户端之间的状态。Servlet都是由HttpServlet继承下来的,其基本结构如下面的代码所示:

import java.io.*;
i
mport javax.servlet.*;
import javax.servlet.http.*;
public class SomeServlet extends HttpServlet
{
   public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException
  {//"request"可以读取输入的值比(e.g.cookies)
   //
和表单提交的数据
   //"response"返回输出的内容
      PrintWrite out=response.getwriter();
   //
"Out"向例览器写内容。
  }
}

1.4 Java Servlet接口

 Servlet从javax包的httpservlet类扩展,在Httpservlet中加入了一些附加的方法,这些方法可以被协助处理HTTP基本请求的Httpservlet类中的方法Service自动调用。这些方法有:

1.doGet用来处理HTTP的Get请求

  这个Get请求仅仅允许客户从HTTP Server上“取得”(get)资源。重载此方法的用户自动允许支持方法Head。这个Get请求被认为是安全的,没有任何的副面影响,对用户来说是很可靠的,比如大多数的正规查询都没有副作用。如果想要改变存储数据的请求必须用其他的HTTP方法。这要求方法也必须是安全的操作。方法doGet的默认执行将返回一个 HTTP的BAD_REQUEST错误。

  方法doGet的格式:
protected void doGet(HttpServletResqucst request, HttpServletResPonse response)
throws ServletException, IOException;

2.doPost用来处理HTTP的Post请求

这个Post请求包含了在必须通过此Servlet执行的请求中的数据。由于它不能立即取得资源 故对于那些涉及到安全性的用户来说,通过Post请求操作会有一些副作用。

  方法doPost的默认执行将返回一个HTTP的BAD_REQUEST错误。当编写Servlet时,为了支持Post操作必须在于类HttpServlet中执行此方法。

此方法的格式:
Protected void doPost(HttpServletRequest requst,
   HttpServletResPonse response)
 throws ServletException,IOException;

3 doPut用来处理HTTP的Put请求

  此Put请求模拟通过FTP发送一个文件。对于那些涉及到安全性的用户来说,通过Put请求操作也会有一些副作用。

  此方法的格式:
Protected void doPut(HttpServletResquest requcst,
  HttpServletResPonse response)
 throws ServletExcePtion,IOException;

4.doDelete用来处理HTTP的Delete请求

  此方法允许客户端请求一个从Server移出的URL。对于那些涉及到安全性的用户来说,通过Delete请求操作会有一些副作用。

  方法 doDelete的默认执行将返回一个HTTP的.BAD_REQUEST错误。当编写Servlet时,为支持 Delete请求,必须在子类 HttpServlet中执行此方法。

  此方法的格式:
protected void doDelete(HttpServletResquest request,
 HttpServletResPonse response)
  throws ServletException,IOException;

5. doHead用来处理 HTTP的 Head请求

  默认地,它会在无条件的Get请求执行时期中运行,但不返回任何数据到客户端,只返回包含内容信息的长度的Header。由于用到Get请求,此方法应该是很安全的(没有副作用),也是可重复使用的。此方法的默认执行自动地处理了HTTP的Head请求,并且不需要通过一个子类执行。

  此方法的格式:
p
rotected void doHead(HttpServletResquest request,
 HttpServletResPonse response)
  throws ServletException,IOException;

6. doOptions用来处理HTTP的Options请求

  此方法自动决定支持什么HTTP方法。比如说,如果一个Servlet的作者创建HttPServlet 的子类并重载方法doGet,然后方法doOption会返回下面的header:

  Allow:GET,HEAD,TRACE,OPTIONS

  一般不需要重载方法doOptions。

  此方法的格式:
p
rotected void doOption(HttpServletResquest request,
 HttpServletResPonse response)
  throws ServletException,IOException;

7.doTrace用来处理HTTP的Trace请求

  此方法的默认执行产生一个包含所有在Trace请求中的header信息的应答。在开发Servlet时,多数情况下需要重载此方法。

  此方法的格式:
p
rotected void doHead(HttpServletResquest request,
 HttpServletResPonse response)
  throws ServletException,IOException;

  在开发以HTTP为基础的servlet中,方法doGet和方法doPost是最重要的。

1.5 Servlet的生命周期

  Servet程序可以说是在服务器端运行的Applet,甚至比Applet更为简单,因为Servlet 不需要考虑图形界面的应用。与Applet一样 Servlet也有一个生命周期。Servet的生命周期是当服务器装载运行Servlets,接收来自客户端的多个请求并且返回数据给客户端。然后再删除Servlet。

  详细描述如下:

1. 初始化时期

  当一个服务器装载Servlet时,它运行Servlet的init()方法。

public void init(ServletConfig config)throws ServetException
{super.init();//一些初始化的操作,如数据库的连接}

  需要记住的是,一定要在init()程序的最后调用super.imit()init()方法不能被反复调用,一旦调用就重新装载Servlet;也就是说,直到服务器调用Destroy方法卸载Servlet后才能再次被调用。

2. Servet的执行时期

  在服务器装载初始化Servet后,Servlet就能够处理客户端的请求。用Servlet方法可以很容易做到这一点。每个客户端请求有其自己Service方法,这些方法接收客户端请求。并且发回相应的响应。Servlets能同时运行多个Service 这是很重要的。这样,Service 方法可以按一个thread-safe样式编写,如service方法更新servet对象中的一个字段Field,这个字段可以同时存取的。假如某个服务器不能同时并发运行Service方法,也可以用SingleThreadModel interface。这个接口保证不会有两个以上的线程并发运行。在Servlet执行期间其最多的应用是处理客户端的请求,并产生一个网页。其代码如下:

...
PrintWriter out = response.getWriter();//输出的资料
out.println("<html>");
out.println("<head><title>"#Servlet</title></head>");
out.println("<body>:);
out.println("<h1>嗨!! Hello Worid.</h1>");
out.println("</body></html>");
out.close();
...

  执行时期分为数类,分别是对应HTTP方法中的Get、Post时等方法 例如doGet()对应到Get或者doPost()对应到Post方法。其他对应的方法可以参照 Servlet API文件的说明。

3. servet结束时期

  Servlets一直运行到它们被服务器卸载。在init()方法中,可能开启了某些资源,当网页伺服系统要重新启动,或者是要收回资源时就会呼叫destroy()这个方法收回在nit()方法中使用的资源。因此如果需要在结束时关闭一些资源,同样也是重载这个方法。即,也要呼叫 super.destroy(),不过大部分的时候都是不需要的。

public void destroy()
{
//
回收在init()中启用的资源,如关闭数据库的连接等。
}

1.6 使用Servlets的两种模式

  当JSP成为开发动态网站的主要技术时,为何在JSP技术中不强调Servets呢?因为Servlets的应用是没有问题的,它们非常适于服务器端的处理和编程,并且会长期保持现状。从结构上说,可以将JSP看作是Servlet的一个高层的抽象实现。特别是在servlet 2.2 API下。但是用户仍然不能无拘束地使用Servlet.因为它们并不适合每一个人,例如页面设计者可以方便地使用HTML或者XML具开发JSP页面,但SerVet却更适合于后端开发者使用,他们的工具是IDE--一个需要更多编程训练的开发领域。当发布Servlet时,每个开发者必须小心地确定在页面表现和页面逻辑之间没有紧密的关联出现。用户可以使用第三方HTML包装工具,如htmlkona来混合HTML和servlet代码。即使如此,这点灵活性还不足以让用户自由地改变风格本身。例如,如果希望从html改变到dhtml则需要小心测试包装本身,以确保新的格式可以正确使用。在最坏的情况下,包装不可用,那就需要应变马来表现动态内容。所以,需要一种新的解决方案--混合JSP和Servlets的使用。

  早期的JSP标准给出了两种使用JSP的方式。这些方式 都可以归纳为JSP模式1和JSP模式2,主要的差别在于处理大量请求的位置不同。

  在模式1中,JSP页面独自响应请求并将处理结果返回客户。这里仍然有表现和内容的分离,因为所有的数据依靠Beans来处理。尽管模式1可以很好的满足小型应用的需要,但却不能满足大型应用的要求。大量使用模式1,常常会导致页面被嵌人大量的Script或者Java代码。特别是当需要处理的商业逻辑很复杂时 情况会变得严重。也许对于Java 程序员来说,这不算大的问题。但如果开发者是前端界面设计人员——在大型项目中, 这很常见,则代码的开发和维护将出现困难。在任何项目中,这样的模式多少总会导致定义不清的响应和项目管理的困难。

  JSP模式2是一种面向动态内容的实现,结合了Servlet和JSP技术。它利用了两种技术原有的优点,采用JSP来表现页面,采用Servlets来完成大量的处理。这里Servlet扮演一个控制者的角色;并负责响应客户请求。接着,Servlet创建JSP需要的bean和对象,再根据用户的行为,决定将那个JSP页面发送给用户。特别要注意,JSP页面中没有任何商业处理逻辑,它只是简单地检索Servlet先前创建的Beans或者对象,再将动态内容插入预定义的模版。从开发的观点看,这一模式具有更清晰的页面表现,清楚地划分开发者角色,可以充分地利用开发小组中的界面设计人员。事实上 越是复杂的项目,采用模式2的好处就越突出。

  使用模式2,JSP和Servlet可以在功能上最大限度的分开。正确地使用模式2,产生一个中心化的控制Servlet,并且只完成显示的JSP页面。另一方面,模式2的实现很复杂。因此,在简单的应用中,可以考虑使用模式l。

2 创建Servlet程序

  Servlet程序使用的语言为Java语言,保存时需要以“*.java”为扩展名。在运行Servlet程序之前,必须对其进行编译。以下将详细介绍如何使用Java编译器对Servlet进行编译以及如何在JSP程序中加入Servlet程序。

2.1 如何运行Servlet程序

  Java Servlets不像JSP那样,在第一次访问时服务器自动编译,它需要手动编译。在JDK环境下。可以用命令行程序“javac.exe 编译。编译时使用javac命令:

javac<选项><源文件>

 包括下面选项:

-g Generate all debugging info
-g:none Generate no debugging info
-g:{lines,vars,soure} Geaerate only some debugging info
-O Optimize;may hinder debugging or enlarge class files
-nowarn Generate no warnings
-verbose Output messages about what the compiler is doing
-deprecation Output source locations where deprecated APIs are used
-CLASSPATH<path> Specify where to find user class files
-sourcepath<path> Specify where to find input soure files
-bootCLASSPATH<path> Override location of bootstrap class files
-extdirs Override location of installed extension
-d<directory> Specify where to place generated c1ass files
-enceoding<encoding> Specify character encoding used by source files
-target Generate class files for specific VM version

  执行Servlet的必备条件是一个Web Server与Servlet的执行引擎。而JSWDK既是Servlet引擎,也包含了一个简单的Web Server。各种Servlet引擎在对应Servlet时,用的都是差不多的做法。通常都是用URL对应的方式,将以/servlet开头的URL交给Servlet 引擎处理。例如,当网页的Server与Servlet引擎启动后,网页Server将所有向它请求的URL(例如http://locwhost:8080/servlet/helloworidservlet)交给Servlet引擎处理,Servlet引擎就会向指定给它的servtet目录寻找servlet的类别码,然后将其载入。tomcat的Servlet放置目录应该是在以下路径:

C:\jspstudy\tomcat\root\Web-INF\classes

  其中,C:\jspstudy\tomcat\是各用户安装tomcat的目录,tomcat预设安装的情况来看,上面的目录包含的内容如图3-2所示。凡是Servlet的程序编译成class文件以后,只要放在这个目录下,就可以通过URL来取得它。Tomcat的主要配置文件为server.xml,请详细查看该文件。

  关于Tomcat的配置请参看“Tomcat全攻略”。

2.2 第一个Servlet程序

  为了更清楚地理解Servlets是如何工作的,下面来详细地看一个Servlet示例。程序 Hellow.java简单向客户端输出信息。

文件hellow.java:

import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class hellow extends HttpServlet {
  public void service(HttpServletRequest request,HttpServletResponse    response) throws IOException,ServletException
 {
  response.setContentType("text/html");
  PrintWriter out = response.getWriter();
  out.println("<html>");
  out.println("<head>");
  String title="Hello World";
  out.println("<title>"+ title +"</title>");
  out.println("</head>");
  out.println("<body bgcolor=\"white\">");
  out.println("<h1>" + title + "/h1>");
  out.println("</body>");
  out.println("</html>");
 }
}
 在命令行键人“javac Hellow.java”。如果没有任何提示的话就是运行通过了。执行后会在同一个目录里生成一个 Hellow.lass文件,为了在浏览器里执行Hellow Servlet需要把该class文件放在Tomcat安装目录\webapps\ROOT\WEB-INF\classes\目录下。在测览器中用httP://localhost:8080/servlet/hellow就可以执行 Hellow servlet了 执行结果见演示或教材图3-3。如果编译不通过,请注意Java程序的大小写问题。如果不是语法错误的话,一般就是因为找不到相应的环境变量。如果是这种错误,可以在操作系统的环境变量CLASSPATH 中加人教材36页上半部分的代码。注意,可以把这些文件集中放到一个文件夹下,以免太分散。

3 Servlet处理表单提交

3.1 表单的基本概念

  HTML 表单的作用在于客户和服务器的交互。用户填写完表单以后按提交(英文为submit), 中文通常为“确定”或“提交”按钮,表单中的信息将被发送到服务器端进行处理。服务器将处理过的用户提供信息的HTML 文件返回到客户端进行显示。

3.1.1 什么是HTML 表单

  在Web 上获取用户的信息,大多数情况下都是通过表单来实现的。比如说输入消费者的姓名、地址,或者输入一个词来使用搜索引擎查找,或者从来访者处收集数据提供参考等等。

1. HTML 表单的数据流

  来访者通过表单向JPS 引擎输入了数据,并保存在request 对象中,那么接下来怎么办?图3-3 展示了数据流是如何在服务器和客户之间传递的(至少在SUN 的JSPrdference implementation 是这么做的,别的JPS 引擎工作起来可能会有一点点的不同,其实大同小异都差不多)。

  图3-2,JSP 引擎把存放在request对象中的数据流发到JSP 页面指定的服务器端的组件(JavaBeans 组件,servlet 或者enterprisebean), 组件收到这些个数据以后,有可能再存放这些数据到数据库或者在其他的地方存放起来,同时,返回一个response 对象给JSP引擎。JSP 引擎再把response 对象传给JSP 页面,这时的页面包含了定义好的格式和从服务器端得到的数据。这时JSP 引擎和Web 服务器再发送一个整理好的完整的页面给客户。也就是我们在浏览器上看到的结果。客户和服务器间的通信协议可以用HTTP 当然也可以用其他的协议。

  Request 和Response 对象在你制作的JSP 源代码中起作用

3.1.2 HTML 表单的运行原理

  客户端的浏览器从服务器获取HTML 页面时,实际上使用HTTP 协议(Hypertext Transfer Protocol)。 HTTP 协议规定了信息在Internet 上的传输方法特别规定了浏览器与服务器的交互方法。

  在浏览器从服务器获取页面的过程中,浏览器在网站上打开了一个对Internet 服务器的连接并发出请求服务器收到请求后给予回应所以HTTP 协议又被称为请求和响应协议。

  所有的浏览器和服务器间的通信都发生在离散的“请求──响应”对中浏览器必须发出请求才开始通信,服务器角色完全是被动的,它必须在被请求后起作用。

  一个典型请求通常包含许多头。头提供了关于消息内容的附加信息以及请求的来源。其中有些头是标准的,其他的是有关特定浏览器的。

  一个请求还包含信息体。例如,若请求用POST方法而不是GET方法,信息体可以包含HTML 表单的内容。在HTML 表单上单击submit 键时,该表单使用ACTION = “POST”特征,输入表单的内容都被发送到服务器上。该表单的内容就由POST 方法在请求的信息体中发送。

  服务器收到请求时返回HTTP 响应。每个响应都由状态行开始可以包含几个头及可能的信息体。

对页面的请求如下:

GET/index.html HTTP/1.1
HOST:www.kaoyan.net

  上例中使用请求的方法是GET 方法,此方法获取特定的资源。GET 方法用来获

取名为index.html 的网页,其他请求方法包括POST、HEAD、DELETE、TRACE及PUT

方法。例如POST方法用来提交HTML 表单的内容。第二行是头(header)。 Host 头规

定了在网站上index.html 文件的Internet 地址。此例主机是www.kaoyan.net

3.1.3 创建表单的步骤:

创建表单的步骤如下:

建立HTML 表单
使用GET 和POST 方法
写Bean
传数据到Bean
Request 对象
从Bean 中调数据到JSP 页面
如何运行例子

1. 建立HTML 表单

  一个HTML 的窗分为三个部分:<form>标签,输入方法提交按钮发数据到服务器。一般的HTML 页面里是这么写的<form method = get action = someurl>,在其他的页面里的action 属性可能是其他特殊的CGI 程序或者其他能处理数据的程序。那么在JSP 里边是怎么用的呢?如果你想把数据发到Bean 里的话那么你可以省略action 里边的东西了,直接写<jsp:useBean>标签或者其他特定的JSP 文件。了接下来的那些表单和普通的HTML差不多,<input>的方法,然后加一个提交按钮,可能还有一个Reset 按钮,还得给每一个input 表单加一个名字。

这么写:

<input type = “text” name = “username”>

2. 使用GET 和POST 方法

  用GET 和POST 是从服务器上请求数据,POST 是发送数据到服务器。事实上GET方法是把数据参数队列query string 加到一个URL上,值和表单是一一对应的。比如说name John。在队列里,值和表单用一个&符号分开,空格用+号替换,特殊的符号转换成十六进制的代码。因为这一队列在URL 里边这样队列的参数就能看得到,可以被记录下来或更改。通常GET 方法还限制字符的大小。事实上POST 方法可以没有时间限制的传递数据到服务器,用户在浏览器端是看不到这一过程的。所以POST 方法比较适合用于发送一个保密的比如信用卡号或者比较大量的数据到服务器。

3. 写Bean

  如果JSP 程序用到了Bean,你就得按照JavaBeans API 的说明设计你的Bean。 记住下面两个关键部分。

  如果JSP 程序里用<jsp:getProperty>标签,那你就得在Bean 里边写配合的GET方法。

  如果JSP 程序里面用<jsp:setProperty>标签,那你就得在Bean 里边写配合的Set 方法。

  设置参数到Bean 或者从里边取参数将在以后的部分详细介绍。

4. 传数据到Bean

  把HTML 表单的数据传到Bean 里需要两个工作:

  用<jsp:useBean>标签创建或者定位到Bean。
  在Bean 里面用<jsp:serProperty>设置属性值。

  第一步用<jsp:useBean>标签创建或者定位到Bean, 一定要用在<jsp:setProperty>之前,<jsp:useBean>首先按照你指定的名字查找Bean, 如果没找到会给你指定一个。允许在一个JSP 文件中创建一个Bean ,然后在另一个文件中调用,这就给了Bean 一个很广泛的运行空间。

  第二步在Bean 里面用<jsp:setproperty>设置属性值,最简单的方法是把值定义成与表单名相配合。举个例子如果你把表单名定义成username 那么你就在Bean 里定义属性username ,然后用方法getUsername 和setUsername。

  当然也可以定义成不同的名字,只要你不认为麻烦。

5. Request 对象

  用户输入的数据用来存放在Request 对象里,用javax.servlet.HttpServletRequest 来执行,也可以用其他不同的工具来执行,但他们其实都是javax.servlet.HttpServletRequest 的子集。

  也可以直接用scriptlet 来直接访问Request 对象。Scriptlet 将在以后详细的讨论

  现在只需要知道他是用脚本语言写的一段放在<% 和%>之间的代码就足够了。在JPS 1.0中必须,用JavaTM 程序语言作为你的脚本语言。

你经常会用到如下方法处理Request 对象如下表所示

方法

说明

执行结果

getRequest

Javax.servlet.jsp.PageContext

返回当前Request对象

getParameterNames

javax.servlet.ServletRequest

返回当前Request对象参数名

getParameterValues

javax.servlet.ServletRequest

返回当前Request对象参数值

  你将会发现其他方法包括ServletRequest HttpServletRequest 或者其他任何ServletRequest 的子集。

  JSP 引擎经常在scenes 之后使用Request 对象,即使你没有明确地在JSP 文件调用。

6. 从Bean 中调数据到JSP 页面

  一旦用户的数据被传到Bean,你就想重新得到数据,然后在JSP 页面中显示出来。想达到这一步,,你就得用到<jsp:getProperty>标签传Bean 名和属性名。

<jsp:useBean>, <jsp:setProperty>和<jsp:getProperty>标签必须相配。

下面举一个例子,helloworld.jsphelloworld.java配合,即教材中P21实例二:

helloworld.java如下:

package test;
public class helloworld
{
  public String name="Hello World!";
  public String getHi()
  {
     return name;
  }
}

helloworld.jsp如下:

<html>
<head>
<title>JavaBean 试验</title>
</head>
<body>
<jsp:useBean id = "helloBean" scope="session" class="test.helloworld"/>
<%=helloBean.getHi()%>
<hr>
<%
  helloBean.name="Welcom To JSP World!";
  out.print(helloBean.getHi());
%>
</body>
</html>

7. 如何运行例子

  把相应的文件放到相应的路径即可。hellowworld.jsp放到默认的jsp文件存放处。helloworld.java编译成helloworld.class后放到默认的class路径下建立的test目录下。输入“http://127.0.0.1:8080/jspexa/jsp/helloworld.jsp”即可运行此例。

3.2html表单

3.2.1先例

  先看一个表单的HTML代码:

<html>

<head>
<meta http-equiv="Content-Language" content="zh-cn">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>输入域的各种类型</title>
</head>

<body>

<p align="center"><b><font color="#FF0000" size="5">输入域的各种类型</font></b></p>
<form method="POST" name="form1" action="test.jsp">
<table border="1" cellspacing="1" style="border-collapse: collapse" bordercolor="#111111" width="80%" id="AutoNumber1">
<tr>
<td width="26%">1<span lang="en-us">.</span>文本框</td>
<td width="74%"><input type="text" name="T1" size="20"></td>
</tr>
<tr>
<td width="26%">2.口令型文本框</td>
<td width="74%"><input type="password" name="T2" size="20"></td>
</tr>
<tr>
<td width="26%"><span lang="en-us">3.</span>单选钮</td>
<td width="74%"><input type="radio" value="V1" checked name="R1">男&nbsp;&nbsp;&nbsp;
<input type="radio" name="R1" value="V2">女</td>
</tr>
<tr>
<td width="26%">4.检查框<span lang="en-us">(</span>多选框<span lang="en-us">)</span></td>
<td width="74%"><input type="checkbox" name="C1" value="ON">答案<span lang="en-us">A&nbsp;
<input type="checkbox" name="C2" value="ON"></span>答案<span lang="en-us">B&nbsp;
<input type="checkbox" name="C3" value="ON"></span>答案<span lang="en-us">C&nbsp;
<input type="checkbox" name="C4" value="ON"></span>答案<span lang="en-us">D</span></td>
</tr>
<tr>
<td width="26%">5.图像</td>
<td width="74%">
<input type=image name=img1 src="images/wvwelcom.gif" width="76" height="38"></td>
</tr>
<tr>
<td width="26%">6.下拉列表框</td>
<td width="74%"><select size="1" name="D1">
<option>优秀</option>
<option>良好</option>
<option selected>中等</option>
<option>及格</option>
<option>不及格</option>
</select></td>
</tr>
<tr>
<td width="26%">提交按钮</td>
<td width="74%"><input type="submit" value="提交" name="B1"></td>
</tr>
<tr>
<td width="26%">重置按钮</td>
<td width="74%"><input type="reset" value="重置" name="B2"></td>
</tr>
<tr>
<td width="26%">其它按钮</td>
<td width="74%"><input type="button" value="按钮" name="B3"></td>
</tr>
<tr>
<td width="26%">文本区</td>
<td width="74%"><textarea rows="3" name="S1" cols="56"></textarea></td>
</tr>
</table>

 </form>

</body>

</html>

执行结果请按此

3.2.2 表单的标记与处理

表单的标记有以下五种类型

  <form></form>

  <input>

  <select></select>

  <option>

  <textarea></testaea>

1 Form 标记及其用法

<form>标记包含描述文件结构的标记同时还包括一些输入<input> 标记

<form>标记中的参数包括

  ACTION 用于设定表单的处理方式通常指明一个处理函数的URL 地址

  METHOD 用于设定表单的资料传输方式如POST 或GET 方式

  ENCTYPE 用于设定以何种编码方式来传送表单的数据

Form 标记的用法

<html>
<head>
</head>
<body>
<form method="POST" action=" ">
<table border="0" width="500" cellspacing="0" cellpadding="0"
align="center">
<tr>
<td width="50%">
<p align="right">用户名</td>
<td width="50%">
<input type="text" name="T1" size="20">
</td>
</tr>
</table>
</form>
</body>
</html>

2 Input 标记及其用法

使用<input>标记可以实现在表单上输入信息,每个输入域可分配一个值给予特定名

称及变量。Input 标记的格式如下:

<input name="myname" type="mytype">

其中

  Type 的默认值是TEXT 也可选择PASSWORD、CHECKBOX、RADIO、IMAGE、HIDDEN SUBMIT 等参数值。

  Name 用于指定与input 标记相应表单域的名称

  可选参数

MAXLENGTH 用于限制可以在文本输入域输入的字符数。如果MAXLENGTH 参数值比SIZE 参数值大那么域就可以正确翻动。字符的预设数字并没有什么限制。

SIZE 指明按照其类型分配给此输入域的显示空间大小,预设值取决于用户代理。

VALUE 域的初始值

3. Input Type=Password 的用法

  当Input 标记带有Type=Password 时,与Text 一样是一个文本域,所不同的是在输入时它的值是隐藏的,在浏览器输入域中将以*号隐藏显示。

4. Input Type=checkBox 的用法

当Input 标记带有Type=CheckBox 时,可以多次选择复选钮。使用Type=CheckBox的参数要求如下:

  NAME 用于指定与此标记或一组标记相应的表单域的符号名称

  VALUE 用于表示由此标记提供的域值部分

  可选参数CHECKED 用于指示初始状态为ON

5. Input Type=Radio 的用法

  当Input 标记带有Type=Radio 时,只能选择一个单选钮,使用Type=Radio 的参数要求与CheckBox 一样Name 和Value 参数是必须定义的。

6. Input Type=Image 的用法

  当Input 标记带有Type=Image 时,其功能可以指明显示图片的来源,并可以输入两个单域,即从图片中抽取像素的X 和Y 坐标,域名称是附加X 和Y 的域名称。TYPE=IMAGE 由SUBMIT 处理。也就是说,当选择一个像素后,表单作为一个整体就被提交。

  使用Type=Image 的参数要求如下:

  Name 用于指定选择Map 上的点,是必须定义的。

  SRC 用于指定Map 的图片名称,是必须定义的。

  ALIGN 是可选参数。

Image 的HTML 代码如下

<html>

<head></head>

<body>

<p>选择map 上的一个点</p>

<input type=image name=point src="map.gif">

</body>

</html>

7. Input Type=Hidden 的用法

  当Input 标记带Type=Hidden 时,表示Input 标记是一个隐藏域,用户不能与这个域进行交互作用,而是使用Value 参数值来定义。

例如:

<input type=hidden name=context value="12k3j412k3j41k23">

8. Input Type=Submit 的用法

  当Input 标记带有Type=Submit 时,表示由浏览器提交表单的输入内容。通常是一个命令按钮,单击这个命令按钮可以将Form 表单输入的数据传给Web 服务器。

  使用Type=Submit 的参数要求如下:

  NAME 用于指示该标记提供一个由VALUE 参数给定其值的表单域.如果NAME参数不存在则该标记不提供表单域。

  VALUE 用于指示一个输入按键标记。

  Input Type=Submit 有两种用法:

  向内部提交请求的情况

<input type=submit name=recipient value=internal><br>

  向外部提交请求的情况

<input type=submit name=recipient value=world>

9. Input Type=Reset 的用法

  当Input 标记带有Type=Reset 时,表示Input 标记指示浏览器把表单域重置在初始状

态,通常是一个命令按钮,单击这个命令按钮可以实现清除表单,并重置初始状态。

例如

<Input type=Submit> <br>/*提交请求

<Input type=Reset> /*任何时候清除表单

10 Select 标记及其用法

  Select 标记用来定义表单中的下拉式列表框,<select>和</select>总是成对出现的。Select标记把表单域限制到一个值的下拉式列表中。Select 的值通过Option 标记来定义。

Select 标记的格式如下

<select name="myname" Size= 项目数>

其中

  Name 指定表单域的名称

  Size 指定可视项目的数目

11 Option 标记及其用法

  使用Option 标记定义表单中下拉式列表框中的项目,Option 标记只能在Select 标记中使用,Option 标记的格式如下:

<Option Value="值" Selected>菜单选项</Option>

其中

  Value 用来指示该选项被选定时返回的值。

  Selected 指示该选项在初始状态时被选择。

  菜单项是指下拉式列表框中定义的内容。

例如

<option value="中国科学院"selected>"中国科学院"</option>

<option value="软件所" >"软件所"</option>

<option value="计算中心" >"计算中心"</option>

   执行结果中国科学院为初始状态时,被选择下拉式列表框中的菜单选项为中国科学

院、软件所、计算中心。

11 Textarea 标记及其用法

  使用Textarea 标记可以定义一个多行的文本框。当文本行超过定义的区域时,HTML

浏览器允许用户根据需要通过翻屏的方式突破这些限制进行扩展。

Textarea 标记的格式如下

<Textarea Name="名称" Rows=高度 Cols=宽度>

其中

  Name 用来指明表单域的名称

  Rows 用字符数表示显示文本区域的可视高度

  Cols 用字符数表示显示文本区域的可视宽度

Textarea 标记的用法

  归纳起来表单元素的特征如下表所示

表单元
素名称

 

TEXT

一个单行的文本字段,使用SIZE=属性可以指定该字段的可见长度,使用MAXLENGTH属性可以指定该字段中能够包含的字符数的最大数量

PASSWORD

跟TEXT一样,但是所键入的字符不会回显到屏幕上,而是以星号*来代替所键入的字符

CHECKBOX

这个元素代表一个Boolean布尔值,使用CHECKED属性来表示当表单第一次显示时,这个元素应该是预选中的

RADIO

跟复选框CHECKBOX类似,但是用于一组彼此互相排斥的属性。当用户单击组中任何一个单选按钮时,组中所有其他按钮就自动地不被选中。通过给一组按钮相同的NAME属性就可以指定这些按钮为同一组

SUBMIT

用户单击这个按钮时,浏览器就会把表单发送到表单的动作处理程序中,可以通过给VALUE属性赋值来给这个按钮一个submit以外的标签

RESET

用户单击这个按钮时,会把表单中所有元素的取值都重置为默认值。这个按钮也有VALUE属性,可以给按钮更换标签

IMAGE

带有图形图像的发送按钮,当用户单击IMAGE元素时鼠标单击时的x和y坐标就被发送到服务器端程序

HIDDEN

一个隐藏值,对用户来说是不可见的,可以用来指定一个硬编码的表单值

实例

按钮:jspexa/jsp/Button.html , jspexa/jsp/InputButton.html

检查框:jspexa/jsp/InputCheckbox.html

隐藏属性:jspexa/jsp/InputHidden.html

图片属性:jspexa/jsp/InputImage.html

密码属性:jspexa/jsp/InputPassword.html

单选钮属性:jspexa/jsp/InputRadio.html

重置属性:jspexa/jsp/InputReset.html

SUBMIT 属性:jspexa/jsp/InputSubmit.html

TXET 文本属性:jspexa/jsp/InputText.html

LABEL 属性:jspexa/jsp/Label.html

下拉列表框:jspexa/jsp/Select.html

TEXTAREA 文本区:jspexa/jsp/Textarea.html

3.3 3 Servlet与 HTML表单

  HTML 文件中用户对表单的处理是从提供初始状态的域给该文件开始的。对表单的处理可分为表单提交和表单清除两部分。

表单提交

 用户通过表单提交按键或图形输入来提交表单时,则根据方法ACTION URI 及ENCTYPE 来处理表单数据组。

  如果表单中仅有一个单行文本输入域,浏览器应在此域中接受Enter 作为提交表单的请求。

(1) 表单URL编码媒体类型(The Form Url Encoded Media Type)

  表单的默认编码是Application/x-www-form=urlencoded。

(2) 查询表单METHOD=GET

  如果表单处理很简单,所提交的数据很少,并且该数据的安全性并不重要,那么采用GET的方法比较好。它可以使你用最简单的方式向服务器传输数据。但是,URL 编码可能会造成URL 非常长的后果,这就会导致HTTP 服务器的一些执行历史记录出现错误动作。因而一些HTML 表单还是使用METHOD=POST 写成。

(3) 表单提交METHOD=POST

  POST 方式输入的数据长度不受限制,并且你在浏览器的请求地址内也看不到你的输入。

表单清除

  表单清除按钮的Reset 性质表示当用户单击这个按钮时会把表单中所有元素的取值都重置为默认值。这个按钮也有VALUE 属性,可以给按钮更换标签R。eset 的使用方法如下;

<input type="reset" name="Submit2" value="表单清除">

1.URL地址与 Query String

  Get方法所收得的变量其实就是URL的Query String所代表的值,可以有3种方法向服务器传送Query String。

(l)直接在测览器的地址栏输入、其输入格式为:?key1=value1&key2=value2... ...例如:

http://localhost:8080/examples/jsp/snp/snoop.jsp?id=10&nickname=girl

(2)使用 HTML的URL Link方法。在HTML中可以直接在字符串上加入链接功能,即通常所说的超级链接。以下是一个URL Link方式的例子:

<a href="http://localhost:8080/examples/jsp/snp/snoop.jsp?id=10&nickname=dam boo">使用URL Link方式传递GET参数</a>

  如果有可视化的HTML编辑工具(例如 Frontpage)就叮以直接在字符串的属性栏里修改Link参数来设置。

(3)使用Form表单。这种方法已经进行了详细的介绍。下面将举一个简单的例子 form.html来实现 URL Link与 Form表单这两种方法。

文件form.html

<html>
<head>
 <meta http-equiv="Content-Language" content="zh-cn">
 <meta name="GENERATOR" content="Microsoft FrontPage 5.0">
 <meta name="ProgId" content="FrontPage.Editor.Document">
 <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
 <title>请输入您的昵称</title>
</head>
<body>
 <form method="POST" name="form" action="http://localhost:8080/examples/jsp/snoop.jsp">
<p>
 <b><font color="#000080" size="4">请输入您的昵称:</font></b><input  type="text" name="T1" size="20"></p>
 <p><input type="submit" value="提交" name="submit1"><input type="reset" value="重置" name="submit2"></p>
 <p><font size="4" color="#000080"><b>
<a href="http://localhost:8080/examples/jsp/snp/snoop.jsp?id=10&nickname=dam boo">
使用<span lang="en-us">URL Link</span>方式传递<span lang="en-us">GET</span>参数</a></b></font></p>
 </form>
 <p> </p>
</body>
</html>

本例中单击“提交”按钮或是单击下方的超级链接都会向浏览器传送URL

http://localhost:8080/examples/jsp/snp/snoop.jsp?id=10&nickname=dam boo

其功能与直接在测览器地址栏键入相同。

2.Servlet API中与输入输出有关的 API

  在servlet中可以调用Java的API函数,其中最经常使用的就是与输入输出有关的API。以下列举了这些常用的API函数。

ServletRequest

public java.lang.Object getAttribute(java.lang.String name)

public java.util.Enumeraion getAttributeNames()

Public java.lang.String getCharactereucoding()

public int getContentLength()

public java.lang.String getContentType()

public ServletInputStream getInputStream()throws java.io.IOException

public java.lang.String getParameter(java.lang.Stringname)

public java.lang.String[] getParameterValues(java.lang.String name)

public java.lang.String getProtocol()

public java.lang.String getScheme()

public java.lang.String getServerName()

public int getServerPort()

Public java.io.BufferedReader getReader()throws java.io.IOException

Public java.lang.String getRemoteAddr()

Public java.lang.String getRemoteHost()

Public void setAttribute(java.lang.String key.java.lang.Object o)

Public java.lang.String getRealPath(java.lang.String path)

HttPServletRequest

Public java.lang.String getAuthType()

public long getDateHeader(java.lang.String name)

public java.lang.String getHeader(java.lang.String name)

public java.util.Enumeration getHeaderNames()

public int getIntHeader(java.lang.String name)

public java.lang.String getMcthod()

pubIic java.lang.String getPathInfo()

public java.lang.String getPathTranslated()

pubIic java.lang.String getRemoteUser()

public java.lang.String getServletPath()

ServletResponse

pchlic java.lang.String getCharacterEncoding()

public ServletOutPutStream getOutputStream()throws java.io.IOException

public java.io.PrintWriter getWriter()throws java.io.IOException

public void setContentLength(int len)

HttpServletResponse

public void setContentType(java.lang.String type)

public boolean containsHeader(java.lang.String name)

public void sendError(int sc.java.lang.String msg)throws java.io.IOExcrption
    
public void sendError(int sc)throws java.io.IOExcaption
    
public void sendRedirect(java.lang.String location)throws java.io.IO Excaption
    
public void setDateHeader(java.lang.String name,long date)
    
public void setHeader(java.lang.String name.java.lang.String value)
    
public void setIntHeader(java.lang.String name,int value)

public void setStatus(int sc)
    
public void setStatos(int sc.java.lang.String sm)

3.使用Servlet程序处理表单

  以上介绍的是在客户端的HTML表单提交程序。表单提交以后,在服务器端的Servlet程序就可以对上传数据进行处理了。例如填人数据库、查询、网上购物等。以下请看一个读取HTML表单的实例,formgetexmple.html生成一个提交的表单,formGetExmple Servlet程序在服务器端进行读取。

文件formgetexmple.html

<html>
<head>
<title>表单处理实例</title>
</head>
<body>
<form method="get" action="http://localhost:8080/servlet/jspexa/formGetExample"><div align="center">
    <center>
    <table border="2" cellspacing="1" style="border-collapse: collapse" width="59%" id="AutoNumber1" bordercolorlight="#0000FF" bordercolordark="#00FF00">
      <tr>
        <td width="21%">昵称<span lang="en-us">:</span></td>
        <td width="79%"><input type="text" name="nickname" size="20"></td>
      </tr>
      <tr>
        <td width="21%">密码<span lang="en-us">:</span></td>
        <td width="79%"><input type="password" name="password" size="20"></td>
      </tr>
      <tr>
        <td width="21%">确认密码<span lang="en-us">:</span></td>
        <td width="79%"><input type="password" name="password2" size="20"></td>
      </tr>
      <tr>
        <td width="21%">性别<span lang="en-us">:</span></td>
        <td width="79%"><input type="radio" value="1" name="gender">男&nbsp;
        <input type="radio" name="gender" value="2">女
        <input type="radio" name="gender" value="0" checked>保密</td>
      </tr>
      <tr>
        <td width="21%">爱好<span lang="en-us">:</span></td>
        <td width="79%"><input type="checkbox" name="fond" value="1">旅游&nbsp;
        <input type="checkbox" name="fond" value="2">体育&nbsp;
        <input type="checkbox" name="fond" value="3">音乐&nbsp;
        <input type="checkbox" name="fond" value="4">摄影</td>
      </tr>
      <tr>
        <td width="21%">地区<span lang="en-us">:</span></td>
        <td width="79%"><select size="1" name="area">
        <option selected value="1">北京</option>
        <option value="2">上海</option>
        <option value="3">重庆</option>
        <option value="4">天津</option>
        <option value="5">其它</option>
        </select></td>
      </tr>
      <tr>
        <td width="21%">隐藏域<span lang="en-us">:</span></td>
        <td width="79%"><input type="hidden" name="hidden" value="hidden example"></td>
      </tr>
    </table>
    </center>
  </div>
  <p align="center"><input type="submit" value="提交" name="submit"><span lang="en-us">&nbsp;
  </span><input type="reset" value="重置" name="reset"></p>
</form>
</body>
</html>

formgetexample.html的作用是生成一个表单

文件formGetExample.java
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class formGetExample extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException,ServletException
{
response.setContentType("text/html");
PrintWriter out =response.getWriter();
out.println("<html>");
out.println("<body bgcolor=\"white\">");
out.println("<head>");
out.println("<title>Servlet Get Example </title>");
out.println("</head>");
out.println("<body>");
out.println("<h1> Servlet Get Example</h1>");
Enumeration enum = request.getParameterNames();
while(enum.hasMoreElements())
{
String key = (String) enum.nextElement();
String value = request.getParameter(key);
out.println("<p>");
out.println(key+"="+value);
out.println("</p>");
}
out.println("</body>");
out.println("<html>");
out.close();
}
}

  在命令行执行javac formGetExample.java,运行后将生成一个formGetExample.class文件。将 formGetExamle.class拷贝到合适的目录下,用浏览器 打开formgetexamle.html文件,单击确定按钮后就可以运行formGetExmple servlet了。

  使用Get请求读取表单数据,调用的方法是doGet()

public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException, ServletExcepion

  然后说明生成的文档是text还是html类型,并定义out对象。

response.setContentType("text/html");
PrintWriter out = response.getWriter();

  读取表单中某个域"key"的值,使用的是 HttpSerletResponse中的getParameter方法 , public java.lang.String getParameter(java.lang.Stringname) 。也就是说,如果已知某个域的name属性是“nickname”则可以直接使用getParamter(nickname)来返回该域的值。在不知道域的name属性情况下,可以使用HttpServletResponse中的getParameterName方法:public java.util.Enumration getParameterNams()。该方法将返回一个 Enumeration型的对象,例如formGetExmple程序中的enum对象:

Enumration enum = request.getParameterName();
while(enum.hasMoreElements())
{
String key = (String) enum.nextElement);
String value = request.getParameter(key);
out.ptintln("<P>");
out.println(key+"="+value);
out.println("</P>");
}

  这样就可以列出所有的Key-Value了。

3.3 Servlet处理复杂Form元件

  在formGetExample.java中,一些简单的元件例如文本框、密码框、隐藏域等,这些元件的值可以直接通过赋值语句“String value=request.getParameter(key);”获得。但是在单选框(Radio)、复选框(Checkbox)、列表框等复杂元件中,就需要进一步进行编程,来判断客户的输人内容。以下将介绍几个处理复杂Form元件的例子。

1. 单选框(Radio

  在formGetExmple例子中,性别一栏的代码是:

<input type="radio" value="1" name="gender">男&nbsp;
<input type="radio" name="gender" value="2">女
<input type="radio" name="gender" value="0" checked>保密

  提交时,返回的值是value,即0、l或者2,而程序需要的是得到用户的性别信息,所以在Servlet程序中,应该改为以下代码。 String gender = req ucst. getP arameterf' trend er'' ); String valueed'"; if(gender.equals("l")) value=" N "; else iftgender.equals("2")) vaIue="k"; eIse value="#$"; 还有一种简单的办法是直接在HTML表单里修改Vlue属性。但是在某些情况下 JSWDK不支持中文,这时候就只能使用以上的办法了。

2.复选框(Checkbox)

  在formGetExmple例子中,爱好一栏的代码是。

<input type="checkbox" name="fond" value="1">旅游&nbsp;
        <input type="checkbox" name="fond" value="2">体育
        <input type="checkbox" name="fond" value="3">音乐
        <input type="checkbox" name="fond" value="4">摄影

 因为复选框允许多种选择,所以当使用request.getParameter()时,系统只会选中其中的一个值。在上例中;输出结果中只显示了fond=1。这时候应该使用getParamterValues 方法:public java.lang.String[] getParameterValues(java.lang.String name)。这个方法的参数一样是 HTMLform元件的key值,但是传回的是一个字符串的数组,而不是单一的字符串了。在Servlet程序中,应该改为以下代码。

String[] fonds = request.getParameterVaues("fond");
String value="";
for(int i=0;i<fonds.length;i++
{
if(fonds[i].equals("l"))
value=value+"旅游、";
else if(fonds[i].equals("2"))
va1ue=value+"体育、";
else if(fonds[i].equals("3"))
value=value+"音乐、";
else if(fonds[i].equals("4"))
valuee=value+"摄影";
}

 在这种情况下,即使在HTML表单设计时就使用了value="旅游"这样的提交方式; 也要进行以上的步骤才能获得用户提交的所有信息。

3 修改后的 formGeffixample Servlet

  其他复杂元件的处理方法基本上与这两种相同。以下将formGetExmple.java进行了修改,使其可以处理以上介绍的复杂表单。 以下是修改后的文件 formGetExample.java。

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class formGetExample extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException,ServletException
{
response.setContentType("text/html");
PrintWriter out =response.getWriter();
out.println("<html>");
out.println("<body bgcolor=\"white\">");
out.println("<head>");
out.println("<title>Servlet Get Example </title>");
out.println("</head>");
out.println("<body>");
out.println("<h1> Servlet Get Example</h1>");
String gender = request.getParamtert("gender");
String value="";
if(gender.equals("1"))
value="男";
else if(gender.equals("2"))
value="女";
else value="保密";
out.println("性别="+ value);
out.println("<br>");
String[] fonds = request.getParameterValues("fond");
value="";
for(int i=0;i<fonds.length;i++
{
if(fonds[i].equals("l"))
value=value+"旅游、";
else if(fonds[i].equals("2"))
va1ue=value+"体育、";
else if(fonds[i].equals("3"))
value=value+"音乐、";
else if(fonds[i].equals("4"))
valuee=value+"摄影";
}
out.println("爱好=" + value );
out.prinfln("<br>");
String area = request.getParameter("area");
value="";
if(area.equals("l"))
value="北京";
else if(area.equals("2"))
value="上海";
else if(area.equals("3"))
value="重庆";
else if(area.equals("4"))
value="天津';
else
value="其它";
out.println("地区="+ value);
out.println("<br>");
out.println("</body>");
out.println("</html>");
out.close();
}
}

3.4 Servlet获取环境变量

  以下的例子使用Servlet来读取提交网页的CGI环境变量。

import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class cgiGetExample extends HttpServlet{
public void doGet(HttpServletRequest req,HttpServletResponse res)
throws IOException,ServletException
{// 首先设置头部
res.setContentType("text/html");
// 用write方法返回相应数据
PrintWriter out = res.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>CGI GET EXAMPLE</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("<h1>CGI GET EXAMPLE</h1>");
Enumeration enam=req.getHeaderNames();
while(enam.hasMoreElements()){
String name=(String)enam.nextElement();
String value=req.getHeader(name);
if((value!=null)&&(!value.equals("")));{
out.println("<b>"+name+"</b>");
out.println(":");
out.println(value);
out.println("<br>");
}
}
out.println("</body>");
out.println("</html>");
out.close();
}
}

4 Servlet与网页的结合

  为了使程序更加具有通用性,网站的编程人员常常需要把servet程序与网页的HTML语言结合起来。以下将介绍HTML与Servlet之间的相互调用。

4.1 HTML中调用 Servlet程序

  对网站的编程人员来说,经常会需要在网页中插人Servlet。首先,许多HTML标记可以使用可视化的网页上成器,例如Frompage、Dreamwaver来实现。如果用Servlet生成HTML则会非常麻烦,例如:

<div align="center"><a href="red.j sp" target="_blank"><font color="#FF0000"><font size="6">red<font></b></i></font></a>

  以上语句只是在浏览器中显示一个红色的粗体字"red",该字符串以弹出窗口超级链接到red.jsp上。这么长的HTML语句frontpage中可以用很简单的属性设置来实现,但是如果用Servlet来实现的话,则是以下语句:

out.println("<div align=\"center\"><a href=\"red.jsp\" target=\"_blank\"><font color=\"#FF0000\"><font size="\6\">red<font></b></i></font></a>");

  这样一来,不仅非常麻烦,容易产生错误,而且同站的美观也无法得到保证。另外,网页编程人员需要大量的HTML标记知识,不能把全部精力用于网页编程上。其次,Servlet程序每修改一次就要编译调试一遍。当编程人员不想修改原有的Servlet程序,只是想修改它的输出结构时(例如将数据库里的资料显示到用户端的Servlet程序),完全没有必要把整个Servlet程序重新编译一遍。以下是在HTML文件中调用Servler程 序的规范:

<html>
<body>
<pre>
<SERVLET CODE="yourservlet">

<PARAM NAME=youname VALUE="yourvalue">
... ...
</SERVLET>
</pre>
</body>
</html>

  <SERVLET CODE="yourservlet">中,Code参数所指的就是要插入的Servlet的名称;即呼叫http://locahost/servlet/yourservlet;并将其输出结果与HTML文件相结合。在HTML文件中,还可以在 GET 模式中以URL传递参数,就是利用<PARAM NAME=yourname VALUE="yourvalue">来传递,其方法和表单的传送完全相同。值得一提的是,这个功能并不在Servlet使用规范之内,所以并不是每一个Servlet引擎或支持Servlet的Web Server就一定会有这个功能。

4.2 在JSP中调用Servlet程序

  在JSP中,可以利用<jsp:forward page=yourservlet"/>标签重定向到一个HTML文件,JSP文件,或者是程序段。因此。可以利用<jsp:forward>标签从一个JSP文件向一个Servlet 程序传递包含用户请求的 Request对象。在这种情况下,<jsp:forward>标签以下的代码将不能执行,以转到所需要的Servlet程序。如果想在转移的时候向目标文件传送参数和值;可以使用<jsp:param>标签。如果使用了<jsp:param>标签的话,目标文件必须是一个动态的文件,能够处理参数。注意,如果你使用了非缓冲输出的话,那么使用<jsp:forward>时就要小心;如果在你使用<jsp:forward>之前,jsp文件已经有了数据;那么文件执行就会出错。以下是一个JSP程序调用Servlet的例子。

文件 toservlet.jsp

<html>
<head>
<title> Form JSP to Servlet</title>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
</head>
<body bgcolor="#FFFFFF"
<jsp:forward page="/jspexa/servlet/toJSP"/>
</body>
</html>

  当在测览器中测览 toservlet.jsp时;程序就会被重定向到toJSP.servlet。除了使用<jsp:forward>指令外,还可以使用<jsp:include>来包含一个Servlet程序。

4.3 在Servlet程序中调用JSP

  在Servlet程序中调用JSP的方法是:getServletConfig().getServletContext(). getRequestDispatcher("/jspexa/jsp/stj.jsp).forward(request,response);以下是上例中toservlet.jsp调用的Servlet程序,该程序又重新定向到/jspexa/jsp/stj.jsp,即经过两次重定向,又转回到JSP程序。

文件:toJSP.java

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class toJSP extends HttpServlet{
  public void doGet(HttpServletRequest request,HttpServletResponse response)
  {try{request.setAttribute("comefrom","Servlet");
   getServletConfig().getServletContext().getRequestDispatcher("/jspexa/jsp/stj.jsp").forward(request,response);
    }catch(Exception ex){
     ex.printStackTrace();
        }
  }
}

文件 stj.jsp
<html>
<body bgcolor="white">
<h1>
This page is redir from:
<% out.println(request.getAttribute("comefrom").toString();%>
</h1>
</html>

把上述文件全部处理好后,运行toservlet.jsp,可以看到重新定向的情况。

5 中文显示问题及其解决办法

  若在网页中中文无法正常显示,解决办法如下:

1.修改区域设置。在控制面板中选择区域设置,将中文改为英语(美国),一切就会正常。如果还不正常,可重新启动计算机。

2.在JSP页面中加入一条语句:
<%@page contentType="text/html;charset=gb2312"%>
(此举在Tomcat中可能不起作用。)

3.在编译servlet时加入代码选项:
javac -encoding iso8859-1 文件名.java

posted on 2006-11-15 20:12 lbfeng 阅读(2776) 评论(0)  编辑  收藏 所属分类: JSP&Servlet技术

只有注册用户登录后才能发表评论。


网站导航: