作者:禅楼望月(http://www.cnblogs.com/yaoyinglong

1. ServletConfig和ServletContext

1.1 ServletConfig和ServletContext配置和使用

一些和业务逻辑无关的信息不应该放在硬编码到程序中,一般将其放在ServletConfig或ServletContext。

在web.xml文件中配置ServletConfig和ServletContext参数:

<!-- 配置ServletContext参数 -->
<context-param>
      <param-name>email</param-name>
      <param-value>yaoyinglong@gmail.com</param-value>
</context-param>
<servlet>
  <servlet-name>Test</servlet-name>
  <servlet-class>com.yyl.Test</servlet-class>
  <!-- 配置ServletConfig参数 -->
  <init-param>
        <param-name>email</param-name>
        <param-value>yaoyinglong@gmail.com</param-value>
    </init-param>
</servlet>

我们可以清楚的看到:ServletConfig参数配置在<servlet> 节点内部;而ServletContext参数配置在<servlet> 节点外部。

使用ServletConfig和ServletContext参数:

String servletConfigEmail=getServletConfig().getInitParameter("email");
String servletContextEmail=getServletContext().getInitParameter("email");

不用说大家值也只那行去那个参数了。

ServletConfig和ServletContext参数的使用范围:

ServletConfig参数:

①只可以在配置了它的servlet中可用;

②在Java对象变为Servlet之前不可用(init函数有两个版本,一般情况下不要覆盖接受ServletConfig对象的那个版本吗,即是要覆盖也应该加上super.init(ServletConfig))。

③ServletConfig参数只在Servlet初始化是读取一次,中途不能修改。

ServletContext对Web应用中的所有servlet和JSP都可用。

1.2 ServletConfig和ServletContext举例

这两个对象非常重要,当我们程序需要读取配置文件的时候便可以将在这里配置配置文件的路径,下面以Spring配置来说明:

我们如果通过MyEclipse使用Spring框架时,它会帮我们将Spring配置好,无需劳您大驾亲自动手,但是如果你使用的是Eclipse的时候,抱歉,它可没那么贴心了,只能我们自己手动来配了,无论是IDE帮我们配还是我们自己手动来陪,很多时候都是Ctrl+C和Ctrl+V,可是你知道Spring是怎么做的吗?知道的请略过,或者您可以看看我说的是不是正确,指出错误之处(感激不尽!!!,不知道的就请跟着我一起看看吧:

首先来看为什么要在web.xml中配置Spring:

不在web.xml中配置Spring时,我们要获取配置在Spring的bean时我们是这样做的:

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        BeanFactory beanFactory=new ClassPathXmlApplicationContext("appclicationContext.xml");
        beanFactory.getBean("beanId");
    }
}

C/S端可以这么做,那么B/S端呢?我们可以用一个Servlet来实现:

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    BeanFactory beanFactory=new ClassPathXmlApplicationContext("applicationContext.xml");
    getServletContext().setAttribute("beanFactory", beanFactory);
}

这样配置了之后,在Web应用的所有JSP和Servlet中都可以使用BeanFactory了。

还有一种配置方式就是我们下面要讲到的监听器(可以先看一下下面的内容在回来):

@Override
public void contextDestroyed(ServletContextEvent sce) {
    BeanFactory beanFactory=new ClassPathXmlApplicationContext("applicationContext.xml");
    sce.getServletContext().setAttribute("beanFactory", beanFactory);
}

大家有没有发现无论用什么方法配,代码都是一样的。Spring框架开发者,也发现了这件事情,于是他们就把这件事情给做了(他们提供了后两种的实现),我们都知道,Servlet和监听器都是要在web.xml中配置的。因此我们工作就是把Spring框架开发者帮我们实现好的Servlet和监听器配置到web.xml中。

注:我这里只是简单的说明最核心的部分,强大的Spring要做的工作远比我这里做的多的多,并且我这里将application.xml配置文件的路径硬编码到了程序里,这是不好的,应该使用我们现在讲的ServletConfig和ServletContext参数配置到xml文件中。

我们看看Spring到底是怎么做的:

哈哈,我没有骗大家吧,Spring为我们实现了Servlet和Listener的配置方式。不过大多数情况下我们都是用Listener来配置的。那我们进到这个监听器中看看:

public class ContextLoaderListener implements ServletContextListener {
    private ContextLoader contextLoader;
    public void contextInitialized(ServletContextEvent event) {
        this.contextLoader = createContextLoader();
        this.contextLoader.initWebApplicationContext(event.getServletContext());
    }
    protected ContextLoader createContextLoader() {
        return new ContextLoader();
    }
    public ContextLoader getContextLoader() {
        return this.contextLoader;
    }
    public void contextDestroyed(ServletContextEvent event) {
        if (this.contextLoader != null) {
            this.contextLoader.closeWebApplicationContext(event.getServletContext());
        }
    }
}

我们发现他在Web应用启动时,做了两件事情:创建ContextLoader类,然后调用它的initWebApplicationContext方法,进入该方法:

