2020.12.16

一、今日学习内容:

今天主要是对servlet的系统性总结:

Servlet
6.1.1 什么是 Servlet
从完成的功能上来说,Servlet 与 JSP 完全一样。但是,从编写的角度来说是不一样的:
JSP是在HTML或者XML文档中嵌入Java脚本或者JSP标签形成的,是文本文件;而Servlet
是纯 Java 文件,是一个类。所有使用 Servlet 完成的功能,包括与用户的交互,都是通过 Java
代码完成的。
Servlet 是用 Java 语言编写的运行在服务器端的小应用程序,能够接收 Web 客户端的请
求,并能对 Web 客户端进行响应,通常是通过 HTTP(HyperText Transfer Protocol)协议进
行工作的。
可以认为 Servlet 是服务器端的 Applet(实际上,Applet 运行在客户端,而 Servlet 运行
在服务器端)。
6.1.2 Servlet 的主要方法
Servlet 是一个 Java 类,通常会有三类方法,分别是:
(1) init 方法,用于初始化。
(2) destroy 方法,用于释放资源。
(3) service 方法(服务类方法),对用户的请求进行处理,并对用户进行响应。几乎所有
处理功能都在这里完成。这类方法可以有多个,例如 doGet 和 doPost 等。doGet 方法可以响
应 get 方式的请求,doPost 方法可以响应 post 方式的请求。通常,表单提交都使用 post 方
式,超链接使用 get 方式。
除了上面的三个方法之外,还可以有其他的辅助方法,可以在上面的三个方法中调用
这些辅助方法。
6.1.3 编写简单的 Servlet
编写一个 Servlet 的完整过程包括:Servlet 的编写、编译、配置、部署以及访问。下面
通过一个实例来介绍这个过程。该实例完成的功能是向用户输出一行文字“Hello World!”。
1. 编写 Servlet
根据要完成的功能来编写 Servlet。功能确定之后,根据 Servlet 的框架来编写 Servlet。
这里主要关注编写 Servlet 的一般过程。
因为 Servlet 是 Java 类,所以它与一般的 Java 类的编写基本相同。具体步骤如下:
(1) 创建一个包。假设包名是 servlets,创建包的代码如下:
package servlets;
(2) 导入用到的包。需要导入的包有 javax.servlet.*和 javax.servlet.http.*,通常还需要导
入的包是 java.io.*。代码如下:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
(3) 定义类的基本框架并继承 HttpServlet。每个 Servlet 都必须实现接口 Servlet,而这
里要编写的 Servlet 主要是用于 HTTP 协议的,可以继承实现了 Servlet 接口的 HttpServlet。
代码如下:
public class HelloServlet extends HttpServlet
{
}
(4) 编写成员方法。Servlet 通常不需要成员变量,成员方法包括 init、service、destroy
等。如果需要对 Servlet 进行初始化,则需要实现 init 方法。如果需要在卸载 Servlet 的时候
执行一些功能,则需实现 destory 方法。一般情况下,根据需要完成的功能只需要实现服务
类方法即可。这里只实现 doGet 方法。服务类方法有两个参数:第一个参数是
HttpServletRequest 的对象,该参数包含了用户的所有请求信息,要想获取用户的请求信息,
必须使用该对象提供的方法;第二个参数是 HttpServletResponse 的对象,可以通过这个对
象对用户进行响应,如果希望对用户进行响应或者设置响应相关的信息,需要使用该对象
的方法。
该实例完成的功能是向用户输出一行文字,所以不需要获取用户的请求信息,只需要
对用户进行响应即可。在对用户进行响应的时候,需要设定文档类型以及编码方式等,就
像在 JSP 中每个文件都要设置 page 标签的 contentType 属性一样。之后要向用户输出一些内
容,需要先获取输出流。响应页面的属性设置和输出流的获取都是与响应相关的,需要使
用第二个参数来完成。
代码如下:

public void doGet(HttpServletRequest request,HttpServletResponse)
throws IOException,ServletException
{
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>Hello World!</title></head>");
out.println("<body>");
out.println("<p>Hello World!</p>");
out.println("</body></html>");
}


从代码可以看出,如果使用 Servlet 完成对用户的响应,所有的响应内容,包括格式信
息等都要通过输出语句进行输出。要是使用 JSP 完成这个功能,就非常简单了。正因为这
个原因,才推出了 JSP 技术,JSP 技术的主要优势就在于与用户进行交互比较方便。所以,
如果要完成的功能是与用户进行交互,则应该使用 JSP 完成。在本书的后续内容中,使用
Servlet 技术主要完成控制功能。
为了使这个 Servlet 能够响应 post 请求,需要实现 doPost 方法,这时只需要调用 doGet
方法即可。代码如下:

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doGet(request, response);
}


