(3)servlet单例问题、load-on-startup、ServletConfig

细节4servlet单例问题
①当servlet被第一次访问后,就被加载到内存,以后该实例对各个请求服务,即在使用中是单例的(可以设置全局变量i,然后再doget中i++,并输出该i,则在不同浏览器中或者不同的用户都能看到i加后的结果,并且i就像共享变量一样都能访问i不断加后的结果)。
②因为servlet是单例,因此会出现线程安全问题。这个实例在web退出/reload时实例才会消失。
③在servlet的整个生命周期内,servlet的init方法只被调用一次。对一个servlet的每次访问请求都导致servlet引擎调用一次servlet的service方法。每次访问请求,servlet引擎都会创建一个新的httpservletrequest请求和一个新的httpservletresponse响应对象,然后将这两个对象作为参数传递给它调用的service()方法,service方法再根据请求方式分别调用doxxx方法。
线程安全解决原则:
(1)如果一个变量需要多个用户共享(共享变量),则应该在访问该变量的时候,加同步机制
synchronized(对象){共享变量代码}
(2)如果一个变量不需要共享,则只需在doGet或者doPost中定义即可,也不会出现线程不安全问题,是个局部变量
细节5:load-on-startup配置
load-on-startup配置,中的数据代表init执行次序
需求:当网站启动的时候,可能需要初始化一些数据(比如创建临时表、网站有一些定时完成的任务(定时写日志、定时备份数据库、定时发送邮件))
解决方法:可以通过load-on-startup和线程知识搞定
先说明load-on-startup,通过配置load-on-startup我们可以指定某个servlet自动创建。

//简单理解
public void init() throws ServletException {
        System.out.println("inti被执行......");
    }
 <servlet>
    <servlet-name>demo2</servlet-name>
    <servlet-class>com.TongPeiFu.demo2</servlet-class>
    <!-- 1表示init启动的顺序 -->
    <load-on-startup>1</load-on-startup>
  </servlet>

需求:模拟电子邮件定时发送

public class sendemailThread extends Thread {
    public void run()
    {
        int  i=0;
        try{
            while(true){
            Thread.sleep(10*1000);
            System.out.println("发出第"+(++i)+"邮件");
            }
        }catch(Exception e){
            e.printStackTrace();

        }

    }
}
public class demo2 extends HttpServlet {
public void init() throws ServletException {
        System.out.println("inti被执行......");
        //创建一个线程
        sendemailThread s=new sendemailThread();
        s.start();
      }
    }
public class demo3 extends HttpServlet {
    public void init() throws ServletException {
        System.out.println("demo3   inti被执行......");
    }

}
<servlet>
    <servlet-name>demo2</servlet-name>
    <servlet-class>com.TongPeiFu.demo2</servlet-class>
    <!-- 1表示init启动的顺序 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>demo3</servlet-name>
    <servlet-class>com.TongPeiFu.demo3</servlet-class>
    <load-on-startup>2</load-on-startup>

  </servlet>

细节6:ServletConfig对象:读取servlet的配置信息
这里写图片描述

public class configTest extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

         response.setContentType("text/html");

          String encoding1=this.getServletConfig().getInitParameter("encoding");
          response.setCharacterEncoding(encoding1);
          response.getWriter().println("编码是:"+encoding1);
    }
}
  <servlet>
    <servlet-name>configTest</servlet-name>
    <servlet-class>com.TongPeiFu.configTest</servlet-class>
    <!-- 这里可以给servlet配置信息,这里配置的信息,只能被该servlet读取 -->
    <init-param>
       <param-name>encoding</param-name>
       <param-value>UTF-8</param-value>
    </init-param>
  </servlet>

补充说明①:这种配置参数的方式,只能被某个servlet独立使用,若希望让所有的servlet都读取某个参数,则如下配置:

<!-- 这里配置的参数,可以被所有的servlet读取 -->
<context-param>
  <param-name></param-name>
  <param-value></param-value>
</context-param>

补充说明②:可以读取所有的配置信息,使用如下方法getInitParameterNames()

  <servlet>
    <servlet-name>configTest</servlet-name>
    <servlet-class>com.TongPeiFu.configTest</servlet-class>
    <!-- 这里可以给servlet配置信息,这里配置的信息,只能被该servlet读取 -->
    <init-param>
       <param-name>encoding</param-name>
       <param-value>UTF-8</param-value>
    </init-param>

    <init-param>
      <param-name>version</param-name>
      <param-value>1.0</param-value>
    </init-param>
    <init-param>
    <param-name>author</param-name>
    <param-value>zhangsan</param-value>
    </init-param>
  </servlet>

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

     response.setContentType("text/html"); 
      Enumeration<String> names=this.getServletConfig().getInitParameterNames();
      while(names.hasMoreElements())
      {
          String name=names.nextElement();
         String value=this.getServletConfig().getInitParameter(name);
         response.getWriter().println("name:"+name+"-----"+"value:"+value);

      }
}
posted @ 2017-08-26 21:04  测试开发分享站  阅读(100)  评论(0编辑  收藏  举报