Servlet的生命周期(重点)

来源:互联网 发布:webrtc python 编辑:程序博客网 时间:2024/06/05 03:04

有关servlet的类有Servlet,HttpServlet以及GenericServlet.
其实我们要写一个Servlet只要写一个类去实现Servlet就可以了,但是,Servlet里面有很多的方法,我们没有必要每次为了写一个Servlet而去实现这么多方法,所以这里提供了一个GenericServlet,这个类实现了一些方法,我们可以直接继承这个类还不用去实现Servlet,但是我们要做的web,GenericServlet里面并没有有关协议的一些方法,所以,我们要再写一个类,这个类里面要有有关协议的方法,这个类就是HttpServlet,里面有doGet()和doPost()方法

Servlet—>GenericServlet—>HttpServlet

我们正式讲servlet的生命周期。

4.1 引入

Servlet的生命周期: servlet类对象什么时候创建,什么时候调用什么方法,什么时候销毁。参照下例:

以前的对象: new Student(); stu.study(); stu=null;

注意Servlet程序的生命周期由tomcat服务器控制的!

4.2 Servlet重要的四个生命周期方法

构造方法: 创建servlet对象的时候调用。默认情况下,第一次访问servlet的时候创建servlet对象,只调用1次。证明servlet对象在tomcat是单实例的。

init方法: 创建完servlet对象的时候调用。只调用1次。

service方法: 每次发出请求时调用。调用n次。

destroy方法: 销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象。只调用1次。

4.3 伪代码演示servlet的生命周期

下面的d代码都是在Tomcat内部做的。

Tomtcat内部代码运行:

1)通过映射找到到servlet-class的内容,字符串: gz.itcast.a_servlet.FirstServlet

2)通过反射构造FirstServlet对象

  a、得到字节码对象

Class clazz = class.forName(“gz.itcast.a_servlet.FirstServlet”);

b、调用无参数的构造方法来构造对象

Object obj = clazz.newInstance(); —1.servlet的构造方法被调用

3)创建ServletConfig对象,通过反射调用init方法

  a、得到方法对象

Method m = clazz.getDeclareMethod(“init”,ServletConfig.class);
//上述代码的意思是:“init”是方法的名字,ServletConfig.class是init方法要传入的参数的类型。

//m其实就是init方法,并且传入的参数类型是Servletonfig.class;

b、 调用方法

m.invoke(obj,config); –2.servlet的init方法被调用

//上面代码的意思是:由obj(上面已经生成好了)这个对象去调用init这个方法,传入config这个实参(之前说的形参是ServletConfig.class),这里的config就是一个//ServletConfig对象
4)创建request,response对象,通过反射调用service方法

             a、 得到方法对象              Methodm m =clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);

//”service”,这个方法要传入的参数有两个,分别是HttpServletRequset和HttpServletResponse类型。

              b、调用方法              m.invoke(obj,request,response);  --3.servlet的service方法被调用

//上面代码的解释参考前面,

5)当tomcat服务器停止或web应用重新部署,通过反射调用destroy方法

a、得到方法对象
Method m = clazz.getDeclareMethod(“destroy”,null);

b、 调用方法

m.invoke(obj,null); –4.servlet的destroy方法被调用
c、 用时序图来演示servlet的生命周期

5) Servlet的自动加载

默认情况下,第一次访问servlet的时候创建servlet对象。如果servlet的构造方法或init方法中执行了比较多的逻辑代码,那么导致用户第一次访问sevrlet的时候比较慢。

怎么解决上面的说的加载慢的问题: 改变servlet创建对象的时机: 提前到加载web应用的时候!!!
在servlet的配置信息中,加上一个即可!!

<servlet>    <servlet-name>LifeDemo</servlet-name>    <servlet-class>gz.itcast.c_life.LifeDemo</servlet-class>    <!-- 让servlet对象自动加载 -->    <load-on-startup>1</load-on-startup>  注意: 整数值越大,创建优先级越低!!  </servlet>

6) Servlet的多线程并发问题

注意: servlet对象在tomcat服务器是单实例多线程的。

因为servlet是多线程的,所以当多个servlet的线程同时访问了servlet的共享数据,如成员变量,可能会引发线程安全问题。
解决办法:
1)把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)

2)建议在servlet类中尽量不要使用成员变量。如果确实要使用成员,必须同步。而且尽量缩小同步代码块的范围。(哪里使用到了成员变量,就同步哪里!!),以避免因为同步而导致并发效率降低。

