Skip to content

Commit 8fc8c1f

Browse files
committed
Servlet 介绍与使用
1 parent 8d13610 commit 8fc8c1f

3 files changed

Lines changed: 780 additions & 0 deletions

File tree

docs/develop/web-base-03.md

Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
---
2+
title: Web笔记(三)Servlet 的类与接口API
3+
date: 2018-09-01 09:58:35
4+
url: develop/web/web/base-03
5+
updated: 2018-09-01 09:58:35
6+
categories:
7+
- Java EE
8+
tags:
9+
- Servlet
10+
---
11+
12+
### Servlet 介绍
13+
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
14+
使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
15+
Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:
16+
- 性能明显更好。
17+
- Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
18+
- Servlet 是独立于平台的,因为它们是用 Java 编写的。
19+
- 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
20+
- Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。
21+
<!-- more -->
22+
23+
### Servlet API
24+
Servlet API 包含两个包,分别是:javax.servlet 与javax.servlet.http包。具体的类与接口结构如下图:
25+
26+
![](https://cdn.jsdelivr.net/gh/niumoo/cdn-assets/2019/68c057bb4390b74f4ebb980719345e2a.jpg)
27+
28+
Servlet 的运行需要Web 服务器的支持,Web服务器可以通过调用Servlet对象提提供的标准API ,对客户端请求做出处理。
29+
[官方API](https://tomcat.apache.org/tomcat-5.5-doc/servletapi/)
30+
31+
#### Servlet 接口
32+
定义所有 servlet 都必须实现的方法。
33+
servlet 是运行在 Web 服务器中的小型 Java 程序。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。
34+
要实现此接口,可以编写一个扩展 javax.servlet.GenericServlet 的一般 servlet,或者编写一个扩展 javax.servlet.http.HttpServlet 的 HTTP servlet。
35+
此接口定义了初始化 servlet 的方法、为请求提供服务的方法和从服务器移除 servlet 的方法。这些方法称为生命周期方法,它们是按以下顺序调用的:
36+
37+
1. 构造 servlet,然后使用 init 方法将其初始化。
38+
2. 处理来自客户端的对 service 方法的所有调用。
39+
3. 从服务中取出 servlet,然后使用 destroy 方法销毁它,最后进行垃圾回收并终止它。
40+
41+
除了生命周期方法之外,此接口还提供了 getServletConfig 方法和 getServletInfo 方法,servlet 可使用前一种方法获得任何启动信息,而后一种方法允许 servlet 返回有关其自身的基本信息,比如作者、版本和版权。
42+
43+
Servlet 接口中定义的方法如下:
44+
45+
```java
46+
//当Servlet将要卸载时由Servlet引擎调用,用于是释放资源
47+
void destroy()
48+
49+
//由 servlet 容器调用,指示将该 servlet 放入服务。servlet 容器
50+
//仅在实例化 servlet 之后调用 init 方法一次。在 servlet 可以接
51+
//收任何请求之前,init 方法必须成功完成。
52+
void init(ServletConfig config) throws ServletException
53+
54+
//由 servlet 容器调用,以允许 servlet 响应某个请求。此方法仅在
55+
//servlet 的 init() 方法成功完成之后调用。
56+
void service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException
57+
58+
//返回 ServletConfig 对象,该对象包含此 servlet 的初始化和启动
59+
//参数。返回的 ServletConfig 对象是传递给 init 方法的对象。此接
60+
//口的实现负责存储 ServletConfig 对象,以便此方法可以返回该对象。
61+
//实现此接口的 GenericServlet 类已经这样做了。
62+
ServletConfig getServletConfig()
63+
64+
// 返回有关 servlet 的信息,比如作者、版本和版权。。
65+
String getServletInfo()
66+
67+
```
68+
69+
#### ServletConfig 接口
70+
由Servlet接口中的Init方法我们可以发现,init方法在做初始化工作的时候会传入ServletConfig类型的参数进行初始化工作, Servlet 容器使用的 ServletConfig配置对象,该对象在初始化期间将信息传递给 Servlet。
71+
72+
ServletConfig 接口中定义的方法如下:
73+
74+
```java
75+
//返回包含指定初始化参数的值的 String,如果参数不存在,则返回 null。
76+
String getInitParameter(String name)
77+
78+
//返回一个存储所有初始化变量的枚举函数,如果Servlet没有初始化变量,
79+
//返回一个空的枚举函数
80+
java.util.Enumeration<E> getInitParameterNames()
81+
82+
//返回一个ServletConfig 对象的引用
83+
ServletContext getServletContext()
84+
85+
//返回此 servlet 实例的名称。该名称可能是通过服务器管理提供的
86+
//在 Web 应用程序部署描述符中分配,或者对于未注册(和未命名)
87+
//的 servlet 实例,该名称将是该 servlet 的类名称。
88+
String getServletName()
89+
90+
```
91+
92+
#### GenericServlet 接口
93+
定义一般的、与协议无关的 Servlet。要编写用于 Web 上的 HTTP Servlet,请改为扩展 javax.servlet.http.HttpServlet。GenericServlet 实现 Servlet 和 ServletConfig 接口。**实现了Servlet 接口中除service()方法之外的所有抽象方法,但是是默认实现。**Servlet可以直接扩展 GenericServlet,GenericServlet 使编写 Servlet变得更容易。它提供生命周期方法 init 和 destroy 的简单版本,以及 ServletConfig 接口中的方法的简单版本。GenericServlet 还实现 log 方法,在 ServletContext 接口中对此进行了声明。
94+
95+
要编写一般的 servlet,只需重写抽象 service 方法即可。在开发中很少使用,不再说明。
96+
#### HttpServlet 接口
97+
HttpServlet 类继承GenericServlet 类,是一个抽象类。在Java Web 开发中自定义Servlet 通常都是直接集成HttpServlet 类,此类实现了Servlet 接口中的service(ServletRequest request,ServletResponse response) 方法,用来处理客户端请求,根据request中的getMethod方法来调用不同的处理方法,例如,get方法,则调用doGet方法进行处理,也因此HttpServlet定义了处理不同请求的不同方法。
98+
99+
![](https://cdn.jsdelivr.net/gh/niumoo/cdn-assets/2019/7ae09229e2b45fc552e9b2ab3b30d31e.jpg)
100+
101+
102+
#### ServletRequest 和 ServletResponse 接口
103+
定义将客户端请求信息提供给某个 servlet 的对象。servlet 容器创建 ServletRequest 对象,并将该对象作为参数传递给该 servlet 的 service 方法。
104+
ServletRequest 对象提供包括参数名称、参数值、属性和输入流的数据。扩展 ServletRequest 的接口可提供其他特定于协议的数据,例如 javax.servlet.http.HttpServletRequest 提供的 HTTP 数据。
105+
106+
ServletRequest中有很多有用的方法:
107+
```java
108+
//返回指定servlet上下文(web应用)的URL的前缀。
109+
String getContextPath()
110+
111+
//返回请求URI上下文后的子串
112+
String getServletPath()
113+
114+
//返回指定的HTTP头标指。如果其由请求给出,则名字应为大小写不敏感。
115+
String getHeader(String name)
116+
117+
//返回具有指定名字的请求属性,如果不存在则返回null。属性可由servlet
118+
//引擎设置或使用setAttribute()显式加入。
119+
Object getAttribute(String name)
120+
121+
//以指定名称保存请求中指定对象的引用。
122+
void setAttribute(String name,Object obj)
123+
124+
//返回指定输入参数,如果不存在,返回null。
125+
String getParameter(String name)
126+
127+
//返回请求所用的字符编码。
128+
String getCharacteEncoding()
129+
130+
```
131+
具体可以参考官方API
132+
[ServletRequest API](https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletRequest.html)
133+
134+
ServletResponse 中有很多有用的方法:
135+
```java
136+
//返回响应使用字符解码的名字。除非显式设置,否则为ISO-8859-1
137+
String getCharacterEncoding()
138+
139+
//返回用于将返回的二进制输出写入客户端的流,此方法和getWrite()
140+
//方法二者只能调用其一。
141+
OutputStream getOutputStream()throws IOException
142+
143+
//返回用于将返回的文本输出写入客户端的一个字符写入器,此方法和
144+
//getOutputStream()二者只能调用其一。
145+
Writer getWriter()throws IOException
146+
147+
//设置内容类型。在HTTP servlet中即设置Content-Type头标。
148+
void setContentType(String type)
149+
```
150+
具体可以参考官方API
151+
[ServletResponse API](https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletResponse.html)
152+
153+
#### HttpServletRequest 和 HttpServletResponse 接口
154+
HttpServletRequest 是专用于HTTP的ServletRequest 子接口,客户端浏览器的请求被封装成一个HttpServletRequest 对象,请求信息请求的地址,参数,数据,上传的文件,IP地址,甚至操作系统信息都包含在内。
155+
主要处理:
156+
157+
1. 读取和写入HTTP头标
158+
2. 取得和设置cookies
159+
3. 取得路径信息
160+
4. 标识HTTP会话。
161+
162+
HttpServletRequest 常用方法:
163+
```java
164+
//返回与请求相关cookie的一个数组。
165+
Cookie[] getCookies()
166+
167+
//返回HTTP请求方法(例如GET、POST等等)
168+
String getMethod()
169+
170+
//返回客户端的会话ID
171+
String getRequestedSessionId()
172+
173+
//调用getSession(true)的简化版。
174+
HttpSession getSession()
175+
176+
//返回当前HTTP会话,如果不存在,则创建一个新的会话,create参数为true。
177+
HttpSession getSession(boolean create)
178+
179+
//返回URL中一部分,从“/”开始,包括上下文,但不包括任意查询字符串。
180+
String getRequestURI()
181+
182+
//返回查询字符串,即URL中?后面的部份。
183+
String getQueryString()
184+
185+
//返回指定servlet上下文(web应用)的URL的前缀。
186+
String getContextPath()
187+
```
188+
HttpServletResponse 则继承了ServletResponse 接口。都提供了与HTTP有关的方法,主要是对HTTP状态码和Cookie的管理。
189+
```java
190+
//将一个Set-Cookie头标加入到响应。
191+
void addCookie(Cookie cookie)
192+
193+
//设置响应状态码为指定值(可选的状态信息)
194+
void sendError(int status)
195+
196+
//重定向到某一个Web组件
197+
void sendRedirect(String location)
198+
```
199+
200+
#### ServletContext 接口
201+
一个ServletContext 接口对象表示一个Web应用程序的上下文,运行在Java虚拟机中每个Web应用程序都有一个与之香瓜你的Servlet上下文,Sevetl API提供了一个ServletContext 接口老表示上下文,它提供了一些方法可以让Servlet 通过这些方法与Servlet 容器进行通信。
202+
常用方法:
203+
```java
204+
//将对象绑定到此 servlet 上下文中的给定属性名称。若存在,则替换之
205+
void setAttribute(String name, Object object)
206+
207+
//返回Servlet 上下文中名字为name的对象,名字是name的对象是全局对象
208+
//因此可以被同一个Servlet 在任意时候访问,或者上下文中任意其他的Servlet访问
209+
Object getAttribute(String name)
210+
211+
// 返回包含指定上下文范围初始化参数值的 String,如果参数不存在,则返回 null
212+
String getInitParameter(String name)
213+
```
214+
[ServletContext 接口官方API](https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletContext.html)
215+
216+
#### HttpSession 接口
217+
提供一种方式,跨多个页面请求或对 Web 站点的多次访问标识用户并存储有关该用户的信息。
218+
HttpSession 接口用于记录HTTP客户端和HTTP会话之间的关联,且可以在多个连接和请求中持续一段时间,Session则可以让无状态的HTTP请求在多个请求时识别用户记录状态。
219+
220+
此接口允许 servlet
221+
查看和操作有关某个会话的信息,比如会话标识符、创建时间和最后一次访问时间
222+
将对象绑定到会话,允许跨多个用户连接保留用户信息。
223+
224+
常用方法:
225+
```java
226+
227+
//使此会话无效,然后取消对任何绑定到它的对象的绑定。
228+
void invalidate()
229+
230+
//从此会话中移除与指定名称绑定在一起的对象。如果会话没有与
231+
//指定名称绑定在一起的对象,则此方法不执行任何操作。
232+
void removeAttribute(String name)
233+
234+
//使用指定名称将对象绑定到此会话。如果具有同样名称的对象已
235+
//经绑定到该会话,则替换该对象。
236+
void setAttribute(String name, Object value)
237+
238+
//返回与此会话中的指定名称绑定在一起的对象,如果没有对象绑
239+
//定在该名称下,则返回 null。
240+
Object getAttribute(String name)
241+
242+
//返回创建此会话的时间,该时间是用自格林威治标准时间 1970
243+
//年 1 月 1 日午夜起经过的毫秒数来测量的。
244+
long getCreationTime()
245+
246+
//返回包含分配给此会话的唯一标识符的字符串。
247+
String getId()
248+
249+
//超时时间以秒为单位。负数则永不超时。
250+
void setMaxInactiveInterval(int interval)
251+
252+
//返回 servlet 容器在客户端访问之间将使此会话保持打开状态
253+
//的最大时间间隔,以秒为单位。
254+
int getMaxInactiveInterval()
255+
```
256+
257+
258+
### 附录:HttpServletRequest的请求信息获取
259+
260+
```java
261+
/**
262+
* HttpServletRequest请求参数获取测试
263+
* @author niumoo
264+
*/
265+
@WebServlet("/dispense")
266+
public class DispenseServlet extends HttpServlet {
267+
@Override
268+
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
269+
throws ServletException, IOException {
270+
// 获取请求方式:GET
271+
System.out.println("req.getMethod():" + req.getMethod());
272+
273+
// 获取项目名称:/dispense
274+
System.out.println("req.getContextPath():" + req.getContextPath());
275+
276+
// 获取完整请求路径:http://localhost:8888/dispense/dispense
277+
System.out.println("req.getRequestURL():" + req.getRequestURL());
278+
279+
// 获取除了域名外的请求数据:/dispense/dispense
280+
System.out.println("req.getRequestURI():" + req.getRequestURI());
281+
282+
// 获取请求参数:name=codingme.net
283+
System.out.println("req.getQueryString():" + req.getQueryString());
284+
// 获取请求头:
285+
System.out.println("req.getHeader(\"user-Agent\"):" + req.getHeader("user-Agent"));
286+
287+
System.out.println("-------------------------------------------------");
288+
// 获取所有的消息头名称
289+
Enumeration<String> headerNames = req.getHeaderNames();
290+
// 获取获取的消息头名称,获取对应的值,并输出
291+
while (headerNames.hasMoreElements()) {
292+
String nextElement = headerNames.nextElement();
293+
System.out.println(nextElement + ":" + req.getHeader(nextElement));
294+
}
295+
296+
System.out.println("---------------------------------------------------");
297+
// 根据名称获取此重名的所有数据
298+
System.out.println("req.getHeader(\"accept\"):" + req.getHeader("accept"));
299+
300+
// 获取请求主机名
301+
System.out.println("req.getHeader(\"host\"):" + req.getHeader("host"));
302+
303+
}
304+
305+
@Override
306+
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
307+
throws ServletException, IOException {
308+
doGet(req, resp);
309+
}
310+
}
311+
312+
```
313+
请求:http://localhost:8888/dispense/dispense?name=codingme.net
314+
输出:
315+
316+
```
317+
req.getMethod():GET
318+
req.getContextPath():/dispense
319+
req.getRequestURL():http://localhost:8888/dispense/dispense
320+
req.getRequestURI():/dispense/dispense
321+
req.getQueryString():name=codingme.net
322+
req.getHeader("user-Agent"):Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3080.5 Safari/537.36
323+
--------------------------------------------------------
324+
host:localhost:8888
325+
connection:keep-alive
326+
cache-control:max-age=0
327+
upgrade-insecure-requests:1
328+
user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3080.5 Safari/537.36
329+
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
330+
accept-encoding:gzip, deflate, br
331+
accept-language:zh-CN,zh;q=0.8
332+
cookie:_ga=GA1.1.1003706294.1499565784; Hm_lvt_57ccbd5c600ed4e6bdb9458e666b6409=1499849256,1499853602,1499950574; Hm_lvt_1b51c3ea9a3e7b1a2bc55df97ab4efd3=1499952403
333+
----------------------------------------------------------
334+
req.getHeader("accept"):text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
335+
req.getHeader("host"):localhost:8888
336+
```

0 commit comments

Comments
 (0)