ServletContext是Servlet与Servlet容器之间直接通信的接口。Servlet容器在启动一个Web应用时,会为它创建一个ServletContext对象。每个Web应用都有唯一的ServletContext对象,可以把Servlet对象形象的理解为Web应用的总管家,同时一个Web应用中的所有Servlet对象都共享一个ServletContext,所有的Servlet对象都可以通过ServletContext来访问容器中的各种资源。当Servlet容器终止一个Web应用时,就会销毁它的ServletContext对象,由此可见,ServletContext对象与Web应用具有同样的生命周期。

在ServletContext对象中提供了一组在Web应用范围内存取共享数据的方法。"范围"在这里有两层含义:

●  表示一个特定时间段。

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

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

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

●  示在Web应用的生命周期内所有Web组件的集合。

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

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

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

如何实现向Web应用范围内存取共享数据呢?由于ServletContext对象具有Web应用同样常的生命周期,而且ServletContext对象可以被Web应用中的所有Web组件共享,因此可以利用ServletContext对象来存取Web应用范围内的共享数据,基本思想如下:

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

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

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

在ServletContext对象中常用的用于存取共享数据的方法包括以下几种:

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

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

●  removeAttribute(String name):根据参数给定的属性名,从Web应用范围内删除匹配的共享数据。

接下来介绍一个向Web应用范围内存放共享数据的范例。许多网站都能统计特定网页被客户端访问的次数,JavaWeb应用就可以利用ServletContext来实现这一功能。

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

public class Countter{

private int count; //计数值

public Counter(){

this(0);

}

public Counter(int count){

this.count = count;

}

public void setCount(int count){

this.count = count;

}

public int getCount(){

return count;

}

public void add(int step){

count+=step;

}

}

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

public class CounterServet extends HttpServlet{

public void service(HttpServletRequest request,

HttpServletResponse response)throws ServletException,IOException{

ServletContext sc = this.getServletContext();

Counter counter = (Counter)sc.getAttribute("counter");

if(counter==null){

counter = new Counter(1);

sc.setAttribute("counter",counter);

}

response.setContentType("text/html;charset=utf-8");

PrintWriter out = response.getWriter();

out.println("欢迎光临本网站。您是第" + counter.getCount() + "位访问者");

counter.add(1);

out.close();

}

}

以上代码在ServletContext中设置了一个Counter类型的属性。属性名为counter,CounterServlet的service()方法从ServletContext中读取counter属性。如果counter属性不存在,那么就创建一个Counter对象,把它作为counter属性存放在ServletContext中,即把代表计数器的Counter对象存放在Web应用范围内。service()方法接下来向客户端输出当前Counter对象的计数值,然后将Counter对象的计数值加1。

下面的CounterClearServlet类负责将Web应用范围内的计数器删除,这个Servlet类没有什么实际的意义,仅仅为了进一步帮助大家理解ServletContext的作用。