Servlet学习:

HttpServletRequest 请求对象:获取请求信息

HttpServletResponse 响应对象: 设置响应对象

ServletConfig对象 servlet配置对象

ServletContext对象; servlet的上下文对象

7) ServletConfig对象
a、 作用
ServletConfig对象: 主要是用于加载servlet的初始化参数。在一个web应用可以存在多个ServletConfig对象(一个Servlet对应一个ServletConfig对象)
b、 对象创建和得到

创建时机: 在创建完servlet对象之后,在调用init方法之前创建。
得到对象: 直接从有参数的init方法中得到!!!
c、 servlet的初始化参数配置

  <servlet>    <servlet-name>ConfigDemo</servlet-name>    <servlet-class>gz.itcast.f_config.ConfigDemo</servlet-class>    <!-- 初始参数: 这些参数会在加载web应用的时候,封装到ServletConfig对象中 -->    <init-param>        <param-name>path</param-name>        <param-value>e:/b.txt</param-value>    </init-param>  </servlet>

注意: servlet的参数只能由当前的这个servlet获取!!!!
ServletConfig的API:

java.lang.String getInitParameter(java.lang.String name) 根据参数名获取参数值
java.util.Enumeration getInitParameterNames() 获取所有参数
ServletContext getServletContext() 得到servlet上下文对象 java.lang.String getServletName() 得到servlet的名称

8) ServletContext对象
a、 引入
ServletContext对象 ,叫做Servlet的上下文对象。表示一个当前的web应用环境。一个web应用中只有一 个ServletContext对象。
b、 对象创建和得到
创建时机:加载web应用时创建ServletContext对象。
得到对象: 从ServletConfig对象的getServletContext方法得到

我们设计:
创建ServletConfig对象

public void init( ServletConfig config,ServletContext context ){ 多了一个参数

得到ServletConfig对象

得到ServletContext对象;

}

Sun公司设计

1)创建ServletContext对象 ServletContext context = new ServletContext()
2)创建ServletConfig对象 ServetConfig config = new ServletConfig(); config.setServletContxt(context);
class ServletConfig{ ServletContext context;
public ServletContext getServletContxt(){
return contxt;
}
}
public void init( ServletConfig config ){
得到ServletConfig对象
从ServletConfig对象中得到ServletContext对象
SerlvetContext context = config.getServletContext();
}

9) ServletContext对象的核心API(作用)
java.lang.String getContextPath() –得到当前web应用的路径
java.lang.String getInitParameter(java.lang.String name) –得到web应用的初始化参数
java.util.Enumeration getInitParameterNames()
void setAttribute(java.lang.String name, java.lang.Object object) –域对象有关的方法
java.lang.Object getAttribute(java.lang.String name)
void removeAttribute(java.lang.String name)
RequestDispatcher getRequestDispatcher(java.lang.String path) –转发(类似于重定向)
java.lang.String getRealPath(java.lang.String path) –得到web应用的资源文件
java.io.InputStream getResourceAsStream(java.lang.String path)

a、 得到web应用路径

java.lang.String getContextPath() 用在请求重定向的资源名称中
b、得到web应用的初始化参数(全局)
java.lang.String getInitParameter(java.lang.String name) –得到web应用的初始化参数
java.util.Enumeration getInitParameterNames()
web应用参数可以让当前web应用的所有servlet获取!!!
c、域对象有关的方法
域对象:作用是用于保存数据,获取数据。可以在不同的动态资源之间共享数据。
案例:
ServletContext就是一个域对象!!!!

保存数据:void setAttribute(java.lang.String name, java.lang.Object object)
获取数据: java.lang.Object getAttribute(java.lang.String name)
删除数据: void removeAttribute(java.lang.String name)
ServletContext域对象:作用范围在整个web应用中有效!!!
所有域对象:
HttpServletRequet 域对象 ServletContext域对象
HttpSession 域对象
PageContext域对象

d、 转发

RequestDispatcher getRequestDispatcher(java.lang.String path)
1)转发

    a)地址栏不会改变b)转发只能转发到当前web应用内的资源    c)可以在转发过程中,可以把数据保存到request域对象中

2)重定向

    a)地址栏会改变,变成重定向到地址。    b)重定向可以跳转到当前web应用,或其他web应用,甚至是外部域名网站。     c)不能再重定向的过程,把数据保存到request中。   结论: 如果要使用request域对象进行数据共享,只能用转发技术!!!
0 0
原创粉丝点击