第3章?Servlet基础      本章要点: * 能知道Servlet的历史发展和特点。 * 能理解Servlet的生命周期和运行过程。 * 会编写Servlet代码。 * 会使用Servlet开发Web网站。 * 会部署Servlet到Web服务器Tomcat。    ?3.1    Servlet概述      在Servlet出现之前,Web服务器通过CGI技术与客户端进行交互。具体实现时,需要使用Perl、Shell Script或C语言编写CGI程序,再部署到Web服务器,从而使Web服务器能处理来自客户端网页表单的输入信息并将处理后的信息反馈给客户端。但是,CGI技术存在很多缺点,主要如下。 * CGI程序开发比较困难。要求开发人员具备处理参数传递的能力,需要开发经验。 * CGI程序不可移植。为某一特定平台编写的CGI程序只能运行于该特定平台中。 * CGI程序内存和CPU开销大,而且在同一进程中不能服务多个客户。因为每个 CGI程序存在于一个由客户端请求激活的Web服务器进程中,并且在请求完成后被卸载。   随着Java语言的广泛使用,Servlet迅速成为动态网站的主要开发技术。实际上,Servlet可以定义为一种基于Java技术的Web组件,用来扩展以请求和响应为模型的Web服务的能力。它是一种独立于平台和协议的服务器端的Java应用程序,与传统的从命令行启动的Java应用程序不同,Servlet本身没有main方法,不是由用户或开发人员调用的,而是由另外一个应用程序——Servlet容器调用和管理的。其中,Servlet容器又称为引擎,承担着运行环境的作用,管理和维护所有Servlet的完整生命周期,并将所有的Servlet编译成字节码从而生成动态的内容以供Web请求调用。   本书使用Tomcat作为运行Java Web网站的服务器,也就是说,Tomcat是Servlet容器,也是Servlet的运行环境。具体运行时,Tomcat负责把客户端的请求传递给Servlet,并把处理结果返回给客户端。当多个客户端请求同一个Servlet时,Tomcat将处理这些并发问题并负责为每个客户端启动一个线程,之后,这些线程的运行和销毁由Tomcat负责。   相比于CGI技术,Servlet具有以下特点。 * 高效。在服务器上仅有一个Java 虚拟机在运行,其优势在于当多个来自客户端的请求访问时,Servlet为每个请求分配一个线程,而不是进程。 * 方便。Servlet提供了大量的实用程序,如处理复杂的HTML表单数据、读取和设置HTTP头,以及处理Cookie和跟踪会话等。 * 跨平台。Servlet用Java语言编写,可以在不同操作系统平台和不同应用服务器平台运行。 * 功能强大。在Servlet中,许多使用传统CGI程序很难完成的任务都可以轻松地完成。例如,Servlet能够直接和Web服务器交互,而CGI程序一般不能实现。Servlet还能够在各个程序之间共享数据,使得数据库连接池之类的功能很容易实现。 * 灵活性和可扩展性强。采用Servlet开发的Web应用具备Java的面向对象特性,因此应用灵活,可扩展性强。    ?3.2    Servlet的生命周期与运行过程      Servlet运行在Web服务器的Servlet容器里,容器根据Servlet的规范,执行Servlet对象的初始化、运行和卸载等动作。Servlet在容器中从创建、初始化、执行到卸载的过程被称为Servlet的生命周期。   (1)当客户端第一次请求Servlet时,容器加载开发人员编写的HttpServlet类。在Java Web网站开发过程中,开发人员编写Servlet代码一般直接继承javax.servlet.http包中的HttpServlet类。   (2)Servlet容器根据客户端请求创建HttpServlet对象实例,并把这些实例加入HttpServlet实例池中。   (3)Servlet容器调用HttpServlet的初始化方法init,完成初始化。   (4)Servlet容器创建一个HttpServletRequest对象实例和一个HttpServletResponse对象实例。HttpServletRequest对象实例封装了客户端的HTTP请求信息,而HttpServletResponse对象实例是一个新实例。   (5)Servlet容器把HttpServletRequest对象实例和HttpServletResponse对象实例传递给HttpServlet的执行方法service。service方法可被多次请求调用,各调用过程运行在不同的线程中,互不干扰。   (6)HttpServlet对象实例在执行service方法时,通常从HttpServletRequest对象读取HTTP请求数据,访问来自HttpSession或Cookie对象的状态信息,执行特定应用的处理并且用HttpServletResponse对象生成HTTP响应数据。   (7)当Servlet容器关闭时会自动调用HttpServlet对象实例的destroy方法,释放运行时占用的资源。   从图3-1中可以看出,当多个客户端请求同一个Servlet时,Servlet容器为每个客户请求启动一个线程。init方法只在Servlet第一次被请求加载时调用一次,当该Servlet再次被客户端请求时,Servlet容器将启动一个新的线程,在该线程中调用service方法响应客户端请求。在Servlet生命周期的各个阶段中,执行service方法时是真正处理业务的阶段,所以开发人员在编写Servlet相关代码时,主要在这个方法中编写代码实现业务功能。    图3-1 Servlet的生命周期与运行过程    ?3.3    开发第一个Servlet      开发编写Servlet类的方式是继承javax.servlet.http包中的HttpServlet类,应在service方法中编写代码响应请求。但是HttpServlet类中的service方法已经实现,部分源代码如下。 源程序:HttpServlet类中service方法的部分代码 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { //若为Get请求 long lastModified = getLastModified(req); if (lastModified == -1) { doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < lastModified) { maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_POST)) { //若为Post请求 doPost(req, resp); } else { //若为其他请求 … } }      从上述源代码中可知,service方法根据请求的类型Get、Post等,调用相应的方法doGet、doPost等,所以开发人员实际编写Servlet类时,只要实现doGet、doPost等方法即可。 实例3-1 第一个Servlet程序   本实例利用Servlet的doGet方法实现在页面上输出节能环保的提示信息。 源程序:FirstServlet.java package com.example.ch03; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/FirstServlet") public class FirstServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request,                  HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.println(""); out.println("

节能环保tips:空调设置温度:" + "夏季不得低于26℃;冬季不得高于20℃。

"); out.println(""); } @Override protected void doPost(HttpServletRequest request,                   HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }      操作步骤:   (1)在Book项目中创建ch03模块。右击Book项目名称,在弹出的快捷菜单中选择New→Module命令,在弹出的对话框中选择模块类型为Java Enterprise,设置模块名称为ch03、位置为D:\ideaProj\Book\ch03,选择模块结构为Web application,选择应用服务器为Tomcat 9.0.29,然后单击Next按钮,在弹出的对话框中单击Finish按钮,ch03模块建立完成。   (2)右击com.example. ch03包,在弹出的快捷菜单中选择New→Servlet命令,然后输入名称FirstServlet,按Enter键确认建立文件,项目文件结构如图3-2所示。    图3-2 项目文件的结构图   (3)在FirstServlet.java文件中输入源代码。   (4)单击运行工具条,选择Edit Configurations,如图3-3所示。       图3-3 选择配置Tomcat   (5)在Run/Debug Configurations对话框中选择Deployment选项卡,单击“+”按钮,选择Artifact选项,在下拉列表中选择ch03:war exploded,单击OK按钮,最后修改Application context为“/ch03”。单击OK按钮,完成ch03模块网站在Tomcat中的部署。配置界面如图3-4所示。    图3-4 部署ch03模块网站   (6)单击运行工具栏中的“运行”按钮,启动Tomcat。Tomcat在启动时,IDEA界面中将输出Tomcat启动和部署当前项目的相关信息,如图3-5所示。其中①表示Tomcat耗时32ms完成启动;②表示当前项目已经成功部署到Tomcat中。    图3-5 Tomcat启动时的提示信息   (7)在浏览器地址栏中输入网址http://localhost:8080/ch03/FirstServlet,查看运行效果,如图3-6所示。    图3-6 FirstServlet.java的运行效果   程序说明: * “response.setContentType("text/html");”表示响应内容格式为HTML文本。 * “response.setCharacterEncoding("UTF-8");”表示响应内容语言编码字符集为UTF-8。 * 在Servlet直接输出HTML页面信息,必须执行上述两行代码。 * “操作步骤”中的(4)(5)两步,仅需要在ch03模块网站第一次运行时设置。    ?3.4    Servlet的部署方法      Servlet容器是Servlet的运行环境,管理和维护Servlet的完整生命周期,所以Servlet必须要部署到Servlet容器中,才能运行起来处理客户端请求。Servlet的部署方法有两种:一种是通过web.xml部署;另一种是通过注解部署。 * 3.4.1 通过web.xml部署Servlet   在IDEA开发工具中创建Web Application项目时,会自动创建webapp和WEB-INF文件夹。webapp是本项目Web站点的根节点,用于存放html、jsp、css、js、jpg等类型资源文件,WEB-INF中包含Web站点的配置文件web.xml。 实例3-2 通过web.xml部署Servlet   本实例利用web.xml文件设置Servlet的配置信息。 源程序:DeployServlet.java package com.example.ch03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; import java.io.PrintWriter; public class DeployServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request,                  HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); out.println(""); out.println("

节能环保tips:节能减排靠大家;低碳生活一同享。

"); out.println(""); } @Override protected void doPost(HttpServletRequest request,                   HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } 源程序:web.xml文件代码 DeployServlet com.example.ch03.DeployServlet    count 100 5 DeployServlet /DeployServlet      操作步骤:   (1)右击com.example.ch03包,在弹出的快捷菜单中选择New→Servlet命令,然后输入名称DeployServlet,按Enter键确认建立文件。   (2)在DeployServlet.java文件中输入源代码,务必删除@WebServlet所在行的代码。   (3)在webapp\WEB-INF\web.xml文件中输入源代码。   (4)单击运行工具栏中的“运行”按钮,启动Tomcat。   (5)在浏览器地址栏中输入网址http://localhost:8080/ch03/DeployServlet,查看运行效果,如图3-7所示。    图3-7 实例3-2的运行效果   程序说明: * 删除@WebServlet所在行的代码,是因为开发工具创建的Servlet文件默认包含注解,而本实例是通过web.xml部署Servlet,所以需要删除注解。 * 标记。XML文件中必须有一个根标记,web.xml的根标记是。 * 标记。可以配置多个不同名称的标记。标记中有四个子标记:①子标记的内容是Tomcat创建Servlet对象的名字,不能重名;②子标记的内容是指定Tomcat用什么类来创建Servlet对象;③子标记的内容是正整数或者0时,表示Tomcat在启动时就加载并初始化这个Servlet,值越小就越先被加载,如果不指定或者为负整数则在客户端第一次请求时再加载;④子标记内容是参数初始值,在Servlet的init方法内通过getInitParameter方法读取。 * 标记。需要与标记成对使用。中有两个子标记:①子标记必须与对应标记中的内容相同;②子标记用来指定客户端请求Servlet模式,即访问Servlet的URL。例如,若子标记的内容是“/SecondServlet”,那么客户端浏览器请求访问时在地址栏中输入的URL内容应为http://localhost:8080/ch03/SecondServlet。    * 3.4.2 通过注解方式部署Servlet   Servlet 3.0版本包含注解(Annotation)新特性,提供了更加便利的部署方式,简化了开发流程。本书中采用的开发环境为JDK8与Tomcat9,支持Servlet 4.0版本,所以在IDEA开发工具中新建的Servlet默认使用注解方式部署Servlet。本书后续的实例都采用注解方式部署Servlet。   @WebServlet注解将继承于javax.servlet.http.HttpServlet的类标注为可以处理用户请求的Servlet。Tomcat根据注解的具体属性配置将相应的类部署为Servlet。该注解具有表3-1给出的常用属性。表中的属性均为可选属性,但是 value属性或者urlPatterns属性是必需的,且二者不能共存,如果同时指定则忽略 value属性。 表3-1 注解@WebServlet的属性 属?性?名 类 ? 型 描 述 name String Servlet的名称,等价于。没有显式指定则默认值为全类名(包含包名和类名) urlPatterns String[] 访问Servlet的URL,指定一组 Servlet的URL。等价于标签 value String[] 访问Servlet的URL,等价于urlPatterns属性 loadOnStartup int Servlet的加载优先级,等价于标签 initParams String Servlet的初始化参数,指定一组 Servlet初始化参数,等价于标签 实例3-3 通过注解方式部署Servlet   本实例利用@WebServlet注解在Tomcat中部署Servlet。 源程序:AnnotationServlet.java的部分代码 @WebServlet( name="AnnotationServlet", value="/AnnotationServlet", initParams = {@WebInitParam(name="count", value = "100")}, loadOnStartup =5) public class AnnotationServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); out.println(""); out.println("

节约粮食tips:向舌尖上的浪费说不,向光盘的您看齐。

"); out.println(""); } }      操作步骤:   (1)右击com.example.ch03包,在弹出的快捷菜单中选择New→Servlet命令,然后输入名称AnnotationServlet,按Enter键确认建立文件。   (2)在AnnotationServlet.java文件中输入源代码。   (3)单击运行工具栏中的“运行”按钮,启动Tomcat。   (4)在浏览器中输入网址http://localhost:8080/ch03/AnnotationServlet,查看运行效果,如图3-8所示。    图3-8 实例3-3的运行效果   程序说明: * 本实例中,若@WebServlet只有一个属性value="/AnnotationServlet",那么value和=符号也可以省略,即最简模式为@WebServlet("/AnnotationServlet")。 * 本书后续实例中的Servlet注解都采用最简模式。    ?3.5    请求Servlet的三种方式      请求Servlet的常用方式有三种,分别为通过超链接方式请求、通过JSP页面或者 HTML页面的表单方式请求,以及通过JavaScript脚本的Ajax方式请求。 * 3.5.1 超链接请求Servlet 实例3-4 超链接请求Servlet   本实例利用超链接标签中的href属性请求Servlet。 源程序:young.html 超链接请求Servlet 学习古诗《教子诗》 源程序:YoungServlet.java的部分代码 @WebServlet("/YoungServlet") public class YoungServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request,       HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); out.println(""); out.println("

教子诗

"); out.println("

【宋】余良弼

"); out.println("

白发无凭吾老矣,青春不再汝知乎。

"); out.println("

年将弱冠非童子,学不成名岂丈夫。

"); out.println("

幸有明窗并净几,何劳凿壁与编蒲。

"); out.println("

功成欲自殊头角,记取韩公训阿符。

"); out.println(""); } }      操作步骤:   (1)右击com.example.ch03包,在弹出的快捷菜单中选择New→Servlet命令,然后输入名称YoungServlet,按Enter键确认建立文件。   (2)右击webapp文件夹,在弹出的快捷菜单中选择New→HTML命令,然后输入名称young,按Enter键确认建立文件。   (3)分别在young.html和YoungServlet.java文件中输入源代码。   (4)单击运行工具栏中的“运行”按钮,启动Tomcat。   (5)在浏览器中输入网址http://localhost:8080/ch03/young.html,查看浏览效果,如 图?3-9所示。    图3-9 young.html的运行效果   (6)单击页面上的超链接,请求访问YoungServlet,运行效果如图3-10所示。    图3-10 YoungServlet.java的运行效果   程序说明: * 超链接属性href的值应与@WebServlet注解中value属性值一致,不包含“/”字符。 * 超链接被单击激活时,浏览器以Get方式发送请求。 * 在浏览器地址栏中输入请求Servlet的URL,与超链接请求效果一致。 * 3.5.2 表单请求Servlet   通过JSP页面或者HTML页面的表单请求Servlet,两者的方法是一致的。 实例3-5 表单请求Servlet   本实例利用HTML页面提交表单方式请求Servlet,实现登记无偿献血者信息的功能。 源程序:donate.html的部分代码

无偿献血登记



源程序:DonateServlet.java的部分代码 @WebServlet("/DonateServlet") public class DonateServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request,       HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); String bloodtype = request.getParameter("bloodtype"); response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.println(""); out.println("

无偿献血是无私奉献、救死扶伤的崇高行为。

"); out.println("

感谢您!"+bloodtype+"型血的"+name+"朋友。

"); out.println(""); } }      操作步骤:   (1)右击com.example.ch03包,在弹出的快捷菜单中选择New→Servlet命令,然后输入名称DonateServlet,按Enter键确认建立文件。   (2)右击webapp文件夹,在弹出的快捷菜单中选择New→HTML命令,然后输入名称donate,按Enter键确认建立文件。   (3)分别在donate.html和DonateServlet.java文件中输入源代码。   (4)单击运行工具栏中的“运行”按钮,启动Tomcat。   (5)在浏览器中输入网址http://localhost:8080/ch03/donate.html,查看运行效果,如图?3-11所示。    图3-11 donate.html的运行效果   (6)在页面上输入姓名,选择血型,单击“提交”按钮,运行效果如图3-12所示。    图3-12 DonateServlet.java的运行效果   程序说明: * 表单属性action的值应与@WebServlet注解中value属性值一致,不包含“/”字符。 * 表单属性method的值应与Servlet中的服务方法对应,即get对应doGet方法,post对应doPost方法。 * “request.getParameter("name");”为读取表单中的姓名信息。 * “request.getParameter("bloodtype");”为读取表单中的血型信息,4.7.1节将详细介绍该方法。 * 通常情况下,Servlet的doGet与doPost方法中的处理请求代码相同,所以可以在doGet中编写处理请求的详细代码,而在doPost中调用doGet,从而优化代码量。    * 3.5.3 Ajax方法请求Servlet 实例3-6 Ajax方法请求Servlet   本实例利用JavaScript脚本中的Ajax方法请求Servlet,实现了在公益志愿者注册时校验用户名是否重复的功能。 源程序:register.html 公益志愿者用户注册
公益志愿者用户注册



源程序:CheckNameServlet.java的部分代码 @WebServlet("/CheckNameServlet") public class CheckNameServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ request.setCharacterEncoding("UTF-8"); String userName = request.getParameter("userName"); response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); //简化实例,假设用户名userA已被占用,当用户提交的用户名为userA时 //Servlet响应输出isUsed,否则响应输出notUsed if (userName.equals("userA")){ //响应输出使用print方法 //因为println方法会带上换行符号,不便于前端JavaScript代码进行字符串比较 out.print("isUsed"); }else{ out.print("notUsed"); } } }      操作步骤:   (1)右击com.example.ch03包,在弹出的快捷菜单中选择New→Servlet命令,然后输入名称CheckNameServlet,按Enter键确认建立文件。   (2)右击webapp文件夹,在弹出的快捷菜单中选择New→HTML命令,然后输入名称register,按Enter键确认建立文件。   (3)在register.html和CheckNameServlet.java文件中输入源代码。   (4)单击运行工具栏中的“运行”按钮,启动Tomcat。   (5)在浏览器中输入网址http://localhost:8080/ch03/register.html,查看运行效果,如图?3-13所示。    图3-13 register.html的运行效果   (6)在“用户名称”文本框中输入userA,单击“邮箱地址”文本框,此时触发“用户名称”文本框的失去焦点(blur)事件,执行Ajax请求,校验“用户名称”是否重复,运行效果如图3-14所示。    图3-14 CheckNameServlet.java的运行效果   程序说明: * “”表示在HTML文件中引入了jQuery库文件。因为是通过网络URL引入库文件的,所以在运行本实例时需要联网。 * 为了简化演示代码,假定用户名userA已经占用,其他用户名可用。 * “out.print("isUsed");”表示Servlet向客户端输出字符串,告知客户端该用户名已经被其他用户占用。这里一般情况下不使用printIn方法,因为该方法输出的字符信息结尾处带换行符,不便于JavaScript进行字符串比较。 * 为了简化演示代码,CheckNameServlet响应输出设置为"text/html"格式,但在实际项目中,前后端之间的数据响应通常使用"application/json"格式。    ?3.6    小结      本章首先介绍了Servlet技术的发展历史,重点说明了Servlet的生命周期和运行过程。其次介绍了编写Servlet的方式以及如何将Servlet部署到Web服务器中。最后通过三个实例展示了Serlvet处理客户端请求的具体方法。    ?3.7    习题      1.填空题   (1)在Servlet出现之前,Web服务器通过 技术与客户端进行交互。   (2)部署Servlet的配置有两种方式:一种是通过 部署;另一种是通过 部署。   (3)在IDEA开发工具中创建Web Application项目时,会自动创建webapp和WEB- INF文件夹。其中 是本项目Web站点根节点。   (4)使用注解方式部署Servlet时,若@WebServlet只有一个属性value="/Servlet1",那么value和=符号也可以省略,即最简模式为 。   (5)请求Servlet的常用方式有3种,分别为通过 方式请求,通过页面的 ________方式请求,以及通过JavaScript脚本的 方式请求。   2.选择题   (1)开发编写Servlet类的方式是继承javax.servlet.http包中的( )。 A.Servlet类 B.HttpServlet类 C.HttpGetServlet类 D.HttpPostServlet类   (2)关于Servlet的说法不正确的是( )。     A.当多个来自客户端的请求访问时,Servlet为每个请求分配一个进程     B.当Servlet容器关闭时会自动调用destroy方法,释放运行时占用的资源     C.Servlet中的service方法可被多次请求调用,各调用过程运行在不同的线程中     D.Servlet中的init方法仅执行一次   (3)关于@WebServlet的注解说法正确的是( )。     A.Servlet 4.0以上版本包含注解(Annotation)新特性     B.name属性是必须显示指定的属性     C.urlPatterns属性用于指定一组 Servlet的URL     D.value属性或者urlPatterns属性是必需的,且二者可以共存   3.简答题   (1)简述Servlet的生命周期与运行过程。   (2)简述web.xml与注解部署Servlet的区别。   (3)简述开发编写以及测试运行Servlet的基本流程。   4.上机操作题   (1)建立并测试本章的所有实例。   (2)Servlet应用练习——古诗学习。   习题背景:党的十八大以来,习近平总书记在多个场合谈到中国传统文化,表达了自己对传统文化、传统思想价值体系的认同与尊崇。2014年5月4日他与北京大学学子座 谈,也多次提到核心价值观和文化自信。习近平总书记在国内外不同场合的活动与讲话中,展现了中国政府与人民的精神志气,提振了中华民族的文化自信。   我们有博大精深的优秀传统文化。它能“增强做中国人的骨气和底气”,是我们最深厚的文化软实力,是我们文化发展的母体,积淀着中华民族最深沉的精神追求。诸如“自强不息”的奋斗精神,“精忠报国”的爱国情怀,“天下兴亡,匹夫有责”的担当意识,“舍生取义”的牺牲精神,“革故鼎新”的创新思想,“扶危济困”的公德意识,“国而忘家,公而忘私”的价值理念等,一直是中华民族奋发进取的精神动力。其中古诗是我们优秀传统文化中重要的一部分,学习优秀古诗是我们中国人的必修课之一。   习题要求:在HTML页面上设计一个表单,表单标题为“古诗学习欣赏”,表单内容为一个输入古诗名称的文本框,表单以Post方式提交到Servlet;Servlet中读取古诗名称,如果古诗名称是“劝学”,输出“劝学”古诗的信息,否则输出“抱歉暂未收录”。   命名规范:HTML页面命名为index31.html,Servlet命名为PoemServlet。   习题指导:①参考3.5.1节的内容,新建HTML文件和Servlet文件。②在Servlet中读取古诗名称,进行字符串比较时不能使用“= =”,应该使用equals方法。   参考资料:《劝学》唐-孟郊 击石乃有火,不击元无烟。人学始知道,不学非自然。万事须己运,他得非我贤。青春须早为,岂能长少年。《劝学》唐-颜真卿 三更灯火五更鸡,正是男儿读书时。黑发不知勤学早,白首方悔读书迟。   (3)Servlet应用练习——北京冬奥会奖牌统计。   习题背景:2022年北京-张家口冬季奥运会,第24届冬季奥林匹克运动会,2022年2月4日至2022年2月20日在中华人民共和国北京市和张家口市联合举行。这是中国历史上第一次举办冬季奥运会,北京、张家口同为主办城市,也是中国继北京奥运会、南京青奥会后,中国第三次举办的奥运赛事。北京-张家口冬季奥运会设7个大项,102个小项。北京将承办所有冰上项目,北京延庆和张家口将承办所有的雪上项目。   聚冰雪热爱展万象灵韵,迎八方宾客赏四季风华。一场精彩、非凡、卓越的冬奥会成为了中国送给世界的美好礼物。盛会闭幕,未来已来,“双奥之城”北京已用一份精彩的答卷点燃了舞动冰雪的激情,照亮了砥砺前行的征程。让我们再道一声“你好,双奥之城”,共赴美好前程。   习题要求:在HTML页面上设计一个表单,表单标题为“2022年北京冬奥会-奖牌统计”,表单内容为3个文本框,分别输入中国队金、银、铜奖牌数量,表单以Post方式提交到Servlet;Servlet中计算奖牌总数,并输出3号标题“2022年北京冬奥会上中国队获得?块奖牌!”,?号用计算结果代替,同时输出奖牌榜图片。   命名规范:HTML页面命名为index32.html,Servlet命名为OlympicServlet,奖牌榜图片命为olympic.png。   习题指导:①参考3.5.2节的内容,新建HTML文件和Servlet文件,在webapp文件夹中新建images文件夹,然后把olympic.png复制到images文件夹中。②在Servlet中分别读取金、银、铜奖牌数量后,读取的值默认为字符串类型,需要转换为整数类型后再计算。③输出奖牌榜图片实际是输出奖牌榜标记。④北京冬奥 会奖牌榜如图3-15所示,请从网络中搜索北京冬奥会奖牌榜,并截图保存。    图3-15 北京冬奥会奖牌榜   (4)Servlet应用练习——志愿者登记。   习题背景:1993年底,共青团中央决定实施中国青年志愿者行动。同年12月19日,2万余名铁路青年率先打出了“青年志愿者”的旗帜,在京广铁路沿线开展了为旅客送温暖志愿服务。之后,40余万名大中学生利用寒假在全国主要铁路沿线和车站开展志愿者新春热心行动,青年志愿者行动迅速在全国展开。青年志愿者行动不断发展,志愿服务的领域不断扩大,志愿者队伍日益壮大。据不完全统计,至2000年6月,全国累计已有8000多万人次的青年向社会提供了超过40亿小时的志愿服务。   为推动青年志愿服务事业的发展,团中央于1994年12月5日成立了中国青年志愿者协会,随后,各级青年志愿者协会也逐步建立起来。到2000年,已初步形成了由全国性协会、36个省级协会和2/3以上的地(市)级协会及部分县级协会组成的志愿服务组织管理网络。   广大青年志愿者加入志愿者协会的第一步就是注册,下面通过练习题来实现简单的志愿者登记功能。   习题要求:在HTML页面上设计一个表单,表单标题为“中国青年志愿者注册”,表单内容为3个文本框,分别输入用户名称、邮箱地址、真实姓名,以及服务类别的复选项,包含社区建设、环境保护、大型赛会、应急救助等选项。表单以Post方式提交到Servlet;Servlet中读取并输出用户注册信息。   命名规范:HTML页面命名为index33.html,Servlet命名为RegServlet。   习题指导:①参考3.5.3节的内容新建HTML文件,参考3.5.2节的内容新建Servlet。②在Servlet中读取服务类别时,使用request. getParameterValues()方法,该方法返回类型为字符串数组,需要遍历数组输出。   扩展要求:使用Ajax技术实现用户名称重复校验功能,假定用户名userA、userB已占用,其他用户名可用。       56    57