什么是Servlet?
1.Servlet
是一种独立于平台和协议的服务端的java技术,可以生成动态WEB页面与传统的CGI(计算机图形接口)和其他类似的CGI技术相比。Servlet具有更好的可移植性。更强大的功能,更少的投资,更高的效率,更好的安全性。
2.Servlet
是使用java Servlet应用程序接口(API)及相关类和方法的java程序。java语言能够实现的功能Servlet基本都能够实现。(除了图形化界面)。Servlet 主要用于处理客户端传来的Http 请求,并返回一个响应,通常来说Servlet就是指HttpServlet,用于处理Http请求,其能够处理的请求有doGet(),doPost(),service()等方法,开发servlet时可以直接结成javax.servlet,http.HttpServlet.
3.Servlet
需要在web.xml中进行描述,例如。映射执行servlet的名字,配置servlet类,初始化参数,进行安全配置,URL映射和设置启动优先权。Servlet不仅可以生成HTML脚本输出,也可以生成二进制表单输出。
4.Servlet
应用广泛,现在许多流行框架都离不开Servlet的支持,比如SHH,Spring 容器启动的时候,要在web,xml中装载Spring容器和Actioncontext来初始化Spring的一些参数。如依赖注入,数据库表的映射,初始化系统的安全配置设置read等属性进行一些相关的操作。
Servlet 的生命周期
**Servlet **被服务器实例化
后,容器运行其init 方法,请求到达时运行其service 方法,service 方法自动派遣运行与请求对应的doXXX 方法(doGet,doPost)等,当服务器决定将实例 销毁的时候调用其destroy 方法。web 容器加载 servlet,生命周期开始。通过调用 servlet 的 init()方法进行 servlet 的初始化。 通过调用 service()方法实现,根据请求的不同调用不同的 do***()方法。结束服务,web 容 器调用 servlet 的 destroy()方法。
Servlet 的基本架构
public class ServletName extends HttpServlet {
public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
}
public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
}
}
Servlet API 中 forward()与 redirect()的区别?
怎样理解Servlet的单实例多线程?
不同的用户同时对同一个业务(如注册)发出请求,那这个时候容器里产生的有是几个servlet实例呢?
答案是:只有一个servlet实例。一个servlet是在第一次被访问时加载到内存并实例化的。同样的业务请求共享一个servlet实例。不同的业务请求一般对应不同的servlet。
由于Servlet/JSP默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的安全性问题。
JSP的中存在的多线程问题:
当客户端第一次请求某一个JSP文件时,服务端把该JSP编译成一个CLASS文件,并创建一个该类的实例,然后创建一个线程处理CLIENT端的请求。如果有多个客户端同时请求该JSP文件,则服务端会创建多个线程。每个客户端请求对应一个线程。以多线程方式执行可大大降低对系统的资源需求,提高系统的并发量及响应时间。
对JSP中可能用的的变量说明如下:
实例变量:
实例变量是在堆中分配的,并被属于该实例的所有线程共享,所以不是线程安全的。
JSP系统提供的8个类变量
JSP中用到的out,request,response,session,config,page,pageContext是线程安全的(因为每个线程对应的request,respone对象都是不一样的,不存在共享问题),APPLICATION在整个系统内被使用,所以不是线程安全的。
局部变量:
局部变量在堆栈中分配,因为每个线程都有它自己的堆栈空间,所以是线程安全的。
静态类:
静态类不用被实例化,就可直接使用,也不是线程安全的.
外部资源:
在程序中可能会有多个线程或进程同时操作同一个资源(如:多个线程或进程同时对一个文件进行写操作).此时也要注意同步问题.
Servlet单实例多线程机制:
Servlet
采用多线程来处理多个请求同时访问。servlet依赖于一个线程池来服务请求。线程池实际上是一系列的工作者线程集合。Servlet使用一个调度线程来管理工作者线程。
当容器收到一个Servlet请求,调度线程从线程池中选出一个工作者线程,将请求传递给该工作者线程,然后由该线程来执行Servlet的service方法。当这个线程正在执行的时候,容器收到另外一个请求,调度线程同样从线程池中选出另一个工作者线程来服务新的请求,容器并不关心这个请求是否访问的是同一个Servlet.当容器同时收到对同一个Servlet的多个请求的时候,那么这个Servlet的service()方法将在多线程中并发执行。
Servlet容器默认采用单实例多线程的方式来处理请求,这样减少产生Servlet实例的开销,提升了对请求的响应时间,对于Tomcat可以在server.xml中通过<Connector>元素设置线程池中线程的数目。
如何开发线程安全的Servlet?
1、实现 SingleThreadModel 接口
该接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行,当然也就不存在线程安全的问题。这种方法只要将前面的Concurrent Test类的类头定义更改为:
Public class Concurrent Test extends HttpServlet implements SingleThreadModel {
…………
}
2、同步对共享数据的操作
使用synchronized 关键字能保证一次只有一个线程可以访问被保护的区段
3、避免使用实例变量
只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。
备注:
1)Struts2的Action是原型,非单实例的;会对每一个请求,产生一个Action的实例来处理。
2)Struts1Action是单实例的,Spring mvc的controller也是如此。因此开发时要求必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
3)** Struts1的Action,Spring的Ioc**容器管理的bean默认是单实例的.
4)Struts2Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)。
5)当Spring管理Struts2的Action时,bean默认是单实例的,可以通过配置参数将其设置为原型。(scope="prototype )
servlet与jsp的区别
1.jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)
2.jsp更擅长表现于页面显示,servlet更擅长于逻辑控制.
3.Servlet中没有内置对象,内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到.Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。
4.对于静态HTML标签,Servlet都必须使用页面输出流逐行输出.