Java 程序员面试笔试宝典 第 5 章 Java Web: 5.1 Servlet 与 JSP(1-8题)

5.1.1 页面请求的工作流程是怎样的

一个 Web 应用程序一般都是由客户端程序与服务器端程序两部分组成。其中,客户端主要是指用户和浏览器,用户可以通过浏览器查找所需的资源,而这些资源则位于服务器上。浏览器是一个工具软件,它主要有两个作用:一是完成与服务器端的交互;二是完成 HTML(Hyper-Text Markup Language,超文本标记语言,用来告诉浏览器怎样给用户展示内容)的解析,从而实现把用户需要查看的资源信息以直观的形式展现出来。服务器端用来接收客户端发来的请求,并对该请求进行处理,找到客户端请求的资源,最后把查找到的资源返回给客户端,这些资源主要包括 HTML 页面、图片、音频、视频、PDF 文件等内容。

1)用户通过浏览器输入链接地址来请求所需的资源。

2)浏览器接受用户的请求,并把该请求组装成指定的格式发送给服务器端,客户端与服务器端之间通过 HTTP 来完成具体的交互。其中请求的数据流中主要包含 HTTP(HyperText Transfer Protocol,超文本传输协议,建立在 TCP/IP 基础上的一个协议,主要用来实现客户端与服务器端之间的通信)请求方法(GET 或 POST)、请求的网址(URL,Uniform Resource Lo-cator,统一资源定位符)以及请求的一些参数信息。

3)服务器接收到客户端发来的请求,并查找用户所需要的资源。

4)服务器查找到用户请求的资源后,把该资源返回给客户端。

5)服务器通过把响应消息组装成特定的消息格式后返回给客户端,这个过程通过 HTTP 来完成。响应的数据流主要包含状态编码(代表请求成功或失败),Content-type(例如 text、picture、HTML 等),响应消息的内容(图片或 HTML 格式的内容)。

6)浏览器对 HTML 进行解析,并把响应结果展现给用户。


5.1.2 HTTP 中 GET 与 POST 方法有什么区别

HTTP 请求的方法有很多种类,例如 GET、POST、HEAD、TRACE、OPTIONS 等,但是 GET 与 POST 是两个最常用的方法。其中,GET 是最简单的一种请求方法,其主要功能是从服务器端获取用户所需资源,并将其作为响应返回给客户端,这些资源可以是 HTML 页面、图片、文档等内容中的任何一种,但需要注意的是,GET 方法的作用主要用来获取服务器端资源信息,就如同数据库中查询操作一样,不会影响到资源自身的状态,例如删除、修改或新增资源都是不允许的。而 POST 方法提供了比 GET 方法更强大的功能,它除了能够从服务器端获取资源外,同时还可以向服务器上传数据。

虽然 GET 方法主要用来从服务器上获取数据,也可以向服务器上传数据,但是一般不建议采用 GET 方法来向服务器上传数据,而是推荐使用 POST 方法实现该功能。具体而言,主要有以下两个方面原因:

1)采用 GET 方法向服务器上传数据时,一般将数据添加到 URL 后面,并且二者用「?」连接,各个变量之间用「&」连接。由于对 URL 的长度存在限制,因此采用这种方法能上传的数据量非常小,通常在 1024Byte 左右。而 POST 方法传递数据是通过 HTTP 请求的附件进行的,传送的数据量更大一些,一般默认为不受限制的。

2)由于 GET 方法上传的数据是添加在 URL 中的,因此上传的数据被彻底「暴露」出来了,本身存在安全隐患,尤其是当用户需要向服务器提交一些敏感信息时。而 POST 方法向服务器提交的内容在 URL 中并没有明文显示,对用户都是不可见的,所以,安全性更好一些。


5.1.3 什么是 Servlet

HTML 只能用来保存静态内容,而通常情况下,静态页面很难满足实际应用的需要,鉴于此,动态页面的概念被引入。所谓动态页面,指的是能够根据不同时间、不同用户而显示不同内容的页面,例如常见的论坛、留言板、电子商务网站等都是通过动态页面来实现的。那么如何才能生成动态页面呢?其中一种方法是采用公共网关接口(Common Gateway Interface,CGI)。CGI 是一种用 Perl 脚本编写的程序,可以用来生成动态页面,而另一种方式则是采用 Servlet 技术

什么是 Servlet 呢?Servlet 是采用 Java 语言编写的服务器端程序,它运行于 Web 服务器中的 Servlet 容器中,其主要功能是提供请求/响应的 Web 服务模式,可以生成动态的 Web 内容,而这正是 HTML 所不具备的功能。

与其他生成动态页面的技术相比,Servlet 有诸多优点,具体而言,主要表现在如下几个方面:

1)较好的可移植性。由于 Java 语言具有跨平台和可移植性强的特点,使得 Servlet 也有较好的可移植性,即无需修改代码就可以部署到多种不同类型的 Web 服务器上。

2)执行效率高。由于 CGI 针对每个请求都会创建一个进程来处理,而 Servlet 针对每个请求创建一个线程来执行,而创建线程比创建进程的开销要小,因此与 CGI 相比,Servlet 在交互过程中有更短的响应时间,响应效率更高。

3)使用方便。Servlet 提供了许多非常有用的接口以用来读取或设置 HTTP 头消息,处理 Cookie 和跟踪会话状态等。

4)可扩展性强。由于 Servlet 是用 Java 语言编写的,因此它具备了 Java 语言的所有优点。Java 语言是健壮的、面向对象的编程语言,它很容易扩展,Servlet 自然也具备这样的优点。

从以上 Servlet 的程序结构中可以看出,在 Servlet 中,并没有 main()方法,连所谓的入口方法都没有,那么它到底是如何执行的呢?其实,它是在容器的控制下执行的,常被使用的容器为 Tomcat。当 Web 服务器获取到一个对 Servlet 的请求时,该服务器将会把这个请求交给对应的容器来处理,容器通过调用 Servlet 的方法(doGet()或 doPost())来响应客户端的请求。

具体而言,Servlet 处理客户端请求有如下几个步骤:

1)用户通过单击一个链接来向 Servlet 发起请求。

2)Web 服务器接收到该请求后,会把该请求交给相应的容器来处理,当容器发现这是对 Servlet 发起的请求后,容器此时会创建两个对象:HttpServletResponse 和 HttpServletRequest。

3)容器可以根据请求消息中的 URL 消息找到对应的 Servlet,然后针对该请求创建一个单独的线程,同时把第 2)步中创建的两个对象以参数的形式传递到新创建的线程中。

4)容器调用 Servlet 的 service()方法来完成对用户请求的响应,service()方法会调用 doPost()或 doGet()方法来完成具体的响应任务,同时把生成的动态页面返回给容器。

5)容器把响应消息组装成 HTTP 格式返回给客户端。此时,这个线程运行结束,同时删除第 2)步创建的两个对象。

以上处理流程如图 5-2 所示。

容器会针对每次请求创建一个新的线程进行处理,同时会针对每次请求创建 HttpServletRe-sponse 和 HttpServletRequest 两个对象。处理完成后线程也就退出了。

5.1.4 doPost()方法与 doGet()方法怎么选择

从 Web 容器处理 HTTP 请求的流程中可以看出,最终的请求都会交给 Servlet 来处理,而 Servlet 是通过调用 service()方法来处理请求的,service()方法会根据不同的请求类型分别调用 doPost()方法(用于处理 POST 请求)或 doGet()方法(用于处理 GET 请求)来处理用户请求,实现对客户的响应。如果请求是 GET,就调用 doGet()方法;如果请求是 POST,就调用 doPost()方法。在 Servlet 接口和 GenericServlet(一个通用的、不特定于任何协议的 Servlet,它实现了 Servlet 接口)中是没有 doGet()方法与 doPost()方法的,而 HttpServlet 中定义了这些方法,但是都是返回 error 信息,所以,当定义一个 Servlet 时,都必须实现 doGet()方法或 doPost()方法。doGet 和 doPost 都接受请求(HttpServletRequest)和响应(HttpServletResponse)。

具体而言,当 HTTP 请求中的 method 属性为 get 时,调用 doGet()方法;当 method 属性为 post 时,则调用 doPost()方法。


5.1.5 什么是 Servlet 的生命周期

由于 Servlet 运行在容器中,没有 main()方法,因此,整个生命周期都是由容器来控制的。简单而言,Servlet 的生命周期只有两个状态:未创建状态与初始化状态。这两种状态的转换主要是由 3 个重要的方法来进行控制:init()、service()和 destroy()。其中,init()方法是 Servlet 生命的起点,用于创建或打开任何与 Servlet 相关的资源以及执行初始化工作。service()方法是 Servlet 中真正处理客户端传过来的请求的方法,它根据 HTTP 请求方法(GET、POST 等)将请求分发到 doGet()、doPost()等方法。destroy()方法释放任何在 init()方法中打开的与 Servlet 相关的资源。

具体而言,Servlet 的生命周期可以分为加载、创建、初始化、处理客户请求和卸载 5 个阶段。

1)加载。容器通过类加载器使用 Servlet 类对应的文件来加载 Servlet。

2)创建。通过调用 Servlet 的构造函数来创建一个 Servlet 实例。

3)初始化。通过调用 Servlet 的 init()方法来完成初始化工作,这个方法是在 Servlet 已被创建但向客户端提供服务之前调用的,需要注意的是,init()方法只会被调用一次。

4)处理客户请求。Servlet 一旦被创建后,它就可以为客户端提供服务了。每当有新的客户请求到来时,容器都会创建一个新的线程来处理该请求,接着会调用 Servlet 的 service()方法来完成客户端的请求,当然,service()方法会根据请求的 method 属性值的不同调用决定是调用 doGet()方法还是调用 doPost()方法来完成具体的响应。

5)卸载。容器在卸载 Servlet 之前需要调用 destroy()方法,让 Servlet 自己释放其占用的系统资源,一旦 destroy 方法被调用,容器就不会再向这个 Servlet 发送任何请求消息了。如果容器需要这个 Servlet,那么就必须重新创建并初始化一个实例。需要注意的是,destroy()方法只会被调用一次。


5.1.6 JSP 有哪些优点

JSP 的引入在一定程度上解决了 Servlet 存在的缺点。其实现理念是让每个 Servlet 只负责其对应的业务逻辑的处理,让 JSP 来负责用户的 HTML 显示,因此实现了业务逻辑与视图实现的分离,从而极大地提高了系统的可扩展性。

5.1.7 JSP 与 Servlet 有何异同

JSP 与 Servlet 的相同点为:JSP 可以被看作一个特殊的 Servlet,它只不过是对 Servlet 的扩展,只要是 JSP 可以完成的工作,使用 Servlet 都可以完成,例如生成动态页面。由于 JSP 页面最终要被转换成 Servlet 来运行,因此处理请求实际上是编译后的 Servlet。

JSP 与 Servlet 的不同点为:①Servlet 的实现方式是在 Java 中嵌入 HTML 代码,编写和修改 HTML 非常不方便,所以它比较适合做流程控制、业务处理;而 JSP 的实现方式为在 HTML 中嵌入 Java 代码,比较适合页面的显示,例如,在 Struts 框架中,Servlet 位于 MVC 设计模式的控制层,而 JSP 位于视图层。②Servlet 中没有内置对象,JSP 中的内置对象都是必须通过 HttpServletRequest 对象、HttpServletResponse 对象以及 HttpServlet 对象得到。


5.1.8 如何使用 JSP 与 Servlet 实现 MVC 模型

MVC 是 Model(模型)、View(视图)和 Controller(控制器)3 个单词的首字母组合。MVC 是一种目前广泛流行的应用模型,其目的是实现 Web 系统的职能分工。图 5-4 为 MVC 模型关系图,其中模型层实现系统中的业务逻辑,通常可以用 JavaBean 或 EJB 来实现;视图层则用于与用户的交互,通常用 JSP 来实现;控制层则是模型与视图之间沟通的桥梁,它可以把用户的请求分派并选择恰当的视图来显示它们,同时它也可以解释用户的输入并将其映射为模型层能够执行的操作。

MVC 强制性地分离 Web 应用的输入、处理和输出,使得 MVC 应用程序被分成 3 个核心部件:模型、视图和控制器。它们各自处理自己的任务。

(1)模型(业务逻辑层)

模型表示企业数据和业务逻辑,它是应用程序的主体部分。业务流程的处理过程对其他层来说是黑箱操作,模型接收视图请求数据,并返回最终的处理结果。业务模型的设计可以说是 MVC 最主要的核心。目前流行的 EJB 模型就是一个典型的应用例子,它从应用技术实现的角度对模型做了进一步的划分,以便充分利用现有的组件,但它不能作为应用设计模型的框架。它仅仅告诉设计人员按这种模型设计就可以利用某些技术组件,从而减少了技术上的困难,可以使设计人员专注于业务模型的设计。

