zoukankan      html  css  js  c++  java
  • 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对象)中获取
  • 相关阅读:
    VC2013一些感受
    第三周 分析程序题
    进度条——持续更新
    怪自己,不怪书
    源程序版本管理软件和项目管理软件
    学习进度条
    个人最终总结
    win8以上windows系统eclipse环境下图片显示乱码问题解决
    黄金点游戏
    编码用命令行执行的C语言词语统计程序
  • 原文地址:https://www.cnblogs.com/sheng-se/p/14376628.html
Copyright © 2011-2022 走看看