对于Servlet,服务器只创建每个servlet的单一实例,每个用户请求都会引发新的线程-----将用户请求将会给相应的doGet/doPost进行处理。那么,servlet是如何进行创建和销毁的?
当首次创建servlet时,它的init方法会得到调用,在这之前首先是服务器加载相应的servlet。init是放置一次性代码 的地方,在这之后,针对每个用户请求,都会创建一个线程,该线程调用前面创建的实例的service方法。多个并发请求一般会导致多个线程的同时调用 service(尽管可以实现特殊的接口,如 SingleThreadModel,规定任何时间只允许单个线程运行)。在调用service方法后,根据service方法收到的HTTP请求的类型,调用doGet,doPost,若其他doXxx方法,最后,如果服务决定缷载某个service,它会首先调用servlet的destroy方法。
service方法
服务器每次接收到对servlet的请求,都会产生一个新的线程,调用service方法,service方法检查HTTP请求的类型(GET,POST,PUT,DELETE等)并相应地调用doGet,doPost,doPut,doDelete等方法,GET请求起因于正常的URL请求,或没有指定method="post"的表单请求。POST请求起因于特别将POST列为method的HTML表单,其他HTTP请求都由定制客户生成。
如果我们需要在servlet中等同地处理POST和GET请求,我们有可能会不去实现doPost doGet方法,而是直接配覆写service方法。但是这样做不是一个好的思想,我们应该在doPost方法中调用doGet或相反。
public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
doGet(request,response);
}
public void doGet()throws ServletException,IOException{ // 相应的业务处理方法代码
}
这样做有几处优点:首先,我们还可以添加doPut,doTrace等方法,支持HTTP请求方法;其次,可以通过添加getLastModified方法加入对修改日期的支持。
destroy方法
服务器可以会决定移除之前载入的servlet实例,这时候它会调用servlet的destroy方法,从而使得servlet有机会关闭数据库连接、停止后台运行的线程、将cookie列表和点击计数写入到磁盘,并执行其他清理活动。在这里,要注意的是 web服务器可能会崩溃;所以我们不应该将destory机制作为向磁盘上保存状态的惟一机制。如果服务器执行诸如点击计数,或对cookie值(表示特殊的访问 )的列表进行累加等活动,应该主动地定期将数据写到磁盘上。
Servlet 与CGI的区别:
与CGI的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。