JAVA Web知识点整理(五)

Servlet的类层次结构

(1)Servlet接口---init()方法  service()方法  destroy()方法,这三个核心方法构成了Servlet组件的生命周期

(2)ServletConfig接口---getInitParameter()方法---获取局部初始化参数

(3)GenericServlet类---普通Servlet---为Servlet接口和ServletConfig接口中的方法提供了默认实现

   这里体现缺省适配器设计模式

(4)HttpServlet类---专门用于Http协议下的Servlet---继承GenericServlet类,并提供了doGet(),doPost()等6个方法等待程序员在自定义的Servlet类中重写

Servlet的生命周期

(1)生命周期是组件在不同时间处于的不同状态,Servlet的生命周期是指Servlet组件在Web容器中从产生到销毁的完整过程

(2)Web容器负责Servlet组件的加载/实例化(new) --> 初始化(init) --> 服务(service) --> 销毁(destroy)

   其中加载、初始化、销毁只会调用一次,服务每次请求时都会被调用

Servlet的加载时机 

(1)首次访问Servlet时(第一个客户首次请求时),容器会自动实例化Servlet,并调用init()方法

(2)如果<servlet>标签中配置了<load-on-startup>子标签,则会在Web容器启动时,自动加载

   <load-on-startup>N</load-on-startup>  //这里的N是大于等于0的整数  值越小,越先加载

Servlet的销毁时机

(1)服务器停止或重启时   

(2)Servlet类的源代码被更新时

   控制台输出---INFO: Reloading Context with name [/项目名] has started,表示项目源代码更新后,重新被服务器加载

Servlet的运行机制---单实例多线程

(1)单实例---为了提高效率,每个Servlet只有一个实例,在第一次请求时被实例化;

(2)多线程---只要有客户发出请求,就创建出一个线程负责响应客户的请求,其service()方法被多个用户反复调用,直到其被销毁

解决Servlet产生的线程安全问题

(1)原因

   因为Servlet是单实例的,所以必然是以多线程的方式处理多个客户的请求,这样当多个客户同时读写Servlet对象中的成员变量时,就可能出现线程安全问题

(2)解决办法

   (2.1)使用同步代码块控制对成员变量的访问

   (2.2)不在Servlet类中使用成员变量,只使用service()方法中的局部变量   推荐

Servlet组件在web.xml文件中的配置

  <servlet>
      <servlet-name>Servlet的名称</servlet-name>
      <servlet-class>Servlet的完整类名</servlet-class>
  </servlet>

  <servlet-mapping>
      <servlet-name>Servlet的名称</servlet-name>
      <url-pattern>Servlet的URL映射模式</url-pattern>
  </servlet-mapping>

Servlet的完整执行流程 


(1)容器根据访问的完整路径URL截取出项目名后面的ServletPath作为url-pattern

(2)根据此url-pattern到web.xml文件中查找是否存在和此url-pattern匹配的<url-pattern>标签,如果找不到,则报404错误,否则找到对应的<servlet-name>子标签

(3)根据<servlet-name>的值去匹配<servlet>标签中的<servlet-name>子标签,进而找到<servlet-class>子标签,最终得到Servlet的完整类名

(4)根据Servlet的完整类名,判断Servlet的实例是否已存在,如果不存在就创建出单一的实例,并执行init()方法,相当于懒汉式单例

   如果<servlet>标签中配置了<load-on-startup>子标签,则在服务器启动时,就创建出单一的实例,并执行init()方法,相当于饿汉式单例

   这里体现单例设计模式

(5)对于客户的每一次请求,容器都会创建一个单独的线程来处理,同时创建出HttpServletRequest请求对象和HttpServletResponse响应对象,并将其作为参数传到service()方法中,service()方法内部根据具体的请求方法去调用doGet()或doPost()方法,service()方法执行结束后,服务器自动删除request对象和response对象,并将结果返回给客户端

   这里体现模板方法设计模式

(6)Servlet被重新加载时,或服务器停止或重启时,调用destroy()方法,并销毁Servlet实例

service()方法和doGet(),doPost()方法的关系  

(1)service()方法在HttpServlet父类中已经给出定义,根据不同的请求的方法去调用doGet()或doPost()方法,体现模板方法设计模式

   因此,一般情况下,只重写doGet()和doPost()方法,不要重写service()方法(因为会导致破坏了模板方法结构的设计)

(2)如果必须重写service()方法,需要在方法中手工调用super.service(request, response);

局部初始化参数---只能被当前Servlet读取到的参数

(1)定义局部参数---在<servlet>标签下面添加<init-param>

  <servlet>
       <servlet-name>...<servlet-name>
       <servlet-class>...<servlet-class>
            
    <init-param>
            <param-name>局部参数名</param-name>
                <param-value>局部参数值</param-value>
    </init-param>
   </servlet>

(2)读取局部参数

   this.getInitParameter("局部参数名");
        

全局初始化参数---能被项目中的所有Servlet读取到的参数

(1)定义全局参数---在所有<servlet>标签之外添加<context-param>标签

   <context-param>
        <param-name>全局参数名</param-name>
        <param-value>全局参数值</param-value>
   </context-param>

(2)读取全局参数

   this.getServletContext().getInitParameter("全局参数名");   //唯一的全局参数从ServletContext(即application对象)中获取

 

posted @ 2021-02-05 11:10  别无所求---  阅读(83)  评论(0编辑  收藏  举报