CGI(Common Gateway Interface),通用网管接口
通用网管接口,简称CGI,是一种根据请求信息动态产生回应内容的技术。通过CGI,web服务器可以根据请求的不同,启动不同的外部程序。也就是说,对于每个请求,都要产生一个新的进程进行处理。因为每个进程都会占有很多服务器的资源和时间,这就导致了服务器无法同时处理很多的并发请求。另外CGI程序都是与操作系统平台相关的。
Servlet
Servlet最初是在1995年由James Gosing提出的,因为使用技术需要复杂的Web服务器支持,所以当时并没有得到重视,也就放弃了。后来随着Web应用复杂度的提升,并要求提供跟高的并发处理能力,Servlet被重新捡起,并在Java平台上得到实现。
Java Servlet要求必须运行在Web服务器当中,与Web服务器之间属于分工和互补关系。确切的说,在实际运行的时候Java Servlet与Web服务器会融合到一块,如同一个程序一样运行在同一个Java虚拟机当中。与CGI不同的是,Servlet对每个请求都是单独启动一个线程,而不是进程。这种处理方式大幅度的降低了系统中的进程数量,提供了系统的并发处理能力。另外因为Java Servlet是运行在虚拟机上的,也就解决了 跨平台的问题。如果没有Servlet的出现,也就没有互联网的今天。
Servlet侧重解决运算和业务逻辑,JSP侧重于解决展示问题。
两者的对比
- servlet处于服务器进程中,它通过多线程的方式运行service方法。
- CGI是一个HTTP请求都会产生一个新的进程,服务完成后就销毁。
- CGI主要用shell Script或C语言编写
- Servlet主要使用Java语言编写
- CGI进程在服务完成后就会被销毁,所以效率上低于Servlet。
- Servlet进程出于服务器进程中,只有在服务器被卸载时才会被卸载
- CGI是不可被移植的,是运行于特定平台上的。
- Servlet是可移植的,运行在JVM上的。
Servlet是线程安全的吗?为什么?
servlet是线程不安全的,因为在tomcat容器中所创建出的servlet对象是单例的,每次请求到达后就会从线程池中启用一个线程去操作servlet对象,如果多个线程操作的是同一个servlet对象,并且使用servlet处理请求的代码中包含有实例对象或者静态变量,就可能造成线程安全问题。但是也要分具体的情况来处理问题。
如果service方法没有访问成员变量或者是静态变量、文件、数据库连接等,而是只是用了当前线程自己的资源,比如临时变量、request、response对象等。该方法本身就是线程安全的那就不需要再进行同步操作。
如果service方法访问 servlet的成员变量但是只对其读操作那就不必进行同步控制,如果进行写操作就需要加上同步语句;如果访问了全局静态变量,既有读也有写操作,通常需要加上同步控制。
解决线程安全问题也可以通过加锁
或者实现
SingleThreadModel
接口。(该接口已经过时)
实现这个接口后,就意味着web容器能够为每个请求创建一个Servlet对象,而不再使用默认的单例模式。
Servlet的生命周期
servlet的生命周期就是从servlet出现到销毁的过程
分以下几个阶段
加载--->实例化---->初始化(为对象的属性赋值)---->请求处理---->销毁
服务器启动时(web.xml中配置load-on-startup=1,默认是0)或者第一次请求该servlet时,会初始化一个Servlet对象,也就是会执行初始化方法init ,该Servlet对象会处理所有客户端请求,service方法中执行,最后服务器关闭时才会调用destory方法销毁该对象,其中加载阶段无法观察,但是初始化,服务,销毁阶段是可以观察到的。
创建Servlet的时机:在tomcat启动时,客户端首次向容器发出请求,Servlet容器会判断内存中是否存在指定的Servlet对象,如果没有就创建它,然后根据客户端的请求创建HTTPRequest、HTTPResponse对象,从而调用Servlet对象的service方法。