什么是Servlet
运行在服务器端的程序
servlet是一个接口,定义了Java类被浏览器访问到的规则(接口)
Servlet是用java编写的服务器端的程序,主要是交互式的浏览和修改数据,生成动态Web内容,在JavaEE平台上,处理TCP连接,解析HTTP协议这些底层工作统统扔给现成的Web服务器去做,我们只需要把自己的应用程序跑在Web服务器上
Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
Struts2的核心用的是Filter(过滤器),而SpringMVC的核心用的就是Servlet。
1 | // WebServlet注解表示这是一个Servlet,并映射到地址/: |
一个Servlet总是继承自HttpServlet
,然后重写doGet()
或doPost()
方法。注意到doGet()
方法传入了HttpServletRequest
和HttpServletResponse
两个对象,分别代表HTTP请求和响应。我们使用Servlet
API时,并不直接与底层TCP交互,也不需要解析HTTP协议,因为HttpServletRequest
和HttpServletResponse
就已经封装好了请求和响应
工作模式
- 客户端发送请求至服务器
- 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
- 服务器将响应返回客户端
API预览
Servlet API 包含以下4个Java包:
1.javax.servlet 其中包含定义servlet和servlet容器之间契约的类和接口。
2.javax.servlet.http 其中包含定义HTTP Servlet 和Servlet容器之间的关系。
3.javax.servlet.annotation 其中包含标注servlet,Filter,Listener的标注。它还为被标注元件定义元数据。
4.javax.servlet.descriptor,其中包含提供程序化登录Web应用程序的配置信息的类型。
使用Servlet
Servlet技术的核心是Servlet,它是所有Servlet类必须直接或者间接实现的一个接口。在编写实现Servlet的Servlet类时,直接实现它。在扩展实现这个这个接口的类时,间接实现它。
工作原理
Servlet接口定义了Servlet与servlet容器之间的契约:Servlet容器将Servlet类载入内存,并产生Servlet实例和调用它具体的方法。
但是要注意的是,在一个应用程序中,每种Servlet类型只能有一个实例。
用户请求致使Servlet容器调用Servlet的Service()方法,并传入一个ServletRequest对象和一个ServletResponse对象。 ServletRequest中封装了当前的Http请求,ServletResponse表示当前用户的Http响应.
对于每一个应用程序,Servlet容器还会创建一个ServletContext对象。这个对象中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext。每个Servlet对象也都有一个封装Servlet配置的ServletConfig对象。
接口中定义的方法
1 | public interface Servlet { |
执行原理
当服务器接收到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
查找Web.xml文件,是否有对应的
tomcat会将其字节码加载进内存然后构建对象,调用其方法
Servlet的生命周期
上述接口中定义的方法内,init( ),service( ),destroy( )是Servlet生命周期的方法。
Servlet容器(例如TomCat)会根据下面的规则来调用这三个方法:
当Servlet第一次被请求时,Servlet容器就会开始调用 init() 方法,初始化一个Servlet对象出来,这个方法在后续请求中不会在被Servlet容器调用。调用这个方法时,Servlet容器会传入一个ServletConfig对象进来从而对Servlet对象进行初始化。
service( )方法,每当请求Servlet时,Servlet容器就会调用这个方法,第一次请求时,Servlet容器会先调用init( )方法初始化一个Servlet对象出来,然后会调用它的service( )方法进行工作,但在后续的请求中,Servlet容器只会调用service方法了。
destory,当要销毁Servlet时,Servlet容器就会调用这个方法,一般在这个方法中会写一些清除代码,只有服务器正常关闭的时候,才会执行destory方法
演示代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("Servlet正在初始化");
}
public ServletConfig getServletConfig() {
return null;
}
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//专门向客服端提供响应的方法
System.out.println("Servlet正在提供服务");
}
public String getServletInfo() {
return null;
}
public void destroy() {
System.out.println("Servlet正在销毁");
}
其中servlet的创建时期是可以被指定的
1 | <!-- 指定servlet的创建时期,负数为第一次访问时期,0或正数为服务器启动时期--> |
Servlet中的 init 方法只执行一次,说明一个Servlet中只存在一个对象,是单例的,多个用户同时访问可能存在线程安全的隐患,所以尽量不要再其中定义成员变量,也不要对其赋值
Tomcat部分
普通的Java程序是通过启动JVM,然后执行main()
方法开始运行。但是Web应用程序有所不同,我们无法直接运行war
文件,必须先启动Web服务器,再由Web服务器加载我们编写的HelloServlet
,这样就可以让HelloServlet
处理浏览器发送的请求。
Tomcat本身的目录层次结构