public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
            throws IllegalStateException, BeansException {
        // 考虑到篇幅的太大故将一些我们暂时不关心的部分删掉了……
        try {
            // Determine parent for root web application context, if any.
            ApplicationContext parent = loadParentContext(servletContext);
            // Store context in local instance variable, to guarantee that
            // it is available on ServletContext shutdown.
            this.context = createWebApplicationContext(servletContext, parent);
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
            currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
            // 考虑到篇幅的太大故将一些我们暂时不关心的部分删掉了……
    }

从黄底加粗的代码中我们可以清楚的看到:先创建了WebApplicationContext对象,然后将其保存到了servletContext中(即Application范围内)。以后Struts2和Spring继承插件就可以从Application中获取BeanFactory,通过BeanFactory取得Ioc容器中的Actoin对象,这样Action的依赖对象都会被注入。

那么我再跟踪createWebApplicationContext函数:

protected WebApplicationContext createWebApplicationContext(
            ServletContext servletContext, ApplicationContext parent) throws BeansException {
        Class contextClass = determineContextClass(servletContext);
            // 考虑到篇幅的太大故将一些我们暂时不关心的部分删掉了……
               ConfigurableWebApplicationContext wac =
                (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
        wac.setParent(parent);
        wac.setServletContext(servletContext);
        //这里读取web.xml文件中的 <context-param>节点中的值
        wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM));
        customizeContext(servletContext, wac);
        wac.refresh();
        return wac;
    }

从黄底加粗的代码指示我们必须在web.xml文件中配置<context-param>参数,至于配什么呢,<param-value>参数的值我们知道,肯定是要applicationContext.xml文件的路径,参数的名字是什么呢?往后看,它从那个参数读,我们就用那个参数组为的<param-name>值。

查看CONFIG_LOCATION_PARAM常量:

所以我们的<param-name>的值为contextConfigLocation。

诶!前面我们不是说创建BeanFactory吗?怎么这里创建的是WebApplicationContext呢?经跟踪发现它继承自BeanFactory,主要使用BeanFactory的getBean方法来获取Bean。

这下明白我在web.xml中使用监听器配置Spring的含义了吧。

那么如果我们使用Servlet怎么配置呢?(不懂的可以留言,这里就不浪费篇幅了)。

1.3 ServletContext不是线程安全的

应用中的每一部分都能访问到ServletContext,因此,必要时应该对其同步:

synchronized (getServletContext()) {
    //业务逻辑代码
}

2. 监听器(Listener)

所谓监听者就是,当你做某一件事情的时候,另一个类关注着你,并且采取相应的行动。

2.1 ServletContextListener

查看API可知,它监听Web应用初始化和Web应用销毁动作,那我们就可以指示该监听者,在Web应用初始化和Web应用销毁时帮我们干我们想干的事情:

public class TestServletContextListener implements ServletContextListener {
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("Oh,my god! I was killed");
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("houhou, God created me");
        String email=sce.getServletContext().getInitParameter("email");
        System.out.println("My Email is "+email);
    }
}

这样它就能听我们的话了吗?还不行,因为Tomcat不会看你实现了ServletContextListener接口就会让它去监视Web应用的初始化和销毁。Tomcat只会处理你在web.xml文件中配置了的事情。因此还需在web.xml中配置监听:

在节点下添加:

<listener>
      <listener-class>com.yyl.TestServletContextListener</listener-class>
  </listener>

现在配置就完成了,ServletContextListener的实现者已经为我所用了,不行你看看:

当我启动Tomcat时:

当我们关闭Tomcat时:

到这里您是不是有个疑问:Tomcat怎么知道你配的这个com.yyl.TestServletContextListener是用来监听Web应用的创建于销毁动作呢,即这个监听者是ServletContext监听者?因为Servlet还有很多其他监听者(后面会一一登场亮相)。这是因为Web容器会会检查类,检查它继承了那个监听接口,或者多个监听接口,据此明确它来监听什么类型的事件。

3. 监听器有8种(8种接口)

ServletContextAttributeListener:监听在ServletContext对象中添加、删除、替换属性的动作。

HttpSessionListener:监听Web应用Session的创建于销毁。据此可以知道有多少并发用户。

ServletRequestListener:监听浏览器请求Servlet动作。

ServletRequestAttrubuteListener:监听在ServletRequest对象中请求中添加、删除、替换属性的动作。

HttpSessionBindingListener:属性本身在被添加到session中或从session中删除时得到通知。

HttpSesionAttributeListener:监听在HttpSession中增加、删除、替换属性的动作。

servletContextListener:监听Web应用创建或撤销动作。

HttpSessionActivationListener:当一个Session被迁移到另一个JVM中通知实现了该接口的属性做好准备。

今天实在没有精力一一举例了,下篇吧!

