服务器端开发技术Servl.ppt
2023/11/14,1,服务器端开发技术 Servlet,2023/11/14,2,服务器端开发技术Servlet,第一节.Servlet概述第二节.Servlet的开发环境及程序结构第三节.Servlet基础第四节.会话跟踪第五节.JDBC访问数据库,2023/11/14,3,第一节 Servlet概述,1.Servlet的作用 Servlet技术是使用Java技术开发Web应用的基础,后面讲述的JSP也是在它的基础上发展起来的。Servlet技术支持创建动态的Web页面,即页面内容根据用户输入或其他变量数据而改变的Web页面(动态页面),这就极大地增强了应用开发的能力。Servlet是一个基于Java语言实现的服务器端组件,它可以被用来扩充Web服务器的功能。Servlet可以简单地看作一个Java类。最终该Java类运行在一个服务器端的Servlet容器内,通过容器提供会话管理和对象生命周期管理。,2023/11/14,4,2.Servlet的优点 Servlet效率更高、更容易编程、功能更强、更安全和具有良好的可移植性,因而成为主流的动态网站技术。Servlet最大的优势在于它的高性能,Servlet采用了和CGI不同的运行方式。其次,在默认情况下,Servlet以单实例多线程的方式工作。Servlet继承了Java的所有优势,包括易升级以及平台无关性,在进行程序编写的时候可以调用Java所提供的大量的API。,2023/11/14,5,3.Servlet的基本工作原理 一个Servlet在服务器端由称为Servelt容器(也有称为servlet引擎)的程序来解释执行,可以把Servlet理解成Server上的applet,Servlet在被调用后会被动态地载入到容器由容器解释执行,这样通过Servlet包含的功能就扩展了Web服务器的功能。,2023/11/14,6,Web服务器和Servlet容器可以是两个独立的松耦合的应用程序(图表5-2),也可以是紧密集成的一个应用程序(图表5-3)。从图表5-2和图表5-3显示了一个典型的基于Servlet和JSP(一种Servlet的变体)的Web应用程序,包括若干Servlet或者JSP文件,也可能包含许多HTML文件和图片等其他资源文件。客户端对于Servet的访问先到达Web Server,如果访问的是HTML文件和图片这样的静态资源文件,Web Server会直接处理并给出响应,而如果访问的是Servlet,那么通过Servlet容器去执行Servet并给出响应。浏览器或者其他应用程序一般通过HTTP协议访问Web Server。,2023/11/14,7,2023/11/14,8,第五章.服务器端开发技术 Servlet,第一节.Servlet概述第二节.Servlet的开发环境及程序结构第三节.Servlet基础第四节.会话跟踪第五节.JDBC访问数据库,2023/11/14,9,第二节 Servlet的开发环境及程序结构,1.开发环境安装及测试(1)开发环境概述 进行Servlet开发所需要的基本环境是JSDK(Java Servlet Development Kit)、一个支持Servlet的Web服务器、集成开发工具。,2023/11/14,10,在本书中采用了JBuilder进行编辑、编译和调试Servlet。JSDK包含了编译Servlet应用程序所需要的Java类库以及相关的文档。常用的支持Servet的容器有Resin、Apache Tomcat、IBM Websphere、BEA WebLogic Server等等。本教材面向的是学校的教学,在选择开发软件环境的时候必须考虑学校和学生的实际条件。因为Resin对资源要求不高,配置比较容易,学校实验室和学生本人都有条件使用Resin。因此,在本书关于Servle和JSP的开发中,都将采用Resin 作为Web服务器。其下载Resin的网址如下:http:/,2023/11/14,11,(2)Resin的安装 安装Resin的步骤如下:安装JDK在安装Resin之前要先安装JDK(建议版本在1.4以上)。拷贝Resin目录安装完JDK之后如果要安装Resin,只需要把Resin文件夹(下载后的Resin压缩文件展开后的文件夹)拷贝到机器的特定目录下就可以了,不需要其他配置操作。启动RESIN拷贝完毕后,要启动RESIN直接执行httpd.exe即可。测试启动后,即可测试是否工作正常,方法是在浏览器里面输入http:/机器名:8080即可(如果是本机也可以输入 http:/localhost:8080)。,2023/11/14,12,Resin安装完毕后的目录结构大致如下图:,2023/11/14,13,从上图可以看出,Resin安装在文件夹下,版本号是。其中在子文件夹bin下的httpd.exe是可执行程序,子文件夹conf目录下存放配置文件。建议把所开发的应用程序存放在路径为Webapps文件夹下。另外注意,在lib子文件夹下有很多jar文件,其中jsdk23.jar是执行servlet时需要到的包,这个文件里面包含与开发Servlet有关的包和很多类,我们在Jbulider或者其他开发工具中要指定使用这个包。,2023/11/14,14,(3)Resin环境测试 安装好Resin后,我们可以启动Resin服务器,方式是执行httpd.exe即可,启动后屏幕显示结果如下图,仔细确认屏幕,如果其上没有出错提示,那么表示Resin已经启动。启动后屏幕显示结果 如下:,2023/11/14,15,为验证Resin是否工作正常,我们需要打开浏览器测试一下,在地址栏输入http:/localhost:8080,如果屏幕出现类似下面内容,表示Resin工作正常。,2023/11/14,16,2.配置Web应用 一般一个Web应用发布时都会有一个自己发布区,这个发布区往往对应一个物理的目录,所有发布的html文件、图片文件、样式表、Servlet类、JSP文件和其他一些描述性文件等都要放到这个目录及其子目录下。(1)Resin的配置文件 Resin的配置文件是resin.conf,位于安装目录的conf目录下(比如D:resin-2.1.16conf)。resin.conf是一个XML格式的配置文件,这个配置文件由很多标记组成。标记对标记对,2023/11/14,17,标记对标记是用来配置Resin所使用的资源,一般用来声明管理资源,如数据库驱动程序等。,2023/11/14,18,标记对在标记对中的配置和resin的Java Web 服务器有关。找到,在标记对里的id属性和app-dir子标记非常重要。id属性表示该应用的Web路径。如,表示该应用在Web上访问的时候应该用http:/机器名/shopping/来访问。app-dir属性表示该应用的实际路径。如:d:resindoctest表示该应用在d:resindoctest目录下。,2023/11/14,19,(2)配置自己的Web应用 假设我们有一个welcome.html的网页、一个counter.jsp的JSP文件和一个类名为RequestInfoExample.class的Servlet,现在要发布它们到一个支持Java的Web服务器上,访问的URL分别为:http:/localhost:8080/myweb/welcome.html http:/localhost:8080/myweb/counter.jsp,2023/11/14,20,修改Resin的配置文件 为了做到这点,需要修改Resin的配置文件resin.conf,在该配置文件中的中需要增加一个和其他并列的标记,指定id=/myweb,同时在的子标记中指定D:resin-2.1.16myweb,其他标记和值暂时忽略不变。该配置文件内容如下:D:resin-2.1.16myweb 修改配置文件后,一定记住要重新启动Resin,以便使新的修改被重新加载从而生效。,2023/11/14,21,HTML网页的发布及测试 使用记事本或者网页编辑工具编辑如下html代码并保存到前面配置的D:resin-2.1.16myweb目录下,文件名为welcome.html。welcome.html内容如下:Welcome,have a nice day.打开浏览器,在地址栏输入http:/localhost:8080/myweb/welcome.html,就可以看到网页的执行结果。,2023/11/14,22,JSP的发布及测试 同样,使用记事本或者网页编辑工具编辑如下JSP代码并保存到前面配置的D:resin-2.1.16myweb目录下,文件名为counter.jsp。counter.jsp,其内容如下:Counter欢迎,访问次数:打开浏览器,在地址栏输入http:/localhost:8080/myweb/counter.jsp,就可以看到JSP的执行结果。多刷新几次或者关闭浏览器重新访问看看结果会如何。,2023/11/14,23,3.第一个Servlet(1)编写及编译Servlet Java Servlet API是一个标准的Java扩展程序包,和Servlet相关的有javax.servlet和两个Java包。对于想开发基于客户自定义协议的开发者,应该使用javax.servlet包中的类与接口;对于仅利用HTTP协议与客户端进行交互的开发者,则只需要使用包中的类与接口进行开发即可。,2023/11/14,24,Servlet的结构 下面一个例子RequestInfoExample.java打印前端请求参数,代码如下:import javax.servlet.*;import.*;import java.io.*;import java.util.*;public class RequestInfoExample extends HttpServlet public void doGet(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletExceptionresponse.setContentType(text/html);PrintWriter out=response.getWriter();out.println();out.println();out.println();out.println(Request Information Example);out.println();out.println();out.println(Request Information Example);out.println(Method:+request.getMethod();out.println(Request URI:+request.getRequestURI();out.println(Protocol:+request.getProtocol();out.println(PathInfo:+request.getPathInfo();out.println(Remote Address:+request.getRemoteAddr();out.println();out.println();public void doPost(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletExceptiondoGet(request,response);,2023/11/14,25,有关该servlet程序结构说明 一般基于HTTP协议的servlet要引入javax.servlet和包RequestInfoExample从类HttpServlet派生,HttpServlet为基于HTTP协议的Servlet提供了基本的支持;HttpServletRequest对象包含了客户端请求的信息,可以通过该参数取得客户端的一些信息(例如IP地址、浏览器类型等)以及HTTP请求类型(例如GET、HEAD、POST、PUT等);HttpServletResponse对象用于完成Servlet与客户端的交互,通过调用HttpServletResponse.getWriter 方法取得向客户端进行输出的输出流(PrintWriter的对象),向客户端发送HTML页面。编写了doGet方法,对于HTML POST 请求,调用Servlet 的doPost()方法。,2023/11/14,26,编译Servlet(RequestInfoExample.java)利用Jbuilder对Servlet代码进行编译,在编译的时候一定记住要在Jbuilder中设置JSDK的路径,否则会找不到Servlet编译需要的类。编译后会生成RequestInfoExample.class类文件,该文件要发布到Resin服务器的myweb应用中,以便客户端调用。,2023/11/14,27,(2)配置Resin以调用Servlet Servlet编译后要发布到Resin服务器的指定目录下,然后通过URL去调用,就象调用HTML文件和JSP文件一样。Servlet的发布稍微麻烦一些,主要有两个工作:把类编译后的类文件拷贝到特定目录 如果要作为myweb应用的一部分发布,那么需要拷贝RequestInfoExample.class到D:resin-2.1.16mywebWEB-INFclasses目录下。如果没有该目录,手工创建即可。指定要发布的Servlet 需要在Resin配置文件resin.conf里指定要发布的Servlet,包括要让客户端调用的Servlet,调用的映射地址,并且重新启动Resin。一般Resin的配置文件发生改动,或者发布的Servlet类有变化时都需要重新启动Resin。,2023/11/14,28,为了调用RequestInfoExample Servlet,resin配置文件还针对myweb应用增加下面黑体字的内容:D:resin-2.1.16myweb,2023/11/14,29,这段代码中的servlet这一段声明了你要调用的Servlet的Java类是RequestInfoExample(servlet-class=RequestInfoExample,不带.class扩展名);同时指定它的逻辑名字是RequestInfoName(servlet-name=RequestInfoName),逻辑名字和类名不同(当然也可以相同);servlet-mapping声明逻辑名字为RequestInfoName的Servet访问时候可以通过地址/RequestInfo访问,地址/RequestInfo和Servelt的类名可以相同也可以不同。在上述配置下,可以使用如下URL去访问该Servlet:http:/localhost:8080/myweb/RequestInfo(访问方式1),2023/11/14,30,可以看出配置文件中的url-pattern=/RequestInfo 和共同决定了Servlet的调用URL(/myweb/RequestInfo)。使用配置可以让URL中访问Servlet时候的路径和Servlet类的名字无关,这样即使Servlet的类的名字修改了,对外访问的URL也可以不变,这样带来了很大的灵活性。当然,访问的时候,也可以直接通过类名或者逻辑名字访问Servlet,访问URL如下:(访问方式2)http:/localhost:8080/myweb/servlet/RequestInfoExample(访问方式3)http:/localhost:8080/myweb/servlet/RequestInfoName,2023/11/14,31,第五章.服务器端开发技术 Servlet,第一节.Servlet概述第二节.Servlet的开发环境及程序结构第三节.Servlet基础第四节.会话跟踪第五节.JDBC访问数据库,2023/11/14,32,第三节 Servlet基础,5.3.1 Servlet的生命周期 一个Java servlet具有一个生命周期,这个生命周期定义了一个Servlet如何被载入并被初始化,如何接收请求并作出对请求的响应,如何被从服务中清除。Servlet的生命周期被这个接口所定义。所有的Java Servlet都会直接地或间接地执行接口,这样它才能在一个Servlet引擎中运行。Servlet引擎是Web 服务器按照Servlet API定制的扩展。Servlet引擎提供网络服务,能够理解MIME请求,并提供一个运行Servlet的容器。理解并掌握Servlet的生命周期极为重要,只有理解了Servlet的生命周期里涉及的方法、方法的作用和方法的调用时机,才能掌握Servlet编程。接口定义了在Servlet的生命周期中特定时间以及特定顺序被调用的方法(下图)。,2023/11/14,33,1、Servlet的解析、载入和初始化 Web容器(含Servlet引擎)在启动时或者在一个Servlet被请求时载入一个Servlet并对Servlet进行初始化,在这一过程中,Servlet可以读取一些固定存储的数据、初始化JDBC的连接以及建立与其他资源的连接。,2023/11/14,34,2、Servlet处理请求 Servlet被初始化之后,它可以处理来自客户端的请求,每一个来自客户端的请求都被描述成一个ServletRequest对象,而Servlet的响应被描述成一个ServletResponse对象。当客户端发出请求时,Servlet引擎传递给Servlet一个ServletRequest对象和一个ServletResponse对象,这两个对象作为参数传递到service()方法中。,2023/11/14,35,3、Servlet的卸载 当Servlet引擎决定卸载一个Servlet时(如引擎被关闭等),这个引擎必须允许Servlet释放正在使用的资源并存储有关资料。引擎会调用Servlet的destroy()方法。Servlet引擎可以自由的在任何时候使用或清除一个Servlet。卸载一个Servlet之前,Servlet引擎会等待所有的service()方法完成或超时结束。一个Servlet被卸载时,引擎将不会给Servlet发送任何请求。引擎必须释放Servlet并完成无用存储单元的收集。,2023/11/14,36,5.3.2 Servlet相关接口和类 Servlet相关的接口和类共有3个:Servlet接口,GenericServlet类和HttpServlet类。Servlet接口定义了所有的Servlet的基本功能,作为一个接口,其他的Servlet(GenericServlet和HttpServlet)必须实现其中的方法。GenericServlet抽象类实现了Servlet接口,定义了一个通用的,与协议无关的Servlet。HttpServlet定义了一个抽象类,它继承了GenericServlet抽象类,支持基于HTTP协议的Servlet,一般自写的Servlet都是为了处理HTTP请求的,所以应当继承HttpServlet类。,2023/11/14,37,1、Servlet接口 Servlet接口定义了所有的Servlet的基本功能,以及生命周期等方法。其方法见下面的内容:,2023/11/14,38,public void init(ServletConfig config)throws ServletException;Servlet引擎会在Servlet实例化之后,置入服务之前精确地调用init方法。在调用service方法之前,init方法必须成功退出。public void service(ServletRequest request,ServletResponse response)throws ServletException,IOException;Servlet引擎调用这个方法以允许Servlet响应请求。这个方法在Servlet未成功初始化之前无法调用。在Servlet被初始化之前,Servlet引擎能够封锁未决的请求。在一个Servlet对象被卸载后,直到一个新的Servelt被初始化,Servlet引擎不能调用这个方法。,2023/11/14,39,public void destroy();当一个Servlet被从服务中去除时,Servlet引擎调用这个方法。在这个对象的service方法所有线程未全部退出或者没被引擎认为发生超时操作时,destroy方法不能被用。public ServletConfig getServletConfig();返回一个ServletConfig对象,作为一个Servlet的开发者,你应该通过init方法存储ServletConfig对象以便这个方法能返回这个对象。GenericServlet在执行这个接口时,已经这样做了。public String getServletInfo();允许Servlet向主机的Servlet运行者提供有关它本身的信息。返回的字符串应该是纯文本格式而不应有任何标志(例如HTML,XML等)。,2023/11/14,40,2、GenericServlet类 GenericServlet 类是最基本的类之一。程序员要编写Servlet 应用程序,一般要继承GenericServlet 类或它的子类HttpServlet 类。它提供了一个简单的方案来执行有关Servlet生命周期的方法以及在初始化时对ServletConfig对象和ServletContext对象进行说明。该类包含的方法如下:,2023/11/14,41,init等生命周期方法的作用和前面介绍的Servlet接口类似,注意以下两个方法在和Servlet容器交互时会使用。public ServletConfig getServletConfig()返回一个通过这个类的init方法产生ServletConfig对象的说明。public ServletContext getServletContext()它将会调用ServletConfig对象的同名的方法。,2023/11/14,42,3、HttpServlet类 HttpServlet 是从GenericServlet 继承而来,因此它具有GenericServlet 类似的方法和对象,HttpServlet是使用Servlet编程直接用到的类,它支持HTTP 的post 和 get 等方法。具体方法如下:,2023/11/14,43,init()方法的使用 在 Servlet 的生命期中,仅执行一次 init()方法。它是在服务器装入 Servlet 时执行的。可以配置服务器,以在启动服务器或客户机首次访问 Servlet 时装入 Servlet。无论有多少客户机访问Servlet,都不会重复执行 init()。service()方法使用 service()方法是 Servlet 的核心。每当一个客户请求一个HttpServlet 对象,该对象的service()方法就要被调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在 HttpServlet 中已经实现了 service()方法,该方法会根据请求调用与 HTTP 请求的方法相应的 doXXX 功能。destroy()方法 destroy()方法仅执行一次,即在服务器停止且卸装Servlet 时执行该方法。典型的,将 Servlet 作为服务器进程的一部分来关闭。缺省的 destroy()方法通常是符合要求的,但也可以覆盖它,典型的是管理服务器端资源。例如,如果 Servlet 在运行时会累计统计数据,则可以编写一个 destroy()方法,该方法用于在未装入 Servlet 时将统计数字保存在文件中。另一个示例是关闭数据库连接。,2023/11/14,44,GetServletConfig()方法 GetServletConfig()方法返回一个ServletConfig 对象,该对象用来返回初始化参数和ServletContext。ServletContext 接口提供有关servlet 的环境信息。GetServletInfo()方法 GetServletInfo()方法是一个可选的方法,它提供有关servlet 的信息,如作者、版本、版权。,2023/11/14,45,4、使用HttpServlet类进行Servlet开发 创建一个 HTTP Servlet,通常涉及下列四个步骤:扩展 HttpServlet 抽象类。重载适当的方法。如覆盖(或称为重写)service()方法或者doGet()和doPost()方法。获取信息 如果有 HTTP 请求信息的话,获取该信息。用请求对象(HttpServletRequest的对象,见后面HttpServletRequest的说明)来检索 HTML 表单所提交的数据或 URL 上的查询字符串。“请求”对象含有特定的方法以检索客户机提供的信息。生成 HTTP 响应。用响应对象(HttpServletResponse的对象,见后面的HttpServletResponse的说明)生成响应,并将它返回到发出请求的客户机上。,2023/11/14,46,一个servlet样例(ServletSample.java)如下:import java.io.*;import java.util.*;import javax.servlet.*;import.*;/第一步:扩展 HttpServlet 抽象类。public class ServletSample extends HttpServlet/第二步:重写service方法public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException System.out.println(in);/调试用,判断是否进入该函数 String myName=;/第三步:获取HTTP 请求信息 myName=request.getParameter(myName);if(myName=)|(myName=null)myName=guest;/第四步:生成 HTTP 响应。PrintWriter out=response.getWriter();response.setContentType(text/html;charset=GBK);out.println(测试例子);out.println();out.println(这是一个Servlet测试例子);out.println(+myName+你好,这是一个仅给出HTML响应的Servlet例子.);out.println(+请输入http:/localhost:8080/myweb/servlet/ServletSample?myName=John);out.println();System.out.println(html ok);/调试用,判断是否前面语句正常结束 out.flush();,2023/11/14,47,上述ServletSample类继承了HttpServlet 抽象类,同时它覆盖了父类的service()方法。在重写的service()方法中,获取HTTP 请求中的一个任选的参数(myName)。然后设置设定响应的内容的类型,并从响应对象(response)获取PrintWriter对象(out),然后使用 PrintWriter 的 print()和 println()方法给请求的客户端程序响应一个HTML格式的内容。将Servlet的类ServletSample发按照前面介绍的技术来发布到myweb应用中,需要调用 Servlet 或 Web 应用程序,可以使用下列任一种方法:由 URL 调用、在 标记中调用。,2023/11/14,48,URL 调用 Servlet()在发布Servlet的Resin服务器上打开浏览器,输入如下URLhttp:/localhost:8080/myweb/servlet/ServletSample?myName=John如果在其他机器上,上述URL的localhost可以换成发布Servlet的Resin服务器的主机名。在 标记中指定 Servlet可以在 标记中调用 Servlet。HTML 格式使用户能在 Web 页面(即从浏览器)上输入数据,并向 Servlet 提交数据。例如:Zhang Jun Administrator,2023/11/14,49,5.3.3 请求响应类及接口当一个servlet接收来自客户端的调用请求(通过service,doXXX方法),它接收两个对象:一个是ServletRequest和ServletResponse。ServletRequest类概括从客户端到服务器之间的联系。ServletResponse类概括从servlet返回客户端的联系,用于Servlet向客户发送响应。HttpServletRequest接口继承了ServletRequest接口,他可以让servlet获取更多的HTTP协议特性数据。HttpServletResponse接口继承了ServletResponse 接口,它为Servlet返回HTTP回应给客户端提供了支持。,2023/11/14,50,四个接口里定义的方法,2023/11/14,51,1、ServletRequest public String getParameter(String name)以String对象返回指定的参数的值,如果这个参数不存在返回空值。public String getParameterValues(String name);通过String对象的数组返回指定参数的值,如果这个参数不存在,该方法返回一个空值。public Enumeration getParameterNames()返回所有参数名的String对象列表,如果没有输入参数,该方法返回一个空值。public void setAttribute(String name,Object object)在请求中添加一个属性,这个属性可以被其他可以访问这个请求对象的对象使用。public Object getAttribute(String name)返回请求中指定属性的值,如果这个属性不存在,就返回一个空值。public Enumeration getAttributeNames()返回包含在这个请求中的所有属性名的列表。,2023/11/14,52,2、HttpServletRequest 该接口继承了ServletRequest接口,在ServletRequest接口的方法基础上,需要进一步掌握以下2个方法:public Cookie getCookies()返回一个数组,该数组包含这个请求中当前的所有Cookie。如果这个请求中没有Cookie,返回一个空数组。public HttpSession getSession()public HttpSession getSession(boolean create)返回与这个请求关联的当前的有效的session。如果调用这个方法时没带参数,那么在没有session与这个请求关联的情况下,将会新建一个session。getCookies和getSession方法分别用于支持Cookie和Session,在后面将详细介绍它们的使用。,2023/11/14,53,3、ServletResponse public PrintWriter getWriter throws IOException 这个方法返回一个PringWriter对象用来记录格式化的响应实体。public void setContentType(String type)这个方法用来设定响应的content类型。public String getCharacterEncoding()返回MIME实体的字符编码。在HTTP协议中,这个信息被通过Accept-Charset传送到Servlet引擎。public ServletOutputStream getOutputStream()throws IOException 返回一个记录二进制的响应数据的输出流。public void setContentLength(int length)设置响应的内容的长度,这个方法会覆盖以前对内容长度的设定。为了保证成功地设定响应头的内容长度,在响应被提交到输出流之前必须调用这个方法。,2023/11/14,54,4、HttpServletResponse HttpServletResponse描述一个返回到客户端的HTTP回应。通过该接口可以利用HTTP协议规定的头信息。public void addCookie(Cookie cookie)在响应中增加一个指定的Cookie。可多次调用该方法以定义多个Cookie。为了设置适当的头域,该方法应该在响应被提交之前调用。public void sendRedirect(String location)throws IOException;使用给定的路径,给客户端发出一个临时转向的响应。给定的路径必须是绝对URL。,2023/11/14,55,5、Servlet综合示例 要求达到的功能:用户在界面上输入的姓名(文本框)和选择要购买的商品(多选按钮)后点击提交按钮,提交给后台Servlet处理Servlet对用户的点击的商品的价格给出响应,响应的内容为显示该用户的名字,同时显示用户购买的商品以及商品总价假设页面上显示的商品包括MP3,DV,Radio,Pen,这4种商品的价钱在Servlet里面用变量维护。,2023/11/14,56,HTML页面:要完成这样的功能,考虑使用一个HTML页面(commodity.html)完成商品选择和提交。HTML文件里面包含一个Form,Form里面包含一个文本框,同时包括多选按钮来显示已有4种商品供用户选择。页面外观参考如下:,2023/11/14,57,Servlet:另外,一个Servlet(CommodityServlet)接收Form提交的请求并进行处理,在该Servlet中获取用户输入的姓名,同时获取选择的商品,通过商品名查找该商品的价格,然后给用户响应,响应内容及格式参考下图。,2023/11/14,58,commodity.html:名字商品如下:MP3 DV 收音机 钢笔注意commodity.html提交的两个参数为name和goods,其中goods可能会同时提交多个值。,2023/11/14,59,CommodityServlet.java:import java.io.*;import java.util.*;import javax.servlet.*;import.*;/第一步:扩展 HttpServlet 抽象类。public class CommodityServlet extends HttpServlet/第二步:重写service方法 public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOExceptio