Java Servlet学习笔记

Servlet是什么

Servlet 是 Server Applet 的缩写,译为“服务器端小程序”,是一种使用 Java 语言来开发动态网站的技术

  • Servlet 是 Sun 公司推出的一种基于 Java 的动态网站开发技术

  • 一个 Servlet 程序其实就是一个按照 Servlet 规范编写的 Java 类。Servlet 程序需要先编译成字节码文件(.class文件),然后再部署到服务器运行。

  • 现在没有人直接使用 Servlet 开发动态网站,大家都转向了 JSP 阵营。但是 JSP 依赖于 Servlet,用户访问 JSP 页面时,JSP 代码会被翻译成 Servlet 代码,最终,HTML 代码还是以字符串的形式向外输出的。您看,JSP 只是在 Servlet 的基础上做了进一步封装。JSP 代码可以调用 Servlet 类,程序员可以将部分功能在 Servlet 中实现,然后在 JSP 中调用即可。Servlet 是 JSP 的基础,Servlet 虽然不直接面向用户,但是它依然是 JSP 的后台支撑。

Servlet容器

  • Servlet 容器就是 Servlet 代码的运行环境(运行时),它除了实现 Servlet 规范定义的各种接口和类,为 Servlet 的运行提供底层支持,还需要管理由用户编写的 Servlet 类,比如实例化类(创建对象)、调用方法、销毁类等。举个例子:生活中容器用来装水、装粮食,Servlet 中的容器用来装类,装对象。

  • 可能会提出疑问,我们自己编写的 Servlet 类为什么需要 Servlet 容器来管理呢?这是因为我们编写的 Servlet 类没有 main() 函数,不能独立运行,只能作为一个模块被载入到 Servlet 容器,然后由 Servlet 容器来实例化,并调用其中的方法。

  • 一个动态页面对应一个 Servlet 类,开发一个动态页面就是编写一个 Servlet 类,当用户请求到达时,Servlet 容器会根据配置文件(web.xml)来决定调用哪个类。

用户的 HTTP 请求首先到达 Web 服务器,Web 服务器判断该请求是静态资源还是动态资源:如果是静态资源就直接返回,此时相当于用户下载了一个服务器上的文件;如果是动态资源将无法处理,必须将该请求转发给 Servlet 容器。

Servlet 容器接收到请求以后,会根据配置文件(web.xml)找到对应的 Servlet 类,将它加载并实例化,然后调用其中的方法来处理用户请求;处理结束后,Servlet 容器将处理结果再转交给 Web 服务器,由 Web 服务器将处理结果进行封装,以 HTTP 响应的形式发送给最终的用户。

Servlet三种创建方法

  1. 实现 javax.servlet.Servlet 接口,重写其全部方法。

  1. 继承 javax.servlet.GenericServlet 抽象类,重写 service() 方法。

  1. 继承 javax.servlet.http.HttpServlet 抽象类,重写 doGet() 或 doPost() 方法。

Servlet接口:

定义了五种方法:

返回值

方法

备注

void

init(ServletConfig config)

Servlet 实例化之后,由 Servlet 容器调用,用来初始化 Servlet 对象。该方法只能被调用一次。 参数 config 用来向 Servlet 传递配置信息。

void

service(ServletRequest req,ServletResponse res)

Servlet 容器调用该方法处理客户端请求。

void

destroy()

服务器关闭、重启或者 Servlet 对象被移除时,由 Servlet 容器调用,负责释放 Servlet 对象占用的资源。

ServletConfig

getServletConfig()

该方法用来获取 ServletConfig 对象,该对象中包含了 Servlet 的初始化参数。

String

getServletInfo()

该方法用于获取 Servlet 的信息,例如作者、版本、版权等。

GenericServlet 抽象类:

定义了四种方法:

返回值

方法

备注

String

getInitParameter(String name)

返回名字为 name 的初始化参数的值,初始化参数在 web.xml 中进行配置。如果参数不存在,则返回 null。

Enumeration

getInitParameterNames()

返回 Servlet 所有初始化参数的名字的枚举集合,若 Servlet 没有初始化参数,返回一个空的枚举集合。

ServletContext

getServletContext()

返回 Servlet 上下文对象的引用。

String

getServletName()

返回此 Servlet 实例的名称。

HttpServlet 抽象类

由于 Servlet 主要用来处理 HTTP 的请求和响应,所以通常情况下,编写的 Servlet 类都继承自 HttpServlet。

在 HTTP/1.1 协议中共定义了 7 种请求方式,即 GET、POST、HEAD、PUT、DELETE、TRACE 和 OPTIONS。

HttpServlet 针对这 7 种请求方式分别定义了 7 种方法,即 doGet()、doPost()、doHead()、doPut()、doDelete()、doTrace() 和 doOptions()。

@WebServlet 注解的使用

@WebServlet 属于类级别的注解,标注在继承了 HttpServlet 的类之上。常用的写法是将 Servlet 的相对请求路径(即 value)直接写在注解内,如下所示。

@WebServlet("/MyServlet") 

该写法省略了 urlPatterns 属性名,其完整的写法如下所示。

@WebServlet(urlPatterns = "/MyServlet")。

使用web.xml对Servlet进行配置:

web.xml 中各元素含义及用法如下:

  • : 根元素。

  • :用于注册 Servlet,即给 Servlet 起一个独一无二的名字。

  • 包含两个主要的子元素 和 ,分别用于指定 Servlet 的名称和 Servlet 的完整限定名(包名+类名)。

  • :用于定义 Servlet 与 URL 之间的映射。

  • 包含两个子元素 和 ,分别用于指定 Servlet 的名称和虚拟路径。

  • load-on-startup 是 web.xml 中的一个节点,是 servlet 元素的子元素,用来标记 Servlet 容器启动时是否初始化当前 Servlet,以及当前 Servlet 的初始化顺序。

load-on-startup 元素取值规则如下:

  1. 它的取值必须是一个整数;

  1. 当值小于 0 或者没有指定时,则表示容器在该 Servlet 被首次请求时才会被加载;

  1. 当值大于 0 或等于 0 时,表示容器在启动时就加载并初始化该 Servlet,取值越小,优先级越高;

  1. 当取值相同时,容器就会自行选择顺序进行加载。

Servlet生命周期

Servlet 生命周期流程如下图所示:

  • 初始化阶段:

  1. 加载和实例化 Servlet;

  1. 调用 init() 方法进行初始化。

  • 运行时阶段:

Servlet 容器接收到来自客户端请求时,容器会针对该请求分别创建一个 ServletRequst 对象和 ServletResponse 对象,将它们以参数的形式传入 service() 方法内,并调用该方法对请求进行处理。

这里需要注意的是,执行 service() 方法前,init() 方法必须已成功执行。

在 service() 方法中,Servlet 通过 ServletRequst 对象获取客户端的相关信息和请求信息。在请求处理完成后,通过 ServletResponse 对象将响应信息进行包装,返回给客户端。当 Servlet 容器将响应信息返回给客户端后,ServletRequst 对象与 ServletResponse 对象就会被销毁。

在 Servlet 的整个生命周期内,对于 Servlet 的每一次请求,Servlet 容器都会调用一次 service() 方法,并创建新的 ServletRequest 和 ServletResponse 对象。

  • 销毁阶段:

当 Servlet 容器关闭、重启或移除 Servlet 实例时,容器就会调用 destory() 方法,释放该实例使用的资源,例如:关闭数据库连接,关闭文件的输入流和输出流等,随后该实例被 Java 的垃圾收集器所回收。

对于每个 Servlet 实例来说,destory() 方法只能被调用一次。

Servlet虚拟路径匹配规则

下面我们以 servletDemo 为例,分别介绍 4 种规则。

匹配规则

使用规则

虚拟路径

可访问的URL

完全路径匹配 (精确匹配)

以/开始,不能包含通配符* 。 必须完全匹配

/myServlet /user/myServlet /product/index.action

http://localhost:8080/servletDemo/myServlet http://localhost:8080/servletDemo/user/myServlet http://localhost:8080/servletDemo/product/index.action

目录匹配