Tomcat提供了一个部署其服务器在你本地电脑上的功能
实际上,类似Tomcat这样的服务器也是Java编写的,启动Tomcat服务器实际上是启动Java虚拟机
执行Tomcat的main()
方法,然后由Tomcat负责加载我们的.war
文件,并创建一个HelloServlet
实例,最后以多线程的模式来处理HTTP请求。
如果Tomcat服务器收到的请求路径是/
(假定部署文件为ROOT.war),就转发到HelloServlet
并传入HttpServletRequest
和HttpServletResponse
两个对象。
配置Servlet
web.xml配置
web.xml
文件是用于配置 Web 应用程序的核心文件,它能对
Servlet、过滤器、监听器等组件进行配置
Servlet 定义
1 | <servlet> |
标签:该标签的作用是定义一个 Servlet。在一个 web.xml
文件中,可以定义多个 Servlet。标签:这里为 Servlet 指定一个名称,也就是 ServletExpDemo
。这个名称属于逻辑名称,主要用于在web.xml
文件的其他部分引用该 Servlet。标签:它指定了 Servlet 类的全限定名,即 org.ergoutree.servletexpdemo.demo1.FastGo。当 Web 容器启动时,会依据这个全限定名来加载并实例化该 Servlet 类。
Servlet 映射
1 | <servlet-mapping> |
标签:此标签的功能是将 Servlet 与一个或多个 URL 模式进行映射。当客户端发送请求时,Web 容器会根据请求的 URL 找到对应的 Servlet。 标签:这里引用了之前定义的 Servlet 的名称,也就是 ServletExpDemo
。标签:它指定了与该 Servlet 关联的 URL 模式,即 /demo1
。当客户端请求的 URL 匹配这个模式时,Web 容器就会将请求转发给ServletExpDemo
所对应的 Servlet 类(也就是org.ergoutree.servletexpdemo.demo1.FastGo
)进行处理。
原理及其示例
原理说明
当客户端向 Web 应用程序发送 HTTP 请求时,Web 容器(像 Tomcat 这类)会按照以下步骤处理请求:
- 解析请求 URL:Web 容器对客户端请求的 URL 进行解析,从中提取出请求的路径部分。
- 查找 Servlet 映射:Web 容器在
web.xml
文件里查找与请求路径相匹配的 ``。 - 定位 Servlet:若找到匹配的
,Web 容器会根据对应的
找到之前定义的 Servlet。 - 实例化并调用 Servlet:Web 容器加载并实例化该
Servlet 类,然后调用其
service()
方法来处理请求。 - 返回响应:Servlet 处理完请求后,将响应返回给客户端。
示例
假设客户端发送的请求 URL 为
http://localhost:8080/yourApp/demo1
,Web
容器会进行如下操作:
- 解析出请求路径为
/demo1
。 - 在
web.xml
文件中找到为 `/demo1` 的
。 - 根据
`
为
ServletExpDemo,找到对应的 Servlet 类
org.ergoutree.servletexpdemo.demo1.FastGo`。 - 加载并实例化
FastGo
类,调用其service()
方法处理请求。 - 将处理结果返回给客户端。
Serlvet3.0的注解配置
@WebServlet 的属性列表:

核心注解@WebServlet
取代 和
1 |
|
urlPatterns
:支持精确匹配 (/user
)、通配符 (/api/*
)、后缀匹配 (*.do
)。loadOnStartup
:值越小优先级越高,控制 Servlet 初始化顺序。asyncSupported
:异步处理开关,需配合AsyncContext
使用(后文详解)。
@WebFilter:声明过滤器
替代 和
1 |
|
dispatcherTypes
:控制过滤器作用的请求类型(如FORWARD
、ERROR
)。- 执行顺序问题:注解无法直接指定顺序,需通过类名自然排序或结合
web.xml
的 ``。
@WebListener:事件监听器 简化监听器的声明,覆盖 Servlet 上下文、会话、请求等生命周期事件。
1 |
|
异步处理
在 @WebServlet
或 @WebFilter
中设置
asyncSupported = true
。
流程:
- 开启异步上下文:
AsyncContext asyncContext = request.startAsync()
。 - 提交耗时任务到其他线程(如数据库查询、远程调用)。
- 任务完成时,通过
asyncContext.complete()
或返回响应。
1 |
|
模块化部署介绍
Servlet 3.0 模块化特性:
- 允许将 Web 组件(Servlet、Filter、Listener)打包为 JAR 文件,置于
WEB-INF/lib
目录。 - 容器自动扫描 JAR 中的
META-INF/web-fragment.xml
和注解,实现“即插即用”
注意情况
如果使用@WebServlet Annotation(注解)来配置Servlet,需要注意:
① 不要在 web.xml 文件的根元素(<web-app—/>)中指定 metadata-complete=“true”; ② 不要在 web.xml 文件中再次配置该 Servlet 相关属性
ServletRequest
和 ServletResponse
为
Servlet
提供了处理客户端请求和发送响应的能力;ServletConfig
为
Servlet
提供了配置信息;ServletContext
为
Servlet
提供了整个 Web
应用程序的上下文环境。它们共同协作,使得 Servlet
能够正常运行并处理客户端的请求。
ServletRequset接口
Servlet容器对于接受到的每一个Http请求,都会创建一个ServletRequest对象,并把这个对象传递给Servlet的Sevice( )方法。其中,ServletRequest对象内封装了关于这个请求的许多详细信息。
ServletRequest接口的部分内容:
1 | public interface ServletRequest { |
ServletResponse接口
javax.servlet.ServletResponse接口表示一个Servlet响应,在调用Servlet的Service( )方法前,Servlet容器会先创建一个ServletResponse对象,并把它作为第二个参数传给Service( )方法。
ServletResponse隐藏了向浏览器发送响应的复杂过程。在向客户端发送响应时,大多数都是使用该对象向客户端发送HTML。
ServletResponse内部定义的方法:
1 | public interface ServletResponse { |
ServletConfig接口
当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init( )方式传入一个ServletConfig对象。
其中几个方法如下:

ServletContext对象
ServletContext对象表示Servlet应用程序,是Servlet的上下文对象。每个Web应用程序都只有一个ServletContext对象。
在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。
通过在ServletConfig中调用getServletContext方法,也可以获得ServletContext对象。
有了ServletContext对象,就可以共享从应用程序中的所有资料处访问到的信息,并且可以动态注册Web对象。前者将对象保存在ServletContext中的一个内部Map中
ServletContext中的下列方法负责处理属性:
1 | Object getAttribute(String var1); // 获取 ServletContext 中指定名称的属性值 |
Servlet是否为线程安全
线程安全问题指的是多线程在并发执行时会不会出现问题。由于Web容器只会创建一个Servlet实例,所以多个用户发起请求时,会有多个线程处理Servlet代码,因此Servlet是线程不安全的。
考虑以下代码:
1 |
|
10秒内在两个不同的浏览器窗口中的表单输入name并提交,假如在A浏览器中输入111,B浏览器中输入222,最后会发现A和B浏览器显示的name都是222。这是因为在第一个线程睡眠时,第二个线程修改了name的值,所有最后显示都是222,那么就产生了线程不安全问题。
实际上Servlet,Context上下文作用域,HttpSession都是线程不安全的,只有request请求和局部变量是线程安全的。
关于Servlet与http相关的应用,下一部分是这个
关于Web基础部分
引用文章
菜鸟教程Servlet部分