3 Servlet监听器的更多相关文章

  1. servlet监听器Listener(理论+例子)

    Listener采用了观察者模式(24种模式之一),Listener是servlet的监听器,他可以监听客户端的请求.服务器端的操作等, 通过监听器,可以自动激发一些操作.比如:监听在线用户数量 当增 ...

  2. [原创]java WEB学习笔记47:Servlet 监听器简介, ServletContext(Application 对象), HttpSession (Session 对象), HttpServletRequest (request 对象) 监听器,利用listener理解 三个对象的生命周期

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  3. JSP的Servlet监听器

    JSP的Servlet监听器 来源: http://blog.csdn.net/phoenix_17th/article/details/3868670 Servlet 监听器用于监听一些重要事件的发 ...

  4. Java进阶(十三)servlet监听器

    servlet监听器 Listener是Servlet的监听器,它可以监听客户端的请求.服务端的操作等.通过监听器,可以自动激发一些操作,比如监听在线的用户的数量.当 增加一个HttpSession时 ...

  5. 【Servlet】1、Servlet监听器及相关接口

    Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前.发生后可以做一些必要的处理. 接口: 目前Servlet2.4和JSP2.0总共有8个监听器接口和6个Event类,其中Ht ...

  6. Servlet监听器统计在线人数

    监听器的作用是监听Web容器的有效事件,它由Servlet容器管理,利用Listener接口监听某个执行程序,并根据该程序的需求做出适应的响应. 例1 应用Servlet监听器统计在线人数. (1)创 ...

  7. Servlet监听器的使用

    Servlet监听器的使用 制作人:全心全意 在Servlet技术中已经定义了一些事件,并且可以针对这些事件来编写相关的事件监听器,从而对事件做出相应的处理.例如,想要在Web应用程序启动和关闭时来执 ...

  8. Servlet监听器——实现在线登录人数统计小例子

    一.概念 servlet监听器的主要目的是给web应用增加事件处理机制,以便更好的监视和控制web应用的状态变化,从而在后台调用相应处理程序. 二.监听器的类型 1.根据监听对象的类型和范围,分为3类 ...

  9. 【Servlet】Servlet监听器

    一.Servlet监听器的概念 Servlet监听器是Servlet规范中定义的一种特殊类,用于监听ServletContext.HttpSession和ServletRequest等域对象的创建与销 ...

  10. Servlet监听器详解及举例

    监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行. 监听器原理 监听原理 1.存在事件源 ...

随机推荐

  1. 用Task代替TheadPool

    TheadPool的问题 不支持线程的取消.完成.失败通知等交互性操作 不支持线程执行先后次序 using System; using System.Diagnostics; using System ...

  2. Number Range 管理之并行缓冲

    Number Range 管理之并行缓冲: 常用的事务代码SNRO,SM56还有一些业务专用的号码管理,可以在SPRO中查找: SNRO :Number Range 管理 一般的操作是维护号码范围.如 ...

  3. Spring3 整合MyBatis3 配置多数据源 动态选择SqlSessionFactory

    一.摘要 上两篇文章分别介绍了Spring3.3 整合 Hibernate3.MyBatis3.2 配置多数据源/动态切换数据源 方法 和 Spring3 整合Hibernate3.5 动态切换Ses ...

  4. 简单谈谈Resource,Drawable和Bitmap之间的转换

    一直接触这些东西,还是归个类整理一下比较好. Resource -> Drawable Drawable draw1 = this.getResources().getDrawable(R.dr ...

  5. Windows KB2984972安装后堵住了一个windows 7 桌面可以多个用户远程访问桌面的漏洞。

    之前网络上有方法可以实现2个用户同时使用一个windows 7,一个在终端,一个通过远程桌面. 安装了这个kb后,就无法同时登陆了,同一时间只有一个用户可以登陆windows 7

  6. 利用print2flashsetup.exe文档转swf

    通过使用Print2Flash您可以轻松的将您的文档转换成真正的Adobe Flash格式,最好的保证您的内容将实际可见,与其他格式相比,它并不存在查看工具的安装问题. Print2Flash中有一个 ...

  7. Win7 安装Apache 2.2.4报错:<OS 5>拒绝访问. :Failed to open the WinNT service manager

    Apache 2.2安装档与win7的“用户账户控制”冲突,所以只要先关闭,安装完后再开启即可. 重启,然后再重新安装Apache2.2.4,没有出现错误.然后再把上述设置改回去. 参考:http:/ ...

  8. 分享一个web应用程序池管理工具

    因为项目在联调阶段由于各种各样的原因需要重启应用程序池,而调试服务器基本都需要远登操作.同样的情况也会发生在线上,如果公司权限控制得比较严格,每次都要多部门的服务器权限申请的话有点麻烦, 所以抽点时间 ...

  9. struts2:遍历自定义字符串数组,遍历Action实例所引用对象中的数组

    在struts2:OGNL表达式,遍历List.Map集合:投影的使用一文中已经讲述了OGNL遍历List.Map集合等功能. 本文简单写一个遍历数组的示范程序. 1. 遍历自定义字符串数组 < ...

  10. MiniCrowler

    MiniCrawler Github Path : https://github.com/LixinZhang/miniCrowler Introduction: MiniCrawler is a s ...