需要把这两个方法添加到前面定义的类 HelloServlet 中。
2. 编译 Servlet
Servlet 开发所需要的包有 javax.servlet.*和 javax.servlet.http.*。这些包不是 Java 标准版
的类库,如果没有安装 Java EE 开发环境,则需要配置环境变量。这些包位于 tomcat 安装
目录下的 lib 下的 servlet-api.jar 压缩包中,需要把这个压缩包添加到环境变量中。
假设 servlet-api.jar 所在的位置为 C:Program FilesApache Software FoundationTomcat
6.0lib,需要在环境变量classpath中添加C:Program FilesApache Software FoundationTomcat
6.0libservlet-api.jar。
注意:不要删除 classpath 中原来的信息,如果不存在 classpath 环境变量,可以创建一
个 classpath。
环境变量设置好之后,使用 JDK 中的 javac 命令编译:
javac HelloServlet.java
3. 配置 Servlet
Servlet 编写完之后,作为 Web 应用的组成部分,需要在配置文件 web.xml 中进行配
置。Servlet 的配置包括两部分,第一部分是 Servlet 的声明,第二部分是 Servlet 访问方
式的设置。
首先是 Servlet 的声明,使用<servlet>元素:
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>servlets.HelloServlet</servlet-class>
</servlet>
<servlet-name>用于声明 Servlet 的名字,这里,hello 是 Servlet 的名字;<servlet-class>
用于声明 Servlet 所对应的类,这里,servlets.HelloServlet 是这个 Servlet 所对应的类名。
注意:包名不能缺少。
然后是 Servlet 映射,主要配置访问该 Servlet 的方式,使用<servlet-mapping>元素:
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-name>表示Servlet的名字,需要和上面的Servlet声明保持一致;<url-pattern>
表示访问时候的格式,例如要访问上面这个 Servlet 需要使用 hello 作为名字访问。
servlet-name 和 url-pattern 可以不相同。服务器接收到请求之后会根据这个 url-pattern 查
找相应的 Servlet。
4. 部署 Servlet
Servlet 编写完成之后,需要部署到服务器才能访问,编译好的文件需要放在 Web 应用
的 WEB-INFclasses 下面。
5. 访问 Servlet
对 Servlet 的访问与对 JSP 的访问基本相同,可以通过以下三种方式进行:
98 Java Web 程序设计基础教程
(1) 通过在浏览器中直接输入地址访问:
http://127.0.0.1:8080/test/hello
(2) 通过超链接的形式访问:
<a href ="http://127.0.0.1:8080/test/hello">第一个 Servlet</a>
(3) 通过表单提交的方式访问:
<form method=get action="http://127.0.0.1:8080/test/hello">
6.1.4 Servlet 运行原理
图 6.1 显示了 Servlet 的运行原理:
(1) 服务器接收到客户端的请求时,先判断用户所请求的 Servlet 对象是否存在:
● 如果存在,则直接调用 Servlet 对象的 Service 方法(间接调用 doGet 方法或者 doPost
方法);
● 如果不存在,则加载 Servlet 类,创建 Servlet 对象并实例化,然后调用 init 方法进行
初始化,之后调用 Servlet 对象的 Service 方法。
(2) 使用 service 方法执行的结果对用户进行响应。
注意:在 Servlet 的生命周期中,同一个 Servlet 对象可以为多个客户端服务,多个客户
端之间的区别在于服务器为每个客户端创建的是不同的请求对象和响应对象,而执行的方
法是相同的。加载 Servlet 类、创建对象和调用初始化方法 init 都只有一次。
图 6.1 Servlet 的运行原理
在 Web 应用被卸载或者服务器被关闭的时候,系统卸载 Servlet,调用 destroy 方法释放
资源。
Servlet 的加载有两种方式:
● 第一次请求的时候加载。
● 服务器启动的时候加载。
第 6 章 系统流程控制 99
这两种方式各有利弊。如果第一次请求的时候加载,加载的速度比较慢,但是不浪费
空间。如果是启动服务器的时候加载,第一次访问的时候就快了,但是如果一直没有人访
问,则这段时间就浪费了空间。
加载 Servlet 的方式可以在 web.xml 中声明 Servlet 的时候配置。如果希望在启动的时候
加载 HelloServlet,可使用下面的代码声明:
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>servlets.HelloServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
6.2 使用 Servlet 完成控制
在本章开始的时候,我们讲过 Servlet 可以完成控制功能。那么 Servlet 如何来完成控制
功能呢?下面通过登录功能中的 Servlet 实现来介绍。
本节我们使用 Servlet 完成 process_login.jsp 文件所完成的功能,涉及的功能有:
● 接收用户的输入信息。
● 调用业务逻辑模型。
● 使用 request 存储执行的结果。
● 选择界面对用户进行响应。
这些功能都是在 dePost 方法或者 doGet 方法中完成的,所以要编写的这个 Servlet 的结
构与前面介绍的 HelloServlet 的结构基本一致,只是这里不需要输出。
6.2.1 接收用户的输入信息
在 Servlet 中,doPost 和 doGet 服务方法中都有一个参数是 HttpServletRequest 的对象,
用户的请求信息存放在该对象中,要获取用户提交的数据需要通过该对象获取。获取用户
请求信息的方法如下:
String getParameter(String name)
String[] getParamterValues(String name)
第一个方法用于获取单值表单元素的值,参数指出要获取的表单元素的名字。例如,用
户在输入用户编号的时候使用的表单元素的名字是 userid,要想获取用户在这个输入框中输
入的值,就可以使用下面的代码:
String userid = request.getParameter("userid");
如果参数指定的表单元素的名字不存在,则返回 null。所以通常在处理的时候,需要先
判断返回的结果是否为 null。
第二个方法用于获取多值表单元素的值,参数也是表单元素的名字,但是返回值是一
个数组。
100 Java Web 程序设计基础教程
注意:在使用的时候通常需要判断这个值是否为 null,如果是 null,就不能调用它的方
法了,否则将产生 java.lang.NullPointerException。
6.2.2 调用业务方法
因为 Servlet 是 Java 类,所以调用业务方法的代码就是我们在 Java 中学习的调用其他类
的方法。首先需要创建所使用的 JavaBean 的对象,然后再调用业务方法。
要使用 UserBean 对象,可以使用下面的代码:
UserBean user = new UserBean();
然后调用业务方法,代码如下:
boolean b = user.validate(userid,userpass);
注意:在使用 JavaBean 的时候,需要引入它所在的包。
6.2.3 使用 request 存储执行的结果
Servlet 完成控制的功能,查询的结果通过视图(JSP 文件)显示,需要把查询的结果传递
给 JSP 文件。因为打开这两个文件属于同一次请求,所以共享同一个 request。因为共享同
一个 request,所以在 Servlet 中把查询结果存储在 request 中,然后在视图中显示结果。
在登录功能中不需要传递信息。假设需要把使用 temp 对象保存的查询结果传递到视图,
可以使用下面的代码:
request.setAttribute("user",temp);
第一个参数表示信息的名字,第二个参数存储对象本身,在视图中会根据名字获取。
6.2.4 选择界面对用户进行响应
Servlet 中的最后一项任务就是跳转到显示界面,在显示界面显示信息。在 JSP 中要重
定向到某个文件,可以使用<jsp:forward>标签。那么在 Servlet 中如何完成这种跳转呢?在
Servlet 中提供了一个 RequestDispatcher 接口,通过这个接口可以完成重定向功能。
要 使 用 RequestDispatcher , 需 要 先 创 建 该 类 的 对 象 , 可 以 通 过 request 的
getRequestDispatcher 方法创建。该方法需要一个 String 类型的参数,该参数指定要转向的
文件。假设要转向 userlist.jsp,可以使用下面的代码:
RequestDispatcher rd=request.getRequestDispatcher("userlist.jsp");
要完成转向,还需要调用一个方法,用法如下:
rd.forward(request,response);
在学习<jsp:forward>标签的时候,还学习过一个标签<jsp:include>。<jsp:include>标签对
应的功能在 Servlet 中的实现也是通过上面的 RequestDispatcher 来实现的。例如现在要包含
userlist.jsp,而不是转向 success.jsp,可以使用下面的代码:
RequestDispatcher rd=request.getRequestDispatcher("success.jsp");
rd.include(request,response);
实际上,还有一个方法,即 response 对象的 sendRedirect 方法可以完成重定向的功能。
例如要转向 success.jsp,可以使用下面的代码:
response.sendRedirect("success.jsp");
但是对于我们当前的功能来说,不能使用这个方法,因为这个方法与上面介绍的方法
有一些区别。在使用 RequestDispatcher 的时候,当前文件和要转向的文件属于同一次请求,
可以共享 request 对象。而在使用 response 对象的 sendRedirect 方法的时候,当前文件和要
转向的文件不属于同一次请求,属于两次请求,所以不能共享 request。如果需要通过 request
对象传递信息,就不能使用 response 的 sendRedirect 方法。如果当前文件和要转向的文件不
需要共享任何信息,那么这时候两种方式都可以。

二、遇到的问题:

还是需要理解记忆。

三、明日学习计划:

继续学习javaweb。

原文地址:https://www.cnblogs.com/marr/p/14178081.html