Servlet —— 只有一个实例
就个人说,最早接触J2EE的时候,是使用Module1模式的,也就是纯JSP的开发。对个人开发来说,还挺方便的吧。但是,把页面展示的内容与逻辑结构混合在一起,通常会使得JSP文件膨胀、内容混乱,可阅读性是急剧下降的。所以,后来也就转到Module2模式,也即平常说的MVC模式。MVC模式可以说是一种很不错的分工与合作的思想。而Servlet,也即在其中扮演C——Controller的角色。不过,真正出现Servlet技术的原因,要对比传统的CGI(Common Gateway Inte易做图ce)技术。
Servlet本身也可以说就是一个Java文件,主要是担当Web浏览器(客户请求)与Http服务器上数据库等的中间层。即,承接浏览器(网页)的操作内容以及返回数据库的被访问记录。Servlet运行于服务器内部,并为Web服务器容器加载。也即是,Servlet的创建、运行、销毁等都已交由服务器容器管理。
那,可以看一下Servlet的生命周期:
(1)装载Servlet。该操作一般是动态执行。然而,Server通常会提供一个管理的选项,用于在Server启动时强制装载和初始化特定的Servlet。
(2)Server创建一个Servlet的实例
(3)Server调用Servlet的init()方法
(4)一个客户端的请求到达Server
(5)Server创建一个请求对象
(6)Server创建一个响应对象
(7)Server激活Servlet的Service()方法,传递请求、响应对象作为参数
(8)service()方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息
(9)service()方法使用响应对象的方法,将响应传回Server,最终到达客户端。Service()方法可以激活其他方法以处理请求,如doGet()或doPost()或程序员自己开发的新的方法。
(10)对于更多的客户端请求,Server创建新的请求和响应对象,仍然激活此Servlet的service()方法,将这两个对象作为参数传递给该方法。如此重复以上的循环,但无需再调用init()方法。因为,一般Servlet只初始化一次(只有一个实例),而当Server不再需要Servlet时(如异常或Server关闭),Server将调用Servlet的destroy()方法。
这个生命周期是相当好理解的。唯一的一点,就是,为什么Servlet只有一个实例?
出于性能的考虑:特别的对于门户网站而言,每一个Servlet在每一秒内的并发访问量都可以是成千上万的。在一个面向模块化开发的现在,常常一个点击操作就被定义为一个Servlet的实现,而如果Servlet的每一次被访问,都创建一个新的实例的话,服务器的可用资源消耗量将是一个相当重要的问题。退一步,一般Servlet的访问是很快的,每一个实例被快速的创建,又被快速的回收,GC的回收速度也跟不上,频繁的内存操作也将可能带来次生的问题。所以,Servlet的“单一实例化”是一个很重要的策略。但,它如何解决并发的问题呢?
其实,服务器容器会为每一个Servlet维护一个连接池,是c3p0或dbcp,都实现了DataSource,是其实现类。在编程实现上可理解为一个Application级别的Vector(自身线程安全的集合类),里面装载相当数量的Connection。每一个HTTP请求到来时,将分配一个Connection去响应请求。并在结束响应后,把Connection放回线程池。而如果当前可用Connection小于一个标准数量值,便自动添加新的Connection到Vector中。
所以,除了Servlet文件的编写及相关的部署外,所有的其他操作其实都交付给了服务器容器来进行管理。
后记:
本文的大部分内容都来自网络。关于Servlet的更详细介绍,可以查看百度百科Servlet。
而“Servlet只有一个实例”观点的更多资料,要读者自己搜索更多了。
需要理解连接池的原理,这应该要看看Tomcat等的架构。
补充:软件开发 , 其他 ,