IT兄弟连 JavaWeb教程 ServletContext对象
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对象的更多相关文章
- IT兄弟连 JavaWeb教程 JSP内置对象经典面试题
1.请说明cookie.request.session.application的作用域和声明周期? 并说明它们适用与什么场景? request的生命周期是一次请求.可以用于JSP表单提交数据. ses ...
- IT兄弟连 JavaWeb教程 监听器1
1 基本概念 监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动.监听器其实就是一个实现特定接口的普通java程序,这个程序 ...
- IT兄弟连 JavaWeb教程 Servlet API
Java Servlet是运行在带有支持Java Servlet规范的解释器的web服务器上的Java类. Servlet可以使用javax.servlet和javax.servlet.http包创建 ...
- IT兄弟连 JavaWeb教程 异步请求对象的API
Ajax的核心是XMLHttpRequest对象(xhr),xhr为向服务器发送请求和解析服务器响应提供了接口,能够以异步的方式从服务器获取新数据. xhr的主要方法有: ● void open(S ...
- IT兄弟连 JavaWeb教程 创建异步请求对象
异步请求对象:XMLHttpRequest对象,通过该对象向服务器发送异步请求.它是异步请求的技术,所有的现代浏览器(IE7+.FireFox.Chrome.Safari以及Opera)都支持,老版本 ...
- IT兄弟连 JavaWeb教程 EL表达式中的内置对象
EL语言定义了11个隐含对象,它们都是java.util.Map类型,网页制作者可通过它们来便捷地访问Web应用中的特定数据.表1对这11个隐含对象做了说明. 1 EL表达式中的内置对象 这11个隐 ...
- IT兄弟连 JavaWeb教程 EL表达式获取对象的属性以及数组的元素
使用${对象名.属性名} EL表达式语言可以使用点号运算符"."来访问对象的属性,例如表达式${customer.name}表示customer对象的name属性. 使用${对象名 ...
- IT兄弟连 JavaWeb教程 JSP内置对象经典案例
案例需求:使用MVC模式编写一个程序当发起一个deptList.do请求时在servlet中准备一个部门列表对象,把这个列表对象放入request作用域中,然后转发到deptlist.jsp,使用js ...
- IT兄弟连 JavaWeb教程 JSP内置对象3
读取web.xml配置信息的config对象 config对象主要用于取得服务器的配置信息.通过pageContxt对象的getServletConfig()方法获取一个config对象.当一个Ser ...
随机推荐
- mybatis 一对一映射
xml <mapper namespace="com.oracle.dao.one2oneDao"> <sql id="personColum" ...
- 混合minxins
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 原生js实现悬浮框滑动动画
最近在做个人博客想做个相册,鼠标悬浮后出现个div并且鼠标移动到哪个相册,div跟随到哪个相片上. <!DOCTYPE html> <html lang="en" ...
- (转) Universal-Image-Loader使用大全(史上最屌)
转载自http://blog.csdn.net/zenjj11/article/details/38728481 项目介绍: Android上最让人头疼的莫过于从网络获取图片.显示.回收,不论什么一个 ...
- Linux安装配置Redis CentOS 7 下安装Redis
Redis是一个高性能的,开源key-value型数据库.是构建高性能,可扩展的Web应用的完美解决方案,可以内存存储亦可持久化存储.因为要使用跨进程,跨服务级别的数据缓存,在对比多个方案后,决定使用 ...
- CString转换成char *字符串问题
buf = (LPSTR)(LPCTSTR)str; ==> buf 显示的是第一个字符 strcpy(pNumber,strNumber); ==> e ...
- Android GUI系统学习1:Gralloc
Gralloc模块是从Android Eclair(android 2.1)開始增加的一个HAL模块,Gralloc的含义为是Graphics Alloc(图形分配).他对上为libui提供服务,为其 ...
- iptables apache2
Apache2 iptables 安装指令:sudo apt-get install apache2 2.产生的启动和停止文件是:/etc/init.d/apache2 3.启动:sudo apach ...
- Spring源码深度解析——笔记
1.spring容器的基本用法 xml配置 <bean id="myTestBean" class="bean.MyTestBean"/> 调用 B ...
- hadoop 一些文件操作
在HDFS上面,FileSystem创建目录 复制本地文件到HDFS 获取集群中的节点