Listener

监听器,监听某一个事件的发生,状态的改变。内部机制其实就是接口回调。

  • 回调

A在执行循环,当循环到5的时候,通知B。事先先把一个对象传递给A,当A执行到5的时候,通过这个对象,来调用B中的方法。但是注意,不是直接传递B的实例,而是传递一个接口的实例过去。

img01.png

Web监听器

request --- httpServletRequest

session --- httpSession

aapplication --- ServletContext

在Eclipse中创建监听器需要实现接口,面板上列出的所有接口,并且会在web.xml中添加该监听器

微信截图_20190925094425.png

ServletContextListener

  • web.xml
<listener>
  <listener-class>com.sty.Conlis</listener-class>
</listener>
  • Conlis.java

启动服务器、关闭服务器、从服务器中移除项目都会触发该监听器

package com.sty;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class Conlis implements ServletContextListener {
    public void contextDestroyed(ServletContextEvent arg0)  { 
         System.out.println("关闭服务器或从服务器中移除项目");
    }

    public void contextInitialized(ServletContextEvent arg0)  { 
        System.out.println("启动服务器的时候");
    }
}

ServletContextAttributeListener

  • web.xml
<listener>
  <listener-class>com.sty.Conattlis</listener-class>
</listener>
  • Conattlis.java

可以监听在作用域中值 添加、替换、移除

package com.sty;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

public class Conattlis implements ServletContextAttributeListener {

    public void attributeAdded(ServletContextAttributeEvent arg0)  { 
         System.out.println("add");
    }

    public void attributeRemoved(ServletContextAttributeEvent arg0)  { 
        System.out.println("remove");
    }

    public void attributeReplaced(ServletContextAttributeEvent arg0)  { 
        System.out.println("replace");
    }
}
  • index.jsp
<%
    application.setAttribute("name", "application");
    application.setAttribute("name", "reapplication");
    application.setAttribute("name", null);

/*
控制台输出
add
replace
remove
*/
%>

HttpSessionListener

  • web.xml
<listener>
  <listener-class>com.sty.Seslis</listener-class>
</listener>
  • Seslis.java

访问服务器上的非静态资源并调用session都会触发该监听器

如果session超时或者服务器关闭并钝化(序列化)会触发sessionDestroyed()

package com.sty;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class Seslis implements HttpSessionListener {

    public void sessionCreated(HttpSessionEvent arg0)  { 
         System.out.println("创建session了");
    }

    public void sessionDestroyed(HttpSessionEvent arg0)  { 
        System.out.println("销毁session了");
    }
}
  • index.jsp加入一下代码
<% 
// 获取session
request.getSession();
// 添加属性
session.setAttribute("sess", "123");
// 强制干掉会话 会触发sessionDestroyed()
session.invalidate();
%>

HttpSessionAttributeListener

  • web.xml
<listener>
  <listener-class>com.sty.Sesattlis</listener-class>
</listener>
  • Sesattlis.java

可以监听在作用域中值 添加、替换、移除

package com.sty;

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

public class Sesattlis implements HttpSessionAttributeListener {

    public void attributeAdded(HttpSessionBindingEvent arg0)  { 
        System.out.println("add");
    }

    public void attributeRemoved(HttpSessionBindingEvent arg0)  { 
        System.out.println("remove");
    }

    public void attributeReplaced(HttpSessionBindingEvent arg0)  { 
        System.out.println("replace");
    }
}
  • index.jsp
<%
    session.setAttribute("name", "session");
    session.setAttribute("name", "resession");
    session.setAttribute("name", null);

/*
控制台输出
add
replace
remove
*/
%>

HttpSessionActivationListener

  • web.xml
<listener>
  <listener-class>com.sty.Sesactlis</listener-class>
</listener>

监听现在session的值是钝化(序列化)还是活化(反序列化)

session中的值可能会很多,并且我们有很长一段时间不使用这个内存中的值,那么可以考虑把session的值可以存储到硬盘上【钝化】,等下一次在使用的时候,在从硬盘上提取出来【活化】

  • 让session的在一定时间内钝化
  1. 在tomcat里面 conf/context.xml 里面配置 对所有的运行在这个服务器的项目生效

  2. 在conf/Catalina/localhost/context.xml 配置 对localhost生效 localhost:8080

  3. 在自己的web工程项目中的 META-INF/context.xml 只对当前的工程生效

maxIdleSwap:1分钟不用就钝化 directory:钝化后的那个文件存放的目录位置

<Context>
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="1997sty"/>
    </Manager>
</Context>
  • Sesactlis.java
package com.sty;

import java.io.Serializable;

import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;

public class Sesactlis implements HttpSessionActivationListener,Serializable {

    public void sessionDidActivate(HttpSessionEvent arg0)  { 
        System.out.println("活化");
    }

    public void sessionWillPassivate(HttpSessionEvent arg0)  { 
        System.out.println("钝化");
    }
}
  • index.jsp
<%
    session.setAttribute("Sesactlis",new Sesactlis());

/*
控制台1分钟后输出
钝化
刷新网页后
活化
*/
%>

HttpSessionBindingListener

  • web.xml
<listener>
  <listener-class>com.sty.Sesbinlis</listener-class>
</listener>
  • Sesbinlis.java

监听对象与session绑定和解除绑定的动作

package com.sty;

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

public class Sesbinlis implements HttpSessionBindingListener {

    public void valueBound(HttpSessionBindingEvent arg0)  { 
         System.out.println("对象绑定");
    }

    public void valueUnbound(HttpSessionBindingEvent arg0)  { 
        System.out.println("对象解除绑定");
    }
}
  • index.jsp
<%
    session.setAttribute("Sesbinlis", new Sesbinlis());
    session.setAttribute("Sesbinlis", null);

/*
控制台输出
对象绑定
对象解除绑定
*/
%>

ServletRequestListener

  • web.xml
<listener>
  <listener-class>com.sty.Reqlis</listener-class>
</listener>
  • Reqlis.java

访问服务器上的任意资源都会触发该监听器

package com.sty;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class Reqlis implements ServletRequestListener {

    public void requestDestroyed(ServletRequestEvent arg0)  { 
        System.out.println("访问服务器销毁了");
    }

    public void requestInitialized(ServletRequestEvent arg0)  { 
        System.out.println("访问服务器初始化了");
    }
}

ServletRequestAttributeListener

  • web.xml
<listener>
  <listener-class>com.sty.Reqattlis</listener-class>
</listener>
  • Reqattlis.java

可以监听在作用域中值 添加、替换、移除

package com.sty;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;

public class Reqattlis implements ServletRequestAttributeListener {

    public void attributeRemoved(ServletRequestAttributeEvent arg0)  { 
        System.out.println("remove");
    }

    public void attributeAdded(ServletRequestAttributeEvent arg0)  { 
        System.out.println("add");
    }

    public void attributeReplaced(ServletRequestAttributeEvent arg0)  { 
        System.out.println("replace");
    }
}
  • index.jsp
<%
    request.setAttribute("name", "request");
    request.setAttribute("name", "rerequest");
    request.setAttribute("name", null);

/*
控制台输出
replace
add
replace
remove
*/
%>

Filter

过滤器,其实就是对客户端发出来的请求进行过滤。浏览器发出,然后服务器派servlet处理。在中间就可以过滤,其实过滤器起到的是拦截的作用

使用Filter

在服务器启动时创建,服务器停止时销毁

客户端发出请求,先经过过滤器,如果过滤器放行,那么才能到servlet

如果有多个过滤器,那么他们会按照注册的映射顺序来排队。只要有一个过滤器,不放行,那么后面排队的过滤器以及咱们的servlet都不会收到请求

  1. init方法的参数 FilterConfig,可以用于获取filter在注册的名字 以及初始化参数。 其实这里的设计的初衷与ServletConfig是一样的。

  2. 如果想放行,那么在doFilter 方法里面操作,使用chain.doFilter(request, response);放行,让请求到达下一个目标。

  3. <url-pattern></url-pattern>写法格式与servlet一样。

  • 全路径匹配,以/开始/LoginServlet

  • 以目录匹配 以/开始,以*结束/demo01/*

  • 以后缀名匹配以*开始以后缀名结束*.jsp,*.html

  1. 针对<dispatcher></dispatcher>设置

REQUEST : 只要是请求过来,都拦截,默认就是REQUEST

FORWARD : 只要是转发都拦截

ERROR : 页面出错发生跳转

INCLUDE : 包含页面的时候就拦截

  • web.xml注册过滤器
  <filter>
    <display-name>FilterDemo</display-name>
    <filter-name>FilterDemo</filter-name>
    <filter-class>com.sty.FilterDemo</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>FilterDemo</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
  </filter-mapping>
  • FilterDemo.java 实现Filter接口
package com.sty;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FilterDemo implements Filter {

    public void destroy() {

    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("来到过滤器了。。。");
        chain.doFilter(request, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {

    }
}

/*
控制台输出
来到过滤器了。。。
*/