监听器Listener

一,监听器

监听器就是监听一个对象的状态变化的组件,它主要作用就是当这些绑定着监听器的对象发生监听器所关注的变化时调用我们写的代码。比如js中按钮的点击事件。JAVA服务器中域对象的创建与销毁以及属性变化.


二,JAVAWEB服务器中的监听器有哪些?
JAVAweb服务器中主要有6+2个监听器,6表示的是分别对三个域对象的状态变化进行监听。即ServletContext,HttpSession,ServletRequest三个域对象。2表示与session绑定的对象的监听器,叫对象感知监听器。

三,6个域对象状态变化监听器
每个域对象的监听器分为两种:
1,监听对象的创建与销毁
2,监听对象的属性变化,即做了attribute的操作,比如当setAttribute时自动做我们设定好的操作。

ServletContext

HttpSession

ServletRequest

监听对象的创建与销毁

ServletContextListener

HttpSessionListener

ServletRequestListener

监听对象的属性变化

ServletContextAttributeListener

HttpSessionAttributeListener

ServletRequestAttributeListener

域对象状态变化监听器的实现步骤
1,ServletContextListener监听对象的创建和销毁
(1)创建一个类实现ServletContextListener
(2)重写接口的方法
(3)配置web.xml

public class ListenerDemo implements ServletContextListener {
    @Override
    //监听ServletContextListener创建的方法
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext创建");
    }
    @Override
    //监听ServletContextListener销毁的方法
    public void contextDestroyed(ServletContextEvent sce){
        System.out.println("ServletContext销毁");
    }
}

然后配置web.xml

<listener>
    <!--监听类的全包名-->
        <listener-class>listener.ListenerDemo</listener-class>
    </listener>

ServletContext域是在服务器启动时创建,关闭时销毁。所以我们启动服务器和关闭服务器时就会自动调用ServletContextListener监听器的监听创建和监听销毁的方法

启动服务器,效果如下,可以看到自动执行了监听创建的方法

java 如何监听实体类属性变化 java监听对象属性值变化_监听器


关闭服务器效果如下:

java 如何监听实体类属性变化 java监听对象属性值变化_java_02


对于其它5个域对象状态变化的监听器的创建步骤是一样的。

四,域对象状态变化监听器的作用
监听器具体的作用根据具体的业务需求会有所不同。但ServletContextListener的作用被大多数系统共同用到
ServletContextListener监听器的作用
1,配置服务器初始化时的任务,比如加载数据库驱动,或者配置文件
2,设置定时器,比如每天的12点刷新一次数据。

比如创建一个定时器,每天的12天刷新一次数据

@Override
    //监听ServletContextListener创建的方法
    public void contextInitialized(ServletContextEvent sce) {
        //创建定时器调度对象
        Timer timer = new Timer();
        //定时器任务对象
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                //具体的执行内容
                System.out.println("刷新数据相关操作");
            }
        };
        SimpleDateFormat simpleFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date parse = null;
        try {
        //时间根据自己服务器启动的时间来手动在代码里维护。也可以用数据库来维护。
             parse = simpleFormatter.parse("2019-05-01 12:00:00");
            //定时器启动,schedule(task,firstTime,period);task:具体任务,firstTime:第一次执行的时间单位为毫秒,period:执行间隔,单位毫秒
            timer.schedule(timerTask,parse,24*60*60*1000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

五,对象感知监听器
有两个与session相关的监听器叫对象感知监听器。session域是服务器为客户端单独创建的一个存放数据的区域。这个区域有时会存放一个对象。此时我们可以对这个对象进行监听。
根据监听类型分为两种

对象感知监听器

对象绑定监听器

HttpSessionBindingListener

对象钝化活化监听器

HttpSessionActivationListener

1,对象绑定监听器HttpSessionBindingListener
对象绑定监听器就是对象保存在session和从session移除时会执行的监听器:
1,绑定:使用session.setAttribute(String,对象);,后这个对象就和这个session绑定了,此时对象绑定监听器就会调用绑定方法
2,解绑:使用session.removeAttribute(绑定对象对应的String);后这个对象就和这个session解绑了,此时对象绑定监听器就会调用解绑方法

对象绑定监听器并非绑定在session上而是绑定在与session绑定的对象上的。
代码实现步骤如下:
1,创建一个即将被绑定在session上的对象并实现HttpSessionBindingListener
2,重写绑定和解绑方法
3,不需要配置web.xml

public class Human implements HttpSessionBindingListener{
    @Override
    //绑定的方法,当执行session.setAttribute(String,Human对象)时执行
    public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("Human与session绑定了");
    }
    @Override
    //解绑的方法,当执行session.removeAttribute(Human对象对应String)时执行
    public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("Human与session解绑了");
    }
}

启动服务器并执行以下代码

@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        Human human = new Human();
        //human与Session绑定
        session.setAttribute("human",human);
        //human与session解绑
        session.removeAttribute("human");
    }

结果如下:

java 如何监听实体类属性变化 java监听对象属性值变化_listenet_03


至于这个监听器的用处,一般写企业框架的时候可能会用上。日常开发基本用不上。

2,钝化活化监听器HttpSessionActivationListener
钝化活化监听器就是把保存在session上的对象序列化到磁盘和从磁盘恢复到session上时执行的一个监听器
钝化:session里的某个对象序列化到磁盘上。
活化:把写在磁盘上的某个对象恢复到session

代码实现步骤如下:
1,创建一个即将被绑定在session上的对象并实现HttpSessionBindingListener
2,重写钝化和活化方法
3,不需要配置web.xml
4,同时要实现Serializable接口,钝化活化是序列化与反序列化的过程。

//注意要实现Serializable接口,钝化时序列化的过程,不实现该接口就不会被活化.
public class Human implements HttpSessionActivationListener,Serializable{
    @Override
    //钝化方法
    public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
        System.out.println("human被钝化了");
    }
    @Override
    //活化方法
    public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
        System.out.println("活化");
    }
}

那么,这个监听器什么时候会执行呢?如果就这样只创建一个类绑定了钝化活化监听器。此时在服务器关闭的时候会钝化。再次重启打开的时候会活化。

启动服务器执行以下代码:

public class ServletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        Human human = new Human();
        //human与Session绑定
        session.setAttribute("human",human);
    }
}

然后关闭服务器,效果如下:

java 如何监听实体类属性变化 java监听对象属性值变化_listenet_04


然后再次启动.

java 如何监听实体类属性变化 java监听对象属性值变化_java 如何监听实体类属性变化_05


然后再用session获取这个human.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		 HttpSession session = request.getSession();
	        //human与Session绑定
	        Human human = (Human) session.getAttribute("human");
	System.out.println("+++"+human);
	}

执行后,不会显示为null说明活化成功:

java 如何监听实体类属性变化 java监听对象属性值变化_listenet_06


六,钝化活化作用,配置自动钝化和活化

用户访问服务器时会生成session并会往里面放很多对象。当用户量一多session的量就会非常多。而这么多的用户中有的用户只是暂时离开并没有关闭客户端。此时为了节省服务器的内存资源就需要将这些未在使用中的session里面的对象给钝化起来。等再次使用后在将其活化。

比如服务器重启时保存用户的session信息。或者某种秒杀活动时用户会提前登入但可能不会继续操作。此时先将用户session进行钝化。

要实现一定时间不操作后自动钝化,然后再次操作自动活化的过程。需要进行配置
在META-INF下创建一个context.xml并写入一下内容

<Context>
<!--maxIdleSwap表示多长时间不操作后自动钝化,单位分钟-->
 <Manager className="org.apache.catalina.session.PersistentManager" 																				maxIdleSwap="1">
 <!--directory路径,一般填写项目名称-->
  <Store className="org.apache.catalina.session.FileStore" directory="qjq" />
 </Manager>
</Context>