| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> Servlet运行原理以及生命周期 -> 正文阅读 |
|
[Java知识库]Servlet运行原理以及生命周期 |
前言:
? ? ? ? ?
Servlet是一个java编写的程序,此程序是在服务器端运行的, 是按照Servlet规范编写的一个 java类。Servlet是处理客户端的请求,并将处理结果以响应的 方式返回给客户端。Servlet框架 是怎样的呢?它的生命周期又是什么情况呢?这是本文需要探 求的
🍊
Tomcat
执行
servlet
架构图
1.程序如果一旦打成
war
包,扔
tomcat
中,其实就已经和开
发环境没有任何联系和瓜葛
2.应用程序与应用程序直接,是通过上下文
Context
来隔离
3.其实我们在程序中编写的大量的
Servlet
其实都在给
Tomcat
编写子类。给
HttpServlet
编写子类
4.
如果
tomcat
一旦运行起来,那么就把应用程序所有对应
的子类
Servlet
全部加载内存中(没有实例化),然后用
上线文隔离,准备接受请求。
5.
如果用户一旦发起
http
请求,如果协议和端口都是一致
的,并且上下文
Context
匹配的。然后调用执行引擎
Engine
类,这个引擎类就把要执行的请求对象,响应对
象初始化准备好。(这个都有
HttpServletRequest,
HttpServletResponse
)
6.
然后通过你路由地址,根据你
path=/login---->
映射的
class---com.kuangstudy.LoginServlet ---
用反射实例化
LoginServlet
对象,
但是它只会实例化一次
<servlet>
2 <servlet-name>loginServlet</serlvet-
name>
3 <servlet-
class>com.kuangstudy.LoginServlet</servle
t-class>
4 </servlet>
5 <servlet-mapping>
6 <servlet-name>loginServlet</serlvet-
name>
7 <ul-pattern>/login</ul-pattern>
8 </servlet-mapping>
7.在实例化具体
servlet
对象的时候,先调用你的构造函
数,
----
调用类中的
init
方法
---
初始化结束
8.根据请求方法,统一执行
service
方法,
----
在这个方法
中,会根据你的请求方式去执行具体的方法比如
get
请求
执行
doGet
,如果是
post
就执行
doPost
。
9.结束请求
---destory()
没事具体实现。是空方法。
🍐
Servlet
框架
网上下载
Servlet
源码,解压之后发现其由两个包组成:
1
、
javax.servlet
2
、
javax.servlet.http
📦
javax.servlet
此包中定义了所有
Servlet
类都必须实现的接口或类。
接口定义:
1.ServletConfig
接口
---
在初始化过程中由
Servlet
容器
(Tomcat
调
用
)
2.ServletContext
接口
---
定义
Servlet
用于获取容器信息的方法
3.ServletRequest
接口
---
向服务器请求信息
4.ServletResponse
接口
---
响应客户端请求
Servlet
接口
---
定义所有的
Servlet
必须实现的方法
类定义:
1.ServletInputStream
类
---
用于从客户端读取二进制数据
---
请
求对象的输入流
----
遵循
http
2.ServletOutputStream
类
---
用于将二进制数据写入到客户端
3.GenricServlet---
抽象类,定义一个通用的,独立于底层协议
的
servlet
。
📦
java.servlet.http
此包中定义了使用
HTTP
通信协议的所有
Servlet
类应该实现的
类、接口。
接口定义:
HttpServletRequest
接口
---
封装
http
请求
HttpServletResponse
接口
---
封装
http
响应
HttpSession
接口
---
用于表示客户端存储有关客户的信息
HttpSessionAttributeListener
接口
---
实现这个监听接口,当
用户获取
Session
的属性列表发生
改变的时候得到通知。
类的定义:
HttpServlet
类
---
扩展了
GenericServlet
的抽象类
Cookie
类
---
创建一个
Cookie
,
Cookie
技术,用户存储服务器
发送给客户端的信息。
通过阅读
Servlet
框架源码,其主要的框架结构如下图:
🍊
Servlet
工作过程
1
、
Web Client
向
Servlet
容器(
Tomcat
)发出
Http
请求
2
、
Servlet
容器接收
Web Client
的请求
3
、
Servlet
容器创建一个
HttpRequest
对象,将
Web Client
请求
的信息封装到这个对象中
4
、
Servlet
容器创建一个
HttpResponse
对象
5
、
Servlet
容器调用
HttpServlet
对象的
service
方法,把
HttpRequest
对象与
HttpResponse
对象作为参数传给
HttpServlet
对象
6
、
HttpServlet
调用
HttpRequest
对象的有关方法,获取
Http
请求信息
7
、
HttpServlet
调用
HttpResponse
对象的有关方法,生成响应
数据
8
、
Servlet
容器把
HttpServlet
的响应结果传给
Web Client
附图:
Tomcat
和
HttpServlet
是如何进行交互的呢?从源码中我们可
以得到
🍊
Servlet
生命周期
在
Servlet
框架中所有的
Servlet
类都必须实现
Servlet
这个接
口。其中定义了三个方法
1
、
init
方法:负责初始化
Servlet
对象。
2
、
service
方法:用于响应客户端的请求
3
、
destroy
:销毁
Servlet
对象,释放占用的资源。
🍊
为什么说
Servlet
是请求的时候才初始化
呢?? --- 解决空间
如果说
Servlet
不是在请求的时候就初始化的?那应该在
启动的时候就执行你的构造函数(节约内存空间,需要
的时候在
new
)
比如想
springioc
容器就这样,它启动
springioc
就自
动去加载你的构造函数(用空间
(
浪费一点
jvm
内存
)
换(初始化对象)时间)? --- springioc是用空间换时间
🍊
为什么
LoginServlet
每次请求它只会实例化
一次呢?
每个线程执行的
Servlet
创建只会实例化一次,只要有人
请求实例化了。就会对象就不会在创建了。
经典面试题:
Servlet
是线程安全的吗?
---
不是
🍊Servlet生命周期四个阶段:
🍐
加载阶段
Tomcat
从文件系统,远程文件系统或其他网络服务中通过类
加载器来加载
Servlet
,并调用
Servlet
的默认构造方法
(
不带参
构造器
)
🍐
初始化阶段
init()
方法
当
Servlet
容器启动时:读取
web.xml
配置文件中的信息,构造
指定的
Servlet
对象,根据配置
文件的信息创建
ServletConfig
对象,并将其作为参数传递给
init
方法进行调用。
Tomcat
启动后:用户首次想某个
Servlet
对象发送请求,
Tomcat
会判断内存中是否存在指定的
servlet
对象,如果没有则会去创建它,然后创建
HttpRequest
,
HttpResponse
对象,调
service
方法处理用户的请求。从
Servlet
的构造开始我们没有显示的看
到
init()
方法的调用,那么
init
方法到底是何时进行调用的呢?
阅读源码可以知道:
init
方法是在实例化
Servlet
之后调用的,
其参数
ServletConfig
是在
Servlet
初始化阶段
Tomcat
根据
web.xml
配置信息,和操作系统的相关环境生成并传递给
init
🍐
响应客户请求阶段
service
方法
service()
方法是在客户端第一次访问
servlet
时执行的,其实
init
方法同样也是在有客户端访问
servlet
的时候才被调用。不过需要特别注意的是讨论
init
方法
在
session
级别上时,当存在不同的
会话访问相同的
servlet
时,
Tomcat
会开启一个线程处理这个
新的会话,但是此时
Tomcat
容器
不会实例化这个
servlet
对象,也就是有多个线程在共享这个
servlet
实例。换句话说
Servlet
对象在
servlet
容器中是以单例的
形式存在的!然而查看其源码可以发现,
Servlet
在多线程下并
未使用同步机制,因此,在并发编程下
servlet
是线程不安全
的。对于
Servlet
的并发,线程安全的处理问题,笔者会找个时
间好好的整理下思路。对于不同的
session
访问相同的
serlvet
对象,只有一次
init
的过程,笔者会在接下来予以演示。阅读
HttpServlet
的源码可以知道,基于
Http
通信协议的
HttpServlet
在进行客户端响应处理的时候根据客户端请求,响
应的类别不同分别调用不同的方法,其中最常用的就是
doGet
、
doPost
方法,这两个方法是我们在编写
Servlet
中的主
要的逻辑处理阶段
🍐
终止阶段:
destroy()
方法的调用(没有实现的方法)
上面的探讨中知道的了
Servlet
是如何加载、初始化、处理客户
端的请求响应的,那么
Servlet
在什么时候终止呢?其生命周期又是在什么时候结束的呢?
我们知道的是
Servlet
生命周期是有
Tomcat
容器来管理的,由
此在
Tomcat
关闭、或者
Restart
的时候,
servlet
的生命周期必然结束,
destroy
方法也必然被
调用过。在客户端与服务器的一次
Session
会话中,
session
关闭之后
servlet
并未销毁。后续演
示。
总的来说
servlet
对象什么时候
destroy
的呢?
1
、
Tomcat
服务器
stop
2
、
web
项目
reload
3
、
Tomcat
容器所在的服务器
shutdown(
这不废话吗?
)
更正之处:对于
destroy()
方法笔者略有疑惑,
“
它到底是如何
销毁
Servlet
的呢?
”
,基于这个问题
特意的去查看了源码,结果发现
destroy()
方法在
Servlet
框架中
并未具体去实现。它是由
Coder
自己去实现的。因此
“destroy()
方法用户销毁
Servlet”
这种说法
本身就是离谱的!
🍊
destory
方法
?? ?此方法,并不是说当前
LoginServlet
执行请求结束之后执
行的方法。
? ? ? ? ? ?tomcat
容器如果内部执行
reload
或者关闭的服务器,会来
触发执行
?? ?其实
tomcat
内部也并没有具体实现,其实这个方
法,没有什么意义
|
|
|
上一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 6:01:54- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |