Servlet第三章知识点总结——Servlet生命周期
目标
理解并掌握Servlet生命周期中各方法调用的时机以及特点
理解并掌握多线代码的并发问题以及解决办法
理解并掌握多线代码安全的编码规范
知识点预览
Servlet生命周期
Servlet生命周期
1. 四个阶段:
a) 加载阶段:加载并实例化(创建servlet实例)
b) 初始化阶段:调用init()方法
c) 响应客户请求阶段:调用service()方法
d) 终止阶段:调用destroy()方法
2. 加载并实例化一个Servlet
a) Servlet容器加载和实例化Servlet
b) Servlet容器可以从本地文件系统、远程文件系统或其他网络服务中通过类加载器加载Servlet
c) Servlet容器调用Servlet默认构造方法(不带参的构造方法)
3. 初始化阶段——init()方法
a) 时机:由服务器启动,加载Servlet时调用
b) 作用:让Servlet对象在处理客户请求前完成一些初始化的工作
c) 特点:
i. 只调用一次
ii. 除非它被destroy()方法移除,否则不能重复调用
iii. 一旦调用成功,则servlet可以接受客户端请求
d) 语法:
public void init(ServletConfig config) throws ServletException
4. Init()参数—ServletConfig对象
a) 作用:
封装了Servlet容器的配置信息
b) 特点:
i. 从一个Servlet被实例化后,对任何客户端任何时候访问有效
ii. 仅对本servlet有效,不能访问另一个servlet的ServletConfig
c) 方法:
getInitParameter()
5. 配置初始化参数
a) 初始化参数在web.xml中定义
b) 语法:
<init-param>
<param-name>name</param-name>
<param-value>Ladies and Gentlemen</param-value>
</init-param>
<init-param>
<param-name>message</param-name>
<param-value>Welcome to Servlet World!</param-value>
</init-param>
c) 注意:
i. 必须写在<servlet></serlvet>之间
ii. 必须写在<serlvet-name>和<serlvet-class>之后
6. 初始化方法示例
<init-param>
<param-name>name</param-name>
<param-value>Ladies and Gentlemen</param-value>
</init-param>
<init-param>
<param-name>message</param-name>
<param-value>Welcome to Servlet World!</param-value>
</init-param>
7. Service()方法
a) 时机:
i. 第一次访问Servlet:必须在inint()方法执行之后
ii. 客户端发送请求
b) 语法:
protected void service(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException{}
c) 特点:
i. 通过独立的servlet线程处理客户端请求
ii. 存在并发问题
d) 其他
e) servlet首先不是线程安全的。Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类,也就是有多个线程在使用这个实例。Servlet容器会自动使用线程池等技术来支持系统的运行所以当你需要保证数据一致性的时候,必须自己处理线程安全问题。不能依赖实例变量
8. 并发问题1
9. 并发问题2
10. Servlet线程安全
a) 多个线程安全访问相同的数据
b) 代码建议:
i. 为方法和变量定义适当的访问类型
ii. 对关键数据访问同步所有实例方法
iii. 创造访问方法来访问类变量
11. Servlet规范 --如何使Servlet安全
a) 使用synchronized同步代码块,效率太低,一般不使用
b) 使用单线程模型,如果该Servlet被声明为单线程模型的话,容器就会维护一个实例池,那么将存在多个实例,效率更低,一般不使用。
c) 使用Servlet编程规范。
12. Servlet编程规范
a) 代码必须是线程安全的
b) 可以采用同步方法读取变量
i. class ServletMain extends HttpServlet{
private String strTest1; // 实例变量,线程不安全,只读(客户线程不能改变其值)可用,否则不能使用。
private static final String strTest2 = "TEST"; // 静态变量,但只读,线程安全,可用。
private Config config; // 实例变量,如果是只读,线程安全,可用。
public void init() throws ServletException {
String strTest3; // 局部变量,线程安全
13. destroy()方法
a) 时机:当一个服务器卸载servlet时会自动调用
b) 作用:
i. 释放当前实例所占用的资源
ii. 把当前内存中的数据储存到持久存储设备中
iii. 在整个生命周期中,只被调用一次
c) 语法:
public void destroy(){}
d) 注意:
i. 在destroy()方法完成前必须确保所有线程都已完成
14. Serlvet编程规范
a) 创建线程指示器变量
i. 使用变量访问同步方法,记录线程的数量
ii. 调用service方法时,指示器加1
iii. Service方法执行完成时,指示器减1
b) 创建服务器关闭标记
i. 设置关闭标记,默认值为false,通过同步方法对值进行修改
ii. 当服务器关闭时,关闭标记设为true
iii. 只有当关闭标记为false时,才能执行业务逻辑代码
c) 在destroy()方法完成前确保所有线程都已完成
i. 检查线程指示器的数量
ii. 当线程指示器不为零时,持续等待,直至所有线程结束
15. 处理线程服务示例
16. 有判断和等待线程关闭的过程
17. 没有判断并等待线程关闭过程
回顾Servlet生命周期
重写初始化方法并且给servlet提供初始化信息
初始化方法只调用一次.
不能重新加载.
一旦初始化方法返回则可以接受客户端请求.
没有并发问题.
接受能提取初始化参数值的ServletConfig对象
配置初始化参数(不同网络服务器有所不同)
在servlet服务程序中注意线程安全并发问题
在销毁方法中撤销所有的初始化工作并且同步持久化状态
在servlet销毁前注意线程安全并发问题