以/字符开头,并以/*结尾的字符串。 用于路径匹配

/user/* /*

http://localhost:8080/servletDemo/user/aaa http://localhost:8080/servletDemo/aa

扩展名匹配

以通配符*.开头的字符串。 用于扩展名匹配

*.do *.action *.jsp

http://localhost:8080/servletDemo/user.do http://localhost:8080/servletDemo/myServlet.action http://localhost:8080/servletDemo/bb.jsp

缺省匹配(默认匹配)

映射路径为/,表示这个 Servlet 为当前应用的缺省 Servlet 或默认 Servlet,默认处理无法匹配到虚拟路径的请求。

/

可以匹配任意请求 URL

HttpServletRequest接口

Servlet 处理 HTTP 请求的流程如下:

  1. Servlet 容器接收到来自客户端的 HTTP 请求后,容器会针对该请求分别创建一个 HttpServletRequest 对象和 HttpServletReponse 对象。

  1. 容器将 HttpServletRequest 对象和 HttpServletReponse 对象以参数的形式传入 service() 方法内,并调用该方法。

  1. 在 service() 方法中 Servlet 通过 HttpServletRequest 对象获取客户端信息以及请求的相关信息。

  1. 对 HTTP 请求进行处理。

  1. 请求处理完成后,将响应信息封装到 HttpServletReponse 对象中。

  1. Servlet 容器将响应信息返回给客户端。

  1. 当 Servlet 容器将响应信息返回给客户端后,HttpServletRequest 对象和 HttpServletReponse 对象被销毁。

HTTP 请求消息分为请求行、请求消息头和请求消息体三部分,所以 HttpServletRequest 接口中定义了获取请求行、请求头和请求消息体的相关方法。

获取请求行信息

HTTP 请求的请求行中包含请求方法、请求资源名、请求路径等信息,HttpServletRequest 接口定义了一系列获取请求行信息的方法,如下表。

返回值类型

方法声明

描述

String

getMethod()

该方法用于获取 HTTP 请求方式(如 GET、POST 等)。

String

getRequestURI()

该方法用于获取请求行中的资源名称部分,即位于 URL 的主机和端口之后,参数部分之前的部分。

String

getQueryString()

该方法用于获取请求行中的参数部分,也就是 URL 中“?”以后的所有内容。

String

getContextPath()

返回当前 Servlet 所在的应用的名字(上下文)。对于默认(ROOT)上下文中的 Servlet,此方法返回空字符串""。

String

getServletPath()

该方法用于获取 Servlet 所映射的路径。

String

getRemoteAddr()

该方法用于获取客户端的 IP 地址。

String

getRemoteHost()

该方法用于获取客户端的完整主机名,如果无法解析出客户机的完整主机名,则该方法将会返回客户端的 IP 地址。

获取请求头信息

当浏览器发送请求时,需要通过请求头向服务器传递一些附加信息,例如客户端可以接收的数据类型、压缩方式、语言等。为了获取请求头中的信息, HttpServletRequest 接口定义了一系列用于获取 HTTP 请求头字段的方法,如下表所示。

返回值类型

方法声明

描述

String

getHeader(String name)

该方法用于获取一个指定头字段的值。 如果请求消息中包含多个指定名称的头字段,则该方法返回其中第一个头字段的值。

Enumeration

getHeaders(String name)

该方法返回指定头字段的所有值的枚举集合, 在多数情况下,一个头字段名在请求消息中只出现一次,但有时可能会出现多次。

Enumeration

getHeaderNames()

该方法返回请求头中所有头字段的枚举集合。

String

getContentType()

该方法用于获取 Content-Type 头字段的值。

int

getContentLength()

该方法用于获取 Content-Length 头字段的值 。

String

getCharacterEncoding()

该方法用于返回请求消息的字符集编码 。

获取 form 表单的数据

在实际开发中,我们经常需要获取用户提交的表单数据,例如用户名和密码等。为了方便获取表单中的请求参数,ServletRequest 定义了一系列获取请求参数的方法,如下表所示。

返回值类型

方法声明

功能描述

String

getParameter(String name)

返回指定参数名的参数值。

String [ ]

getParameterValues (String name)

以字符串数组的形式返回指定参数名的所有参数值(HTTP 请求中可以有多个相同参数名的参数)。

Enumeration

getParameterNames()

以枚举集合的形式返回请求中所有参数名。

Map

getParameterMap()

用于将请求中的所有参数名和参数值装入一个 Map 对象中返回。

Servlet请求转发

请求转发的工作原理

在 Servlet 中,通常使用 forward() 方法将当前请求转发给其他的 Web 资源进行处理。请求转发的工作原理如下图所示。

request 域对象

request 是 Servlet 的三大域对象之一,它需要与请求转发配合使用,才可以实现动态资源间的数据传递。

在 ServletRequest 接口中定义了一系列操作属性的方法,如下表。

返回值类型

方法

描述

void

setAttribute(String name, Object o)

将 Java 对象与属性名绑定,并将它作为一个属性存放到 request 对象中。参数 name 为属性名,参数 object 为属性值。

Object

getAttribute(String name)

根据属性名 name,返回 request 中对应的属性值。

void

removeAttribute(String name)

用于移除 request 对象中指定的属性。

Enumeration

getAttributeNames()

用于返回 request 对象中的所有属性名的枚举集合。

HttpServletResponse接口详解

Servlet 容器会针对每次请求创建一个 response 对象,并把它作为参数传递给 Servlet 的 service 方法。Servlet 处理请求后,会将响应信息封装到 response 对象中,并由容器解析后返回给客户端。

响应行相关的方法

当 Servlet 返回响应消息时,需要在响应消息中设置状态码。因此,HttpServletResponse 接口定义了发送状态码的方法,如下表。

返回值类型

方法

描述

void

setStatus(int status)

用于设置 HTTP 响应消息的状态码,并生成响应状态行。

void

sendError(int sc)

用于发送表示错误信息的状态码。

响应头相关的方法

HttpServletResponse 接口中定义了一系列设置 HTTP 响应头字段的方法,如下表所示。

返回值类型

方法

描述

void

addHeader(String name,String value)

用于增加响应头字段,其中,参数 name 用于指定响应头字段的名称,参数 value 用于指定响应头字段的值。

void

setHeader (String name,String value)

用于设置响应头字段,其中,参数 name 用于指定响应头字段的名称,参数 value 用于指定响应头字段的值。

void

addIntHeader(String name,int value)

用于增加值为 int 类型的响应头字段,其中,参数 name 用于指定响应头字段的名称,参数 value 用于指定响应头字段的值,类型为 int。

void

setIntHeader(String name, int value)

用于设置值为 int 类型的响应头字段,其中,参数 name 用于指定响应头字段的名称,参数 value 用于指定响应头字段的值,类型为 int。

void

setContentType(String type)

用于设置 Servlet 输出内容的 MIME 类型以及编码格式。

void

setCharacterEncoding(String charset)

用于设置输出内容使用的字符编码。

响应体相关的方法

由于在 HTTP 响应消息中,大量的数据都是通过响应消息体传递的。因此 ServletResponse 遵循以 I/O 流传递大量数据的设计理念,在发送响应消息体时,定义了两个与输出流相关的方法。

返回值类型

方法

描述

ServletOutputStream

getOutputStream()

用于获取字节输出流对象。

PrintWriter

getWriter()

用于获取字符输出流对象。

Servlet重定向

重定向的工作流程如下:

  1. 用户在浏览器中输入 URL,请求访问服务器端的 Web 资源。

  1. 服务器端的 Web 资源返回一个状态码为 302 的响应信息,该响应的含义为:通知浏览器再次发送请求,访问另一个 Web 资源(在响应信息中提供了另一个资源的 URL)。

  1. 当浏览器接收到响应后,立即自动访问另一个指定的 Web 资源。

  1. 另一 Web 资源将请求处理完成后,由容器把响应信息返回给浏览器进行展示。

Servlet Cookie的使用

会话技术

从打开浏览器访问某个网站,到关闭浏览器的过程,称为一次会话。会话技术是指在会话中,帮助服务器记录用户状态和数据的技术。

常用的会话技术分为两种:

  1. Cookie :客户端会话技术

  1. Session :服务端会话技术

本节将对 Cookie 进行介绍,下节将对 Session 进行介绍。

Cookie

Cookie 属于客户端会话技术,它是服务器发送给浏览器的小段文本信息,存储在客户端浏览器的内存中或硬盘上。当浏览器保存了 Cookie 后,每次访问服务器,都会在 HTTP 请求头中将这个 Cookie 回传给服务器。

Cookie 的分类

Cookie分为两种:

  1. 会话级别 Cookie(默认):Cookie 保存到浏览器的内存中,浏览器关闭则 Cookie 失效。

  1. 持久的 Cookie:Cookie 以文本文件的形式保存到硬盘上。

Cookie 的工作流程

Cookie 是基于 HTTP 协议实现的,工作流程如下。

  1. 客户端浏览器访问服务器时,服务器通过在 HTTP 响应中增加 Set-Cookie 字段,将数据信息发送给浏览器。

  1. 浏览器将 Cookie 保存在内存中或硬盘上。

  1. 再次请求该服务器时,浏览器通过在 HTTP 请求消息中增加 Cookie 请求头字段,将 Cookie 回传给 Web 服务器。服务器根据 Cookie 信息跟踪客户端的状态。

HttpServletResponse 接口和 HttpServletRequest 接口也都定义了与 Cookie 相关的方法,如下表所示。

方法

描述

所属接口

void addCookie(Cookie cookie)

用于在响应头中增加一个相应的 Set-Cookie 头字段。

javax.servlet.http.HttpServletResponse

Cookie[] getCookies()

用于获取客户端提交的 Cookie。

javax.servlet.http.HttpServletRequest

javax.servlet.http.Cookie 类中提供了一系列获取或者设置 Cookie 的方法,如下表。

返回值类型

方法

描述

int

getMaxAge()

用于获取指定 Cookie 的最大有效时间,以秒为单位。 默认情况下取值为 -1,表示该 Cookie 保留到浏览器关闭为止。

String

getName()

用于获取 Cookie 的名称。

String

getPath()

用于获取 Cookie 的有效路径。

boolean

getSecure()

如果浏览器只通过安全协议发送 Cookie,则返回 true;如果浏览器可以使用任何协议发送 Cookie,则返回 false。

String

getValue()

用于获取 Cookie 的值。

int

getVersion()

用于获取 Cookie 遵守的协议版本。

void

setMaxAge(int expiry)

用于设置 Cookie 的最大有效时间,以秒为单位。 取值为正值时,表示 Cookie 在经过指定时间后过期。取值为负值时,表示 Cookie 不会被持久存储,在 Web 浏览器退出时删除。取值为 0 时,表示删除该 Cookie。

void

setPath(String uri)

用于指定 Cookie 的路径。

void

setSecure(boolean flag)

用于设置浏览器是否只能使用安全协议(如 HTTPS 或 SSL)发送 Cookie。

void

setValue(String newValue)

用于设置 Cookie 的值。

Session

Session 是服务器端会话技术。当浏览器访问 Web 服务器的资源时,服务器可以为每个用户浏览器创建一个 Session 对象,每个浏览器独占一个 Session 对象。

由于每个浏览器独占一个 Session,所以用户在访问服务器的资源时,可以把数据保存在各自的 Session 中。当用户再次访问该服务器中的其它资源时,其它资源可以从 Session 中取出数据,为用户服务。

Session 的工作原理

Session 虽然属于服务端会话技术,但是它的实现离不开客户端浏览器和 Cookie 的支持,其工作原理如下。

  1. 当客户端第一次请求会话对象时,服务器会创建一个 Session 对象,并为该 Session 对象分配一个唯一的 SessionID(用来标识这个 Session 对象);

  1. 服务器将 SessionID 以 Cookie(Cookie 名称为:“JSESSIONID”,值为 SessionID 的值)的形式发送给客户端浏览器;

  1. 客户端浏览器再次发送 HTTP 请求时,会将携带 SessionID 的 Cookie 随请求一起发送给服务器;

  1. 服务器从请求中读取 SessionID,然后根据 SessionID 找到对应的 Session 对象。

注意:
流程中的 Cookie 是容器自动生成的,它的 maxAge 属性取值为 -1,表示仅当前浏览器有效。
浏览器关闭时,对应的 Session 并没有失效,但此时与此 Session 对应的 Cookie 已失效,导致浏览器无法再通过 Cookie 获取服务器端的 Session 对象。
同一浏览器的不同窗口共享同一 Session 对象,但不同浏览器窗口之间不能共享 Session 对象。

Session 与 Cookie 对比

Session 和 Cookie 都属于会话技术,都能帮助服务器保存和跟踪用户状态,但两者也存在差异,如下表。

不同点

Cookie

Session

存储位置不同

Cookie 将数据存放在客户端浏览器内存中或硬盘上。

Session 将数据存储在服务器端。

大小和数量限制不同

浏览器对 Cookie 的大小和数量有限制。

Session 的大小和数量一般不受限制。

存放数据类型不同

Cookie 中保存的是字符串。

Session 中保存的是对象。

安全性不同

Cookie 明文传递,安全性低,他人可以分析存放在本地的 Cookie 并进行 Cookie 欺骗。

Session 存在服务器端,安全性较高。

对服务器造成的压力不同

Cookie 保存在客户端,不占用服务器资源。

Session 保存在服务端,每一个用户独占一个 Session。若并发访问的用户十分多,就会占用大量服务端资源。

跨域支持上不同

Cookie 支持跨域名访问。

Session 不支持跨域名访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值