javaWeb之Servlet的工作原理与生命周期

Servlet的生命周期:

1)当浏览器第一次访问Servlet时,服务器会根据浏览器访问的路径,例如/Demo2,在项目的web.xml文件中 找到该Servlet的全路径,进行反射创建。(用户没有设置loadOnStartup的时候或者loadOnStartup < 0 的时候)
如果loadOnStartup > 0则web容器启动的时候做实例化处理,顺序是由小到大,正整数小的先被实例化
loadOnStartup = 0 web容器启动的时候做实例化处理,相当于是最小整数,因此web容器启动时,最先被实例化
2)调用init()为Servlet作初始化工作
3)调用service()为浏览器响应
4)如果浏览器再次访问相同的Servlet,从服务端维护的Servlet实例集合中取得对应的实现,为浏览器响应
5)同一个Servlet实例,在服务端只有一个,即Servlet是单例的。
6)服务器在决定销毁Servlet实例之前,调用destory()方法,每个Servlet实例只会调用一次,在重新部署情况下会销毁之前的
 注意:在web.xml文件中,某些Servlet只有<serlvet>元素,没有<servlet-mapping>元素,这样我们无法通过url的方式访问这些Servlet,这种Servlet通常会在<servlet>元素中配置一个<load-on-startup>子元素,让容器在启动的时候自动加载这些Servlet并调用init()方法,完成一些全局性的初始化工作。

详解:
 首先简单解释一下Servlet接收和响应客户请求的过程,首先客户发送一个请求,Servlet是调用service()方法对请求进行响应的,通过源代码可见,service()方法中对请求的方式进行了匹配,选择调用doGet,doPost等这些方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。在Servlet接口和GenericServlet中是没有doGet,doPost等等这些方法的,HttpServlet中定义了这些方法,但是都是返回error信息,所以,我们每次定义一个Servlet的时候,都必须实现doGet或doPost等这些方法。

  每一个自定义的Servlet都必须实现Servlet的接口,Servlet接口中定义了五个方法,其中比较重要的三个方法涉及到Servlet的生命周期,分别是上文提到的init(),service(),destroy()方法。GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口。而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口。所以我们定义Servlet的时候只需要继承HttpServlet即可。

  Servlet接口和GenericServlet是不特定于任何协议的,而HttpServlet是特定于HTTP协议的类,所以HttpServlet中实现了service()方法,并将请求ServletRequest,ServletResponse强转为HttpRequest和HttpResponse。

Servlet的线程问题:
Servlet 和 filter 被所有请求共享。那是 Java 的一个优点,使得多个不同线程(读取 HTTP 请求)可以使用同一个实例。否则为每个请求重新创建线程的开销实在过于昂贵。但永远不要将任何 request 或 session 域中的数据赋值给 servlet 或 filter 的实例变量。它将会被所有其他 session 中的所有请求共享。那是非线程安全的!
每个线程会共享同一个Servlet的实例变量,所以要对敏感数据加锁
产生线程安全条件如下:
a)单例 && b)实例变量 && c)实例变量进行修改操作
通过加锁的方式,对敏感数据块进行代码同步处理方法也就是多线程中的线程锁
还有一种处理方法就是 实现SingleThreadModel来解决线程安全
此方法已经被废除。主要是有二个不足之处:
a)SingleThreadModel接口的值与web服务器最多接收的线程数有关,可能会出现大值变小值的情况
b)SingleThreadModel接口如果发现某个线程正在占用该Servlet实例,会自动创建一个新的Servlet实例为浏览器服务,
这就违背了Servlet单例的原则

Servlet小结:
1、Servlet的init()和构造方法仅仅调用一次,仅仅会在第一次请求时候被调用一次,或者当Servlet配置为启动时候最先加载则 会在启动时候调用,配置方法是:<load-on-startup>0</load-on-startup>
2、由于Servlet只会调用构造方法一次,因此Servlet是单例的,在Servlet容器中,一个Servlet类只有一个Servlet实例存在。
3、Servlet处理请求是方式是多线程的,也就是说,一个请求会开启一个独立线程来处理。因此,在Servlet的处理方法应该注意线程安全。
4、Servlet可以配置参数,在Servlet类里可以读取参数。

部分内容参考:
http://www.cnblogs.com/cuiliang/archive/2011/10/21/2220671.html
http://honoka.cnblogs.com

你可能感兴趣的:(java,Web,servlet)