目录
Servlet技术及应用预习报告
一、实验目的
二、实验原理
三、实验预习内容
1. Web页面中都可以使用哪些方式来发送HTTP请求?
2. GET与POST两种请求方式有什么区别?分别适用于什么情况?
3.HTTP响应内容的类型都有哪些?如何设置HTTP响应内容的类型?
4.什么是ServletContext对象,它的生存周期如何?
5. ServletContext与ServletRequest的getRequestDispatcher()方法有什么区别?
Servlet技术及应用实验报告
一、实验目的
二、实验要求
三、实验原理
四、实验内容与步骤
1. 简单的综合应用,掌握Servlet将请求转发给另一个Servlet的方法。
2. 编写一个Servlet,显示所有请求头信息:
3. 编写一个名为ExcelServlet的Servlet程序,通过设置响应内容类型和输出流,向客户端浏览器响应一个带数据的Excel电子表格,程序的运行结果要求如下图所示。
4. 使用ServletConfig检索Servlet的初始化参数。
5. 为ServletContext配置初始化参数并进行访问。
四、思考题
1. 请求中的参数如果是中文,如何正常显示中文参数值?
2. 使用RequestDispatcher的forward()方法转发请求和使用HttpServletResponse的sendRedirect()方法重定向请求有什么区别?
3. 什么是Web归档文件?如何为一个Web应用创建一个WAR文件?如何发布WAR文件?
4. 如何编写线程安全的Servlet?
Servlet技术及应用预习报告
一、实验目的
1. 掌握如何获得请求参数;
2. 掌握如何检索请求头;
3. 了解如何通过请求对象获得客户信息;
4. 重点掌握使用请求对象存储数据和请求转发;
5. 掌握如何通过ServletConfig获取Servlet的初始化参数;
6. 掌握ServletContext的概念,如何获得ServletContext对象;
7. 掌握如何通过ServletContex对象的RequestDispatcher进行请求转发;
8. 了解Servlet的多线程问题及解决方法。
二、实验原理
对客户的请求,容器根据请求调用Servlet的相应doXxx()方法,该方法带有两个参数,一个是HttpServletRequest,一个是HttpServletResponse,它们分别表示请求对象和响应对象,它们是容器自动创建的两个对象。可以使用这两个接口定义的若干方法完成有关操作。
Web应用程序有严格定义的目录结构,它需要一个称为部署描述文件的文件web.xml来配置。对应用程序的每个Servlet,可以在web.xml中定义若干个初始化参数,然后通过ServletConfig对象获取这些参数。
ServletContext对象表示该应用程序的环境,通过该对象可以获得应用程序范围的初始化参数、容器版本信息、资源的URL、在其中存放共享数据以及登录日志等。
三、实验预习内容
1. Web页面中都可以使用哪些方式来发送HTTP请求?
(1)用户在浏览器的地址栏中输入URL并按回车键;
(2)用户点击了HTML页面中的超链接;
(3)用户在HTML页面中添写一个表单并提交.2. GET与POST两种请求方式有什么区别?分别适用于什么情况?
(1)GET方法用来检索资源。它的含义是”获得由该URI标识的资源”。GET方法请求的资源通常是静态资源.使用GET也可以请求动态资源,但一般要提供少量的请求参数。
(2)POST方法用来向服务器发送需要处理的数据,它的含义是”将数据发送到由该URI标识的动态资源”。3.HTTP响应内容的类型都有哪些?如何设置HTTP响应内容的类型?
(1)类型有:
1)public PrintWriter getWriter():返回一个PrintWriter对象用于向客户发送文本数据.
2)public ServletOutStream getOutputStream() throws IOException:返回一个输出流对象,它用来向客户发送二进制数据。
3)public void setContentType(String type):设置发送到客户端响应的MIME内容类型。
(2)设置方法:
设置响应数据内容类型应该使用相应对象的setContentType(),如果没有调用该方法,内容类型将使用默认值text/html,即HTML文档。
可以调用响应对象response的setCharacterEncoding()设置响应的字符编码.如果没有指定响应的字符编码,PrintWriter将使用ISO-8859-1编码。
如果不使用默认的响应的内容类型和字符编码,应该先调用响应的setContentType(),然后再调用getWriter()或getOutputStream()获得输出流对象。
4.什么是ServletContext对象,它的生存周期如何?
Web容器在启动时会加载每个Web应用程序,并为每个Web应用程序创建一个唯一的ServletContext实例对象,该对象称为Servlet上下文对象。
ServletContext是一个作用域对象,使用它可以存储数据,它的作用域是整个应用程序。5. ServletContext与ServletRequest的getRequestDispatcher()方法有什么区别?
区别是:对ServletContext的getRequestDispatcher()只能传递以”/”开头的路径,而对ServletRequest的getRequestDispatcher(),可以传递一个相对路径。
Servlet技术及应用实验报告
一、实验目的
1. 掌握如何获得请求参数;
2. 掌握如何检索请求头;
3. 了解如何通过请求对象获得客户信息;
4. 重点掌握使用请求对象存储数据和请求转发;
5. 掌握如何通过ServletConfig获取Servlet的初始化参数;
6. 掌握ServletContext的概念,如何获得ServletContext对象;
7. 掌握如何通过ServletContex对象的RequestDispatcher进行请求转发;
8. 了解Servlet的多线程问题及解决方法。
二、实验要求
1. 实验前进行预习,完成实验预习报告;
2.按照每一项实验内容进行上机实践与编程,将程序源代码和程序运行结果图附在实验报告中实验内容对应的部分。
3. 每次实验预习报告和实验报告打印装订成一份,左侧装订。
4. 每一次实验创建一个Web项目,每一项实验内容的源代码保存在该项目下,按目录组织保存好并压缩,按照老师指定的要求进行提交。代码保存方式如下:exp01表示实验一的Web项目的名称,其下保存各项实验内容的源文件及相关资源,将整个exp01文件夹进行压缩后命名为班级-姓名-实验1,如计算机181-张三-实验1。
三、实验原理
对客户的请求,容器根据请求调用Servlet的相应doXxx()方法,该方法带有两个参数,一个是HttpServletRequest,一个是HttpServletResponse,它们分别表示请求对象和响应对象,它们是容器自动创建的两个对象。可以使用这两个接口定义的若干方法完成有关操作。
Web应用程序有严格定义的目录结构,它需要一个称为部署描述文件的文件web.xml来配置。对应用程序的每个Servlet,可以在web.xml中定义若干个初始化参数,然后通过ServletConfig对象获取这些参数。
ServletContext对象表示该应用程序的环境,通过该对象可以获得应用程序范围的初始化参数、容器版本信息、资源的URL、在其中存放共享数据以及登录日志等。
四、实验内容与步骤
1. 简单的综合应用,掌握Servlet将请求转发给另一个Servlet的方法。
【步骤1】创建一个名为input.html的HTML页面,其中包括一个表单,表单中包含两个文本域,分别供用户输入学号和姓名,该页面也包含提交和重置按钮。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body style="text-align:center"> <form action="FirstServlet" method="post"> <p>学号:<input type="text" name="sno" size="30"></p> <p>姓名:<input type="text" name="name" size=30></p> <input type="submit" value="提交"> <input type="reset" value="重置"> </form> </body> </html>
【步骤2】 定义一个名为com.demo.Student类,其中包括学号sno和姓名name两个private的成员变量,定义访问和修改sno和name的方法。
package com.demo; public class Student { private String sno; private String name; public void setSno(String sno) { this.sno = sno; } public String getSno() { return sno; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Student(String sno,String name) { this.sno = sno; this.name = name; } }
【步骤3】编写名为FirstServlet的Servlet,要求当用户在input.html中输入信息后点击“提交”按钮,请求FirstServlet对其处理。在FirstServlet中使用表单提交的请求参数(学号和姓名)创建一个Student对象并将其作为属性存储在请求作用域中,然后通过请求对象的getRequestDispatcher()方法获得RequestDispatcher()对象,将请求转发到SecondServlet。
package com.demo; import java.io.IOException; import javax.security.auth.message.callback.PrivateKeyCallback.Request; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/FirstServlet") public class FirstServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub req.setCharacterEncoding("utf8"); String sno=req.getParameter("sno"); String name=req.getParameter("name"); Student student=new Student(sno, name); req.setAttribute("student", student); RequestDispatcher requestDispatcher=req.getRequestDispatcher("/SecondServlet"); requestDispatcher.forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }
package com.demo; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/SecondServlet") public class SecondServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub resp.setContentType("text/html;charset=UTF-8"); Student student=(Student)req.getAttribute("student"); System.out.println(student); PrintWriter printWriter=resp.getWriter(); printWriter.println("学号"+student.getSno()+"<br/>"); printWriter.println("姓名"+new String(student.getName()+"<br/>")); resp.setHeader("Refresh","5;url=input.html"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }
图2.1 input.html页面显示结果
图2.2 SecondServlet显示结果
2. 编写一个Servlet,显示所有请求头信息:
【步骤1】在exp01项目下编写一个名为ShowHeadersServlet.java的Servlet程序,使其能够检索所有的请求头,并且能够以表格的形式将请求头的参数名和参数值显示出来。
package com.demo; import java.io.IOException; import java.io.PrintWriter; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/ShowHeadersServlet") public class ShowHeadersServlet extends HttpServlet { private static final long serialVersionUID = 1L; public ShowHeadersServlet() { super(); // TODO Auto-generated constructor stub } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub response.setContentType( "text/html;charset=UTF-8"); PrintWriter out=response.getWriter(); out.print( "<html><head>"); out.print( "<head><title>HTTP Header</ head></title>");out.print( "<body>"); out.print( "<table border=\"1\">"); out.print( "<tr><td>Header名称</td>"); out.print( "<td>Header值</td></tr>"); Enumeration <String> headers=request.getHeaderNames(); while(headers.hasMoreElements()){ String paramName = ( String)headers.nextElement(); out.print( "<tr><td>" + paramName+"  "+ "</td>\n"); String paramValue = request.getHeader(paramName); out.println("<td> " + paramValue +"  "+ "</td></tr>\n"); } out.print( "</table></body></ html>"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
【步骤2】在浏览器地址栏中输入正确的URL,访问并测试该Servlet。
3. 编写一个名为ExcelServlet的Servlet程序,通过设置响应内容类型和输出流,向客户端浏览器响应一个带数据的Excel电子表格,程序的运行结果要求如下图所示。
package com.demo; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/ExcelServlet") public class ExcelServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub resp.setContentType("application/vnd.ms-excel;charset=GB2312"); req.setCharacterEncoding("utf-8"); Students s1=new Students("95001","李勇","男",20,"信息"); Students s2=new Students("95002","刘晨","女",19,"数学"); PrintWriter wr=resp.getWriter(); wr.println("学号\t"+"姓名\t"+"性别\t"+"年龄\t"+"所在系\t"); wr.println(s1.getSno()+"\t"+s1.getName()+"\t"+s1.getSex()+"\t"+s1.getAge()+"\t"+s1.getType()); wr.println(s2.getSno()+"\t"+s2.getName()+"\t"+s2.getSex()+"\t"+s2.getAge()+"\t"+s2.getType()); } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }
图3.1 生成Excel电子表格
4. 使用ServletConfig检索Servlet的初始化参数。
【步骤1】编写ConfigDemoServlet程序,通过注释为其添加初始化参数email、telephone,在Servlet中读取该servlet的名称和初始化参数email、telephone,并将这两个参数的值在响应的HTML文本中输出。
package com.demo; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet( urlPatterns = { "/configDemo.do" }, initParams = { @WebInitParam(name = "email", value = "hacker@163.com"), @WebInitParam(name = "telephone", value = "8899123") }) public class ConfigDemoServlet extends HttpServlet { String servletName = null; ServletConfig config = null; String email = null; String telephone = null; public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub this.config = config; servletName = config.getServletName(); email = config.getInitParameter("email"); telephone = config.getInitParameter("telephone"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<html><body>"); out.println("Servlet名称:"+servletName+"<br>"); out.println("Email地址:"+email+"<br>"); out.println("电话:"+telephone); out.println("</body></html>"); } }
【步骤2】在浏览器的地址栏中输入下面URL请求该Servlet:
http://localhost:8080/ exp01/configDemo.do
要求程序的运行结果如下图所示:
图4.1 ConfigDemoServlet程序的运行结果
5. 为ServletContext配置初始化参数并进行访问。
在web.xml文件中为当前web应用添加两个名为admin-email和admin-tel的ServletContext初始化参数,在ConfigDemoServlet中获取这两个参数的参数值,使用ServletContext对象将admin-email和admin-tel的参数值写入日志文件中,并查看日志文件。
Web.xml文件
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>chapter02</display-name> <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> <context-param> <param-name>admin-email</param-name> <param-value>小熊爱做实验吖@163.com</param-value> </context-param> <context-param> <param-name>admin-tel</param-name> <param-value>1123</param-value> </context-param> </web-app>
ServletContext类文件
package com.demo; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet( urlPatterns = { "/ServletContext" } ) public class ServletContext extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub PrintWriter out=response.getWriter(); javax.servlet.ServletContext context=getServletConfig().getServletContext(); String admin_Email=(String)context.getInitParameter("admin-email"); String admin_tel=(String)context.getInitParameter("admin-tel"); context.log(admin_tel); context.log(admin_Email); } }
6. 编写一个名为CountServlet的Servlet程序:
1)使用成员变量保存该Servlet被访问的次数,试打开多个浏览器窗口模拟多个用户同时访问该Servlet,观察该Servlet被访问次数的变化。
package com.demo; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/CountServlet") public class CountServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html; charset=utf-8"); javax.servlet.ServletContext servletContext = this.getServletContext(); Integer count=1; count++; PrintWriter out =response.getWriter(); out.print("<!DOCTYPE html>"); out.print("<html>"); out.print( "<head>"); out.print("<meta charset=\"UTF-8\">"); out.print("<title>登陆网页次数统计</title>"); out.print("</head>"); out.print("<body>"); out.print("<h1>"); out.print("欢迎光临小熊爱做实验吖的网页!(*╹▽╹*)<br/>您是第 "+ servletContext.getAttribute("count")+"位访客"); out.print("<h1>"); out.print("</body>"); out.print("</html>"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
2)修改该Servlet,通过ServletContext属性保存被多用户同时访问的次数,体会用ServletContext在应用作用域共享数据的方法。
package com.demo; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/CountServlet") public class CountServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html; charset=utf-8"); javax.servlet.ServletContext servletContext = this.getServletContext(); Integer count = (Integer) servletContext.getAttribute("count"); if( servletContext.getAttribute("count") == null) { count = 1; servletContext.setAttribute("count", count); }else { servletContext.setAttribute("count", count+1); } PrintWriter out =response.getWriter(); out.print("<!DOCTYPE html>"); out.print("<html>"); out.print( "<head>"); out.print("<meta charset=\"UTF-8\">"); out.print("<title>登陆网页次数统计</title>"); out.print("</head>"); out.print("<body>"); out.print("<h1>"); out.print("欢迎光临小熊爱做实验吖的网页!(*╹▽╹*)<br/>您是第 "+ servletContext.getAttribute("count")+"位访客"); out.print("<h1>"); out.print("</body>"); out.print("</html>"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
四、思考题
1. 请求中的参数如果是中文,如何正常显示中文参数值?
resp.setContentType("text/html;charset=UTF-8");或者req.setCharacterEncoding("utf8");要看具体是请求还是响应。
2. 使用RequestDispatcher的forward()方法转发请求和使用HttpServletResponse的sendRedirect()方法重定向请求有什么区别?
(1)RequestDispatcher.forward 方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。如果传递给HttpServletResponse.sendRedirect方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher 对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。
(2)调用HttpServletResponse.sendRedirect 方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;而调用 RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
(3)HttpServletResponse.sendRedirect 方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求。
(4)RequestDispatcher.forward 方法的调用者与被调用者之间共享相同的request 对象和response 对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect 方法调用者与被调用者使用各自的request 对象和response 对象,它们属于两个独立的访问请求和响应过程。
3. 什么是Web归档文件?如何为一个Web应用创建一个WAR文件?如何发布WAR文件?
Web归档文件:
相当于 windows 下保存网页为 web档案(.mht)的功能,即把页面上所有元素(文字、格式、图片等)都保存在硬盘上的一个特殊文件里边方便离线查看。保存下来由于是文件,所以除非人工删除,否则是永久保存的。
第一步:打开window下的dos窗口,(window+r再输入cmd回车)。
第二步:把dos窗口操作的目录定位到你的webapp所在的目录(先输入“cd\”进到c盘根目录,再输入“cd 复制你的目录的地址”后回车)。
第三步:在命令窗口中输入 “jar -cvf 应用名称.war 应用名称” 后回车,下面就会出现很多带有“存储了,压缩了”等字样的信息就表示成功了。
注意:(在命令窗口中输入 “jar -cvf 应用名称.war 应用名称”不同的关键字后面要空一个空格)。
第四步:前三步成功后你就可以在你的webapps所在目录下看到一个名为“应用名称.war”的文件。
第五步:因为war文件放到tomcat的webapps目录下,tomcat服务器一启动就会自动解压,所以比较方便。
4. 如何编写线程安全的Servlet?
使用ServletContext中属性参数。