ServletContext与Web应用范围

来源:互联网 发布:淘宝卖家进入 编辑:程序博客网 时间:2024/05/29 19:36

Servlet容器在启动一个Web应用时,会为它创建唯一的ServletContext对象。当Servlet容器终止一个Web应用时,就会销毁它的ServletContext对象。由此可见ServletContext对象与Web应用具有同样的生命周期。

ServletContext接口提供了一组在Web应用范围内存取共享数据的方法。“范围”在这里有两层含义:

1、表示一个特定时间段

2、表示在特定时间段内可以共享数据的所有Web组件的集合

Web应用范围具有以下两层含义:

1、表示由Web应用的生命周期构成的时间段

2、表示在Web应用的生命周期内的所有的Web组件的集合

存放在Web应用范围内的共享数据具有以下特点

1、共享数据的生命周期位于Web应用的生命周期中的一个时间片段内

2、共享数据可以被Web应用中的所有组件共享

由于ServletContext对象与Web应用具有同样长的生命周期,而ServletContext对象可以被Web应用中的所有Web组件共享,因此可以利用ServletContext对象来获取Web应用范围内的共享数据,基本思想如下:

1、面向对象编程的一个基本思想就是万物皆对象,因此,共享数据也理所当然地用java.lang.Object类型的任意Java对象来表示。

2、只要把代表共享数据的Java对象与ServletContext对象关联,该Java对象的生命周期就依附于ServletContext对象的生命周期,并且Web组件就可以通过ServletContext对象来访问它。实际上,该Java对象被存到Web应用范围内。

3、在Web应用范围内可以存放各种类型的共享数据。为了方便地存取特定的共享数据,可以把代表共享数据的Java对象作为ServletContext的属性来存到。每个属性包含一对属性名和属性值,属性值代表共享数据,属性名则用于标识共享数据。

在ServletContext接口中常用的用于存取共享数据的方法包括:

1、setArrribute(String name,Object object):向Web应用范围内存入共享数据。参数name指定属性名,参数Object指定共享数据

2、removeAttribute(String name):根据参数指定的属性名在Web应用范围内删除匹配的共享数据。

3、getAttribute(String name):根据参数给定的属性名,返回Web应用范围内匹配的共享数据。

在Web应用范围内存放共享数据的示例

许多网站都能统计特定网页被客户端访问的次数,JavaWeb应用就可以利用ServletContext来实现这一功能。

首先设计一个用于累计访问次数的计数器,用Counter类来实现。Counter类是一个普通的基于JavaBean风格的Java类。

 

public class Counter {private int count;//计数值public Counter(){this(0);}public Counter(int count){this.count=count;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}public void add(int step){count+=step;}} 

接下来把计数器存放在Web应用范围内,每当网页被客户端访问一次,计数器就会递增一次。CounterServlet类实现了向应用范围内存取计数器的功能。

 

public class CounterServlet extends HttpServlet{@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//获得ServletContext的引用ServletContext context=getServletContext();//从ServletContext中读取counter属性Counter counter=(Counter) context.getAttribute("counter");//如果ServletContext中没有counter属性,就创建counter属性if(counter==null){counter=new Counter(1);context.setAttribute("counter", counter);}response.setContentType("text/html;charset=GB2312");PrintWriter out=response.getWriter();out.println("<html><head><title>CounterServlet</title></head>");out.println("<body>");//输出当前的counter属性out.println("<h1>欢迎光临本站,您是第"+counter.getCount()+"位访问者。</h1>");out.println("</body></html>");counter.add(1);out.close();}}

CounterClearServlet类负责将Web应用范围内的计数器删除。这个Servlet类没有什么实际意义,仅仅是为了更好的理解ServletContext的作用。

public class CounterClearServlet extends HttpServlet{@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//获得ServletContext的引用ServletContext context=getServletContext();context.removeAttribute("counter");//删除counter属性PrintWriter out=response.getWriter();out.println("The counter is remove.");out.close();}}

在web.xml文件中为CounterServlet和CounterClearServlet映射的URL分别为“/counter”和“/clear”。运行示例。

(1)            启动Tomcat,在浏览器中通过http://localhost:8080/helloapp/counter访问CounterServlet。在第一次访问该Servlet时,浏览器端显示计数器的值为1.

(2)            刷新上述访问CounterServlet的页面,会看到每刷新一次,计数器的值增加1,假定最后一次刷新后的计数器的值为5

(3)            另外再打开一个新的浏览器,也访问CounterServlet,此时计数器的值为6.

(4)            在浏览器中通过http://localhost:8080/helloapp/clear访问CounterClearServlet,然后再访问CounterServlet,浏览器端显示计数器的值为1

(5)            多次刷新上述访问CounterServlet的页面,会看到每刷新一次,计数器的值会增加1,假定最后一次刷新后的计数器的值为5

(6)            终止helloapp应用,在重新启动,然后再通过浏览器访问CounterServlet,计数器的值又会被初始化为1

(7)            在<CATALINA_HOME>/webapps目录下复制helloapp应用,改名为helloapp1,并在Tomcat中发布helloapp跟helloapp1这两个应用。在两个浏览器中分别多次通过以下URL访问helloapp应用及helloapp1应用中的CounterServlet。然后再通过浏览器

两个浏览器中的计数器的数值将各自独立地递增,由此可见,这两个Web应用拥有各自独立的计数器。

通过上述实验可以看出,在ServletContext中设置的属性,在Web应用运行期间一直存在,除非通过ServletContext的removeAttribute()方法将其删除。当Web应用被终止时,Servlet容器会销毁ServletContext对象,存储在ServletContext对象中的属性自然也不复存在。不同Web应用的ServletContext对象各自独立。

使用ServletContextListener监听器

在Servlet API中有一个ServletContextListener接口,它能够监听ServletContext对象的生命周期,实际上就是监听Web应用的生命周期。

当Servlet容器启动或终止Web应用时,会触发ServletContextEvent事件,该事件由ServletContextListener来处理。在ServletContextListener接口中定义了处理ServletContextEvent事件的两个方法。

1、contextInitialized(ServletContextEvent sce):当Servlet容器启动Web应用时调用该方法。在调用完该方法之后,容器再对Filter初始化,并且对那些在Web应用启动时就需要被初始化的Servlet进行初始化。

2、contextDestroy(ServletContextEvent sce):当Servlet容器终止Web应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet和Filter过滤器。

public class MyServletContextListener implements ServletContextListener{public void contextDestroyed(ServletContextEvent sce) {System.out.println("helloapp application is Destroyed");//获得ServletContext对象ServletContext context=sce.getServletContext();//从web应用范围获得计数器对象Counter counter=(Counter) context.getAttribute("counter");if(counter!=null){try{//把计数器的数值写到count.txt文件中String filepath=context.getRealPath("/count");filepath=filepath+"/count.txt";PrintWriter out=new PrintWriter(filepath);out.println(counter.getCount());out.close();}catch(IOException e){e.printStackTrace();}}}public void contextInitialized(ServletContextEvent sce) {System.out.println("helloapp application is Initialized.");//获得ServletContext对象ServletContext context=sce.getServletContext();try{BufferedReader reader=new BufferedReader(new InputStreamReader(context.getResourceAsStream("/count/count.txt")));    int count=Integer.parseInt(reader.readLine());    reader.close();    //创建计数器对象    Counter counter=new Counter(count);    //把计数器对象保存到web应用范围    context.setAttribute("counter", counter);}catch(IOException e){e.printStackTrace();}}}


0 0
原创粉丝点击