MVC 把应用的模型按一定的规则抽象出来。抽象的层次很重要,这也是判断设计人员是否优秀的主要依据。抽象与具体不能隔得太远,也不能太近。MVC 并没有提供模型的设计方法,而只告诉设计人员应该如何组织管理这些模型,以便于模型的重构和提高重用性。

业务模型还有一个很重要的模型那就是数据模型。数据模型主要指实体对象的数据持续化,比如将一张订单保存到数据库,从数据库获取订单,将这个模型单独列出,所有相关数据库的操作只限制在该模型中。

(2)视图(表示层)

视图是用户看到的并与之交互的界面。对早期的 Web 应用来说,视图就是由 HTML 元素组成的界面,在新式的 Web 应用中,HTML 依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括 Adobe Flash 以及诸如 XHTML、XML/XSL 等一些标识语言和 Web 服务等。

随着 Web 应用开发技术的发展,用户要求的日益提高,如何处理应用程序的界面已经变得越来越有挑战性。MVC 架构一个大的好处是它能为 Web 应用处理很多不同的视图。在视图中其实没有真正的业务处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。

视图功能强大,主要表现在以下两个方面:

1)根据客户类型显示信息。

2)显示商业逻辑(模型)的结构,而不关心信息如何获得何时获得。

(3)控制器

控制器接收用户的输入并调用模型和视图去完成用户的需求。所以当用户单击 Web 页面中的超链接和发送 HTML 表单时,控制器(例如 Servlet)本身不输出任何东西,也不执行任何处理,它只是接收请求并决定调用哪个模型构件去处理请求,然后确定用哪个视图来显示模型处理返回的数据。

MVC 的处理过程是这样的:对于每一个用户输入的请求,先被控制器接收,并决定由哪个模型来进行处理,然后模型通过业务逻辑层处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过显示页面呈现给用户。

MVC 这种特殊的设计结构,给应用开发带来了很多便利,通过使用 MVC 架构,大大提高了 Web 应用的开发效率,具体来说,MVC 设计结构主要有以下几个方面的优点:

1)低耦合性。由于视图层和业务层分离,这样就使得修改视图层代码时不需要重新编译模型和控制器的代码,同样,一个应用的业务流程或者业务规则的改变只需要改动 MVC 的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。

2)高重用性和可适用性。由于技术的不断进步,现在访问应用程序可以有越来越多的方式。MVC 模式允许使用各种不同样式的视图来访问同一个服务器端的代码。它包括任何 Web(HTTP)浏览器或者无线浏览器(WAP),例如,用户可以通过计算机或手机来订购某样产品,虽然订购的方式不一样,但处理订购产品的方式是一样的。由于模型返回的数据没有进行格式化,因此同样的构件能被不同的界面使用,例如,很多数据可能用 HTML 来表示,但是也有可能用 WAP 来表示,而这些表示所需要的命令仅是改变视图层的实现方式,而控制层和模型层无需做任何改变。

3)较低的生命周期成本。MVC 使得开发和维护用户接口的技术难度降低。

4)部署快速。使用 MVC 模式可以大大缩减开发时间,这使得后台开发人员集中精力于业务逻辑上,使界面开发人员(包括 HTML 和 JSP 开发人员)集中精力于表现形式上。

5)可维护性。分离视图层和业务逻辑层也使得 Web 应用更易于维护和修改。

6)有利于软件工程化管理。由于采用了分层思想,每一层不同的应用具有某些相同的特征,有利于通过工程化、工具化管理程序代码。

用 JSP 与 Servlet 实现的 MVC 模型如图 5-5 所示。

在这个 MVC 模型中,视图模块采用 JSP 来实现,主要负责数据的展现。视图可以从控制器上获取模型的状态,当然不是直接从控制器上获取,而是控制器把模型的数据放到一个视图可以访问的地方,通过间接方式来访问模型的数据。控制器采用 Servlet 来实现,客户端的所有请求都发送给 Servlet,它接收请求,并根据请求消息把它们分发给对应的 JSP 页面来响应,同时根据需求生成 JavaBean 实例供 JSP 来使用。模型采用 JavaBean 来实现,这个模块实现了实际的业务逻辑。

发布了101 篇原创文章 · 获赞 20 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_40993412/article/details/104066398