public class CounterClearServlet{

public void service(HttpServletRequest request,

HttpServletResponse response)throws ServletException,IOException{

ServletContext sc = this.getServletContext();

sc.removeAttribute("counter");

PrintWriter out = response.getWriter();

out.println("The counter us removed.");

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.停止Tomcat服务器,在重新启动Tomcat服务器,然后在通过浏览器访问CounterServlet,计数器的值又被初始化为1。

7.赋值helloapp应用到Tomcat服务器中并改名为hellpapp2,启动Tomcat服务器,此时在服务器中已经有了两个应用,helloapp和helloapp2,在两个浏览器中分别多次通过以下URL访问helloapp应用以及helloapp2应用中的CounterServlet:

http://localhost:8080/helloapp/counter

http://localhost:8080/helloapp2/counter

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

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

Servlet容器运行时Web应用中的各个Java对象之间的关系

从上图可以看出,在helloapp应用中,CounterServlet和CounterClearServlet对象共享一个ServletContext对象,因此也共享与ServletContext对象关联的Conter对象,这种对象之间的关系同样适用于helloapp2应用。

使用ServletContextListener监听器

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

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

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

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

下面通过一个例子来介绍ServletContextListener的用法。前面案例中的CounterServlet类只能统计当Web应用启动后,网页被客户端访问的次数。如果重启Web应用,计数器又会重新从1开始统计访问次数。在实际应用中,往往需要统计自Web应用被发布后网页被客户端访问的次数,这就要求当Web应用被终止时,计数器的数值被永远存储在一个文件中或者数据库中,等到Web应用重新启动时,先从文件或数据库中读取计数器的初始值,然后在此技术上继续计数。

向文件中写入或读取计数器的数值的功能可以由自定义的MyServletContextListener类来完成,它具有以下功能:

在Web应用启动时从文件中读取计数器的数值,并把表示计数器的Counter对象存放为Web应用范围内,存放计数器的文件的路径为helloapp/count/count.txt

在Web应用终止时把Web应用范围内的计数器的数值保存到counter.txt文件中。

public class MyServletContextLinstener extends ServletContextListener{

public void contextInitialized(ServletContextEvent sce){

System.out.println("hellpapp application is Initialized");

ServletContext sc = sce.getServletContext();

try{

BufferedReader reader = new BufferedReader

(new InputStreamReader (sc.getResourceAsStream

("/counte/count.txt")));

int count = Integer.parseInt(reader.readLine());

reader.close();

Counter counter = new Counter(count);

sc.setAttribute("counter",counter);

}catch(IOException e){

e.printStackTrace();

}

}

public void contextDestroyed(ServletContextEvent sce){

System.out.println("helloapp application is Destroyed.");

ServletContext sc = sce.getServletContext();

Counter counter = (Counter)sc.getAttribute("counter");

if(counter!=null){

try{

String filepath = sc.getRealPath("/count");

filepath = filepath +"/count.txt";

PrintWriter pw = new PrintWriter(filepath);

pw.println(counter.getCount());

pw.close();

}catch(IOException e){

e.printStackTrace();

}

}

}

}

用户自定义的MyServletContextListener监听器只有先向Servlet容器注册,Servlet容器在启动或终止Web应用时,才会调用该监视器的相关方法,在web.xml文件中,<listener>元素用于向容器中注册监听器:

<listener>

<listener-class>com.xdl.MyServletCountextListener</listener-class>

</listener>

下面按如下步骤演示MyServletContextListener监听器的作用。

1.在helloapp/count目录下创建count.txt文件,在该文件中存放了一个数字"5",

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

3.刷新上述访问CounterServlet的页面,会看到每刷新一次,计数器的值增加1,假定最后一次刷新后的计数器的值为10。

4.停止Tomcat服务器,查看helloapp/count/count.txt文件,会发现在该文件中存放的数字变为10.

5.启动Tomcat服务器,在浏览器中再次访问CounterServlet,当第一次访问该Servlet时,浏览器端显示计数器的值为10。

从上面的案例中可以看出,MyServletContextListener监听器与CounterServlet共享Web应用范围内的代表计数器的Counter对象。监听器在Web应用启动或终止时会操纵Counter对象,而Servlet在每次响应客户请求时会操纵Counter对象。

IT兄弟连 JavaWeb教程 ServletContext对象的更多相关文章

  1. IT兄弟连 JavaWeb教程 JSP内置对象经典面试题

    1.请说明cookie.request.session.application的作用域和声明周期? 并说明它们适用与什么场景? request的生命周期是一次请求.可以用于JSP表单提交数据. ses ...

  2. IT兄弟连 JavaWeb教程 监听器1

    1  基本概念 监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动.监听器其实就是一个实现特定接口的普通java程序,这个程序 ...

  3. IT兄弟连 JavaWeb教程 Servlet API

    Java Servlet是运行在带有支持Java Servlet规范的解释器的web服务器上的Java类. Servlet可以使用javax.servlet和javax.servlet.http包创建 ...

  4. IT兄弟连 JavaWeb教程 异步请求对象的API

    Ajax的核心是XMLHttpRequest对象(xhr),xhr为向服务器发送请求和解析服务器响应提供了接口,能够以异步的方式从服务器获取新数据. xhr的主要方法有: ●  void open(S ...

  5. IT兄弟连 JavaWeb教程 创建异步请求对象

    异步请求对象:XMLHttpRequest对象,通过该对象向服务器发送异步请求.它是异步请求的技术,所有的现代浏览器(IE7+.FireFox.Chrome.Safari以及Opera)都支持,老版本 ...

  6. IT兄弟连 JavaWeb教程 EL表达式中的内置对象

    EL语言定义了11个隐含对象,它们都是java.util.Map类型,网页制作者可通过它们来便捷地访问Web应用中的特定数据.表1对这11个隐含对象做了说明. 1  EL表达式中的内置对象 这11个隐 ...

  7. IT兄弟连 JavaWeb教程 EL表达式获取对象的属性以及数组的元素

    使用${对象名.属性名} EL表达式语言可以使用点号运算符"."来访问对象的属性,例如表达式${customer.name}表示customer对象的name属性. 使用${对象名 ...

  8. IT兄弟连 JavaWeb教程 JSP内置对象经典案例

    案例需求:使用MVC模式编写一个程序当发起一个deptList.do请求时在servlet中准备一个部门列表对象,把这个列表对象放入request作用域中,然后转发到deptlist.jsp,使用js ...

  9. IT兄弟连 JavaWeb教程 JSP内置对象3

    读取web.xml配置信息的config对象 config对象主要用于取得服务器的配置信息.通过pageContxt对象的getServletConfig()方法获取一个config对象.当一个Ser ...

随机推荐

  1. 如何干掉那些.ipch 与 .sdf文件

    参考资料: http://blog.163.com/yangjun1988422@126/blog/static/47412917201074446054/     vs2010中臃肿的ipch和sd ...

  2. Photoshop 更改图片颜色

    程序猿兼职美术的常常没有时间搞太多图片.我们能够一张图片更改主要颜色来到达目的.我知道的主要有2种方法,1是更改色相,2是替换颜色.直接用油漆桶仅仅能在异常简单的图片才干用. 1. 更改色相      ...

  3. USB/IP项目总结

    青云最近推出了云桌面功能,用户可以像使用本地计算机一样访问远程主机,支持USB重定向,不禁让我想起了2年前调试的一个开源项目USB/IP,当时还用英文写了一个总结性文档,放在这里方便以后查看.     ...

  4. OOP思想又一随笔

    现有类再有对象, 类:对现实世界事物的抽象表示,包括事物的状态信息(成员变量)和行为信息(成员方法).我们要让我们的计算机程序设计更有意思,也更有逻辑性,则我们的程序中对事物的描叙就必须符合真实情况, ...

  5. 浅谈JavaScript的函数表达式(闭包)

    前文已经简单的介绍了函数的闭包.函数的闭包就是有权访问另一个函数作用域的函数,也就是函数内部又定义了一个函数. var Super=function(num){ var count=num; retu ...

  6. ARC机制之__strong具体解释

    ARC机制之__strong具体解释 __strong  解析: 默认情况下,一个指针都会使用 __strong 属性,表明这是一个强引用.这意味着,仅仅要引用存在,对象就不能被销毁.这是一种所期望的 ...

  7. Mysql性能优化笔记

    一,索引 1.Innodb索引使用的是B+树 2.尽量简化where条件,比如不要出现 where id + 3 = 5,这无法使用索引 3.索引很大时,可以冗余一列来模拟哈希索引 4.小的表不需要使 ...

  8. Region Range

    三篇文章了解 TiDB 技术内幕 - 说存储| PingCAP https://pingcap.com/blog-cn/tidb-internal-1/ 对于一个 KV 系统,将数据分散在多台机器上有 ...

  9. ios 关于动画用法的总结

      #import "FirstVC.h" @implementation FirstVC /*     创建xib过程     1 创建xib(名字和类名相同)     2 文件 ...

  10. react native 中的redux

    一.使用redux 的条件: 1.某个组件的状态,需要共享: 2.某个状态需要在任何地方都可以拿到: 3.一个组件需要改变全局状态: 4.一个组件需要改变另一个组件的状态. redux   说明白点, ...