1 Servlet基本生命周期
一个Servlet是HttpServlet的子类,由支持Servlet的服务器完成该子类的对象初始化的工作。当有多个客户端请求同一个Servlet时候,servlet引擎就会为每个客户端启动一个线程来处理连接。
Servlet容器一般采用“单实例,多线程”的方式管理Servlet,即Servlet容器只会创建一个Servlet实例,针对不同的用户访问将开启不同的线程运行service方法,每个线程调用的service方法都在各*JVM分配的内存地址中独立运行,Servlet容器一般会维护一个线程池去管理这些线程。
Servlet的生命周期有三个过程:
1)初始化Servlet。当Servlet第一被请求加载的过程中,服务器先初始化这个Servlet,创建一个Servlet对象,这个对象会调用init方法完成必要的初始化工作。
2)诞生的Servlet对象再次调用Service方法来响应客户端的请求。
3)当服务器关闭的时候,调用Destroy方法,消灭该Servlet对象。
Init方法只会被调用一次,即在Servlet第一次被请求加载的时候调用,当后续的客户请求Servlet服务器的时候,Web服务器将启动一个新的线程,在该线程中Servlet将会调用Service方法来响应请求。
Publicvoid init(ServletConfig config)throws ServletException
当Servlet第一杯请求加载的时候,服务器初始化一个Servlet,创建一个Servlet对象,这个对象调用init方法完成一些必要的初始化工作。Servlet引擎会把ServletConfig类型的对象传递给init方法,这个对象就被保存在Servlet对象中了,直到被消灭掉,这个ServletConfig负责向Servlet传递一些服务设置信息。
由于每个客户请求一个Servlet的时候,都是从唯一一个已经创建的Servlet对象来出启动一个单独的线程为客户端服务,所以该Servlet类的成员变量被所有线程所共享。
publicvoid service(HttpServletRequest request
HttpServletResponse response) throw ServletException,IOException
当 servlet 成功创建和初始化之后,servlet就调用 service 方法来处理用户的请求并返回响应。Servlet 引擎将两个参数传递给该方法,一个HttpServletRequest类型的对象,该对象封装了用户的请求信息,此对象调用相应的方法可以获取封装的信息,即这个对象可以获取用户提交的信息。另外一个参数对象是HttpServletResponse类型的对象,该对象用来响应用户的请求。service 方法可能被多次的调用,当后续的客户请求 servlet 服务时,Servlet引擎将启动一个新的线程,在该线程中,servlet 调用 service 方法响应客户的请求,也就是说,每个客户的每次请求都导致 service 方法被调用执行,调用过程运行在不同的线程中,互不干扰。
protected void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletException, IOException
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
HttpServlet 除了 init、service、destroy 方法外,该类还有两个很重要的方法:doGet和 doPost,用来处理客户的请求并作出响应。当服务器引擎第一次接受到一个servlet请求时,会使用init方法初始化一个servlet,以后每当服务器再接受到一个servlet 请求时,就会产生一个新线程,并在这个线程中调用service 方法检查 HTTP 请求类型(Get 、Post 等),并在 service 方法中根据用户的请求方式,对应地再调用 doGet 或 doPost 方法。因此,在 servlet 类中,我们不必重写 service 方法来响应客户,直接继承 service 方法即可。我们可以在 servlet 类中重写 doPost 或 doGet方法来响应用户的请求,这样可以增加响应的灵活性,并降低服务器的负担。
如果不论用户请求类型是 Post 还是 Get,服务器的处理过程完全相同,那么我们可以只在 doPost 方法中编写处理过程,而在doGet 方法中再调用 doPost 方法即可,或只在doGet方法中编写处理过程,而在 doPost 方法中再调用doGet 方法。
2 Servlet的基本配置说明
一个HttpServlet需要有特定的部署描述符(web.xml指定其特征:其定义如下:
<servlet>
<servlet-name>Tst</servlet-name>
<servlet-class>test.TestServlet</servlet-class>
<init-param>
<param-name>someKey</param-name>
<param-value>someValue</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Tst</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
-
<servlet-name>子元素指定Serlvet的名称,作为该Servlet的唯一标识。
-
<servlet-class>子元素指定所对应的Servlet类。
-
<init-param>子元素用 于定义所谓基于键-值对的初始化参数,Servlet对象可以通过调用ServletConfig对象的getInitParameter(String name)获取制定指定键的对应值。可以有多个元素,用于定义Servlet在工作时要获取的某些初始化信息(如:要读取的某些属性文件的路径等)。
-
<load-on-startup>子元素用于指定在Servlet容器启动时即创建该Servlet对象, 还是在Serlvet容器接收到针对该Servlet的请求后再实例化该Servlet对象。它的值为负数时采取后一种策略,它的值为0或正数时采取前一种策略。web.xml中可能会定义多个为正数的Servlet,Servlet容器会根据其值得大小决定其实例化顺序,值小的先实例化,值大的后实例化。
-
<url-pattern>元素用于把特定的Servlet映射到一个URI地址,当Servlet容器收到针对该地址发出的请求时,就会实例化相应的Servlet对象,并调用其方法。
访问这个配置文件中的Servlet的格式如下,当该servlet的所在项目名为MyTest,假如servlet容器为Tomcat,即http://localhost:8080/MyTest//test.
3 关于JSP与Servlet
准确的说,JSP就是Servlet,JSP是一个标准的文本文件,在第一次访问时,Servlet会将该文件“翻译”成Servlet,然后再实施调用。不同的应用服务器会有不同的翻译方式。
在Tomcat中全局的conf/Web.xml中定义了翻译JSP的配置,JspServlet负责翻译所有的JSP,其配置如下:
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
通过该配置文件可以看出,Tomcat会拦截所有的以后缀名*.jsp或*.jspx的请求,然后将该JSP文件转换翻译为Servlet类。我们可以在Tomcat安装目录下的\work\Catalina下可以找到JSP经过“翻译”后的Java源文件和编译后类文件,假如一个JSP为:view.jsp,则经过“翻译”后的Servlet源文件为:\work\Catalina\localhost\tst\org\apache\jsp\view_jsp.java
通过查看该view.jsp所生成的类,该类名view_jsp,继承了org.apache.jasper.runtime.HttpJspBase类,而HttpJspBase类又是HttpServlet的子类。HttpJspBase在其service方法中调用了_jspService方法,针对特定的jsp页面,Tomcat的JSP引擎将其“翻译”成 HttpJspBase的子类并重写其_jspService方法。该类的很多初始化内容有JSP引擎完成。在JSP中使用<%...%>所书写的Java代码被原样的置于_jspService方法中;另外在JSP中的HTML脚本通过流对象out原样输出。
在_jspService方法中,可以看到,JSP内建对象(request、reponse、application、session等),它们或是_jspService方法的参数变量,或是由JSP引擎在_jspService方法中预先定义好的变量,我们在JSP 的<%...%>中可以直接使用。因为我们编写的JSP最终都会翻译成Servlet类的。
本文转自 zhao_xiao_long 51CTO博客,原文链接:http://blog.51cto.com/computerdragon/1198587