美文网首页
Listener and Filter

Listener and Filter

作者: 达摩君 | 来源:发表于2017-12-03 19:24 被阅读14次

    Listener监听器

    Javaweb开发中的监听器,是用于监听web常见对象
    HttpServletRequest HttpSession ServletContext
    监听它们的创建与销毁 属性变化 session绑定javaBean

    1、监听机制

    事件 : 就是一个事情
    事件源 : 产生这个事情的源头
    监听器 : 用于监听指定的事件的对象
    注册监听 : 要想让监听器可以监听到事件产生,必须对其进行注册。

    2、Javaweb开发中常见监听器
    • 监听域对象的创建与销毁
      监听ServletContext创建与销毁 ServletContextListener
      监听HttpSession创建与销毁 HttpSessionListener
      监听HttpServletRequest创建与销毁 ServletRequestListener
    • 监听域对象的属性变化
      监听ServletContext属性变化 ServletContextAttributeListener
      监听HttpSession属性变化 HttpSessionAttributeListener
      监听HttpServletRequest属性变化 ServletRequestAttributeListener
    • 监听session绑定javaBean
      它是用于监听javaBean对象是否绑定到了session域 HttpSessionBindingListener
      它是用于监听javaBean对象的活化与钝化 HttpSessionActivationListener
    3、监听器的快速入门

    关于创建一个监听器的步骤

    1. 创建一个类,实现指定的监听器接口
    2. 重写接口中的方法
    3. 在web.xml文件中对监听器进行注册。
    • 关于域对象创建与销毁的演示
    public class listenerDemo implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            System.out.println("ServletContext对象创建了");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            System.out.println("ServletContext对象销毁了");
        }
    }
    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
        
        <listener>
            <listener-class>com.ljb.listenerDemo.listenerDemo</listener-class>
        </listener>
        
    </web-app>
    
    • HttpSession对象的创建与销毁
      HttpSession session=request.getSession();
      Session销毁
      1.默认超时 30分钟
      2.关闭服务器
      3.invalidate()方法
      4.setMaxInactiveInterval(int interval) 可以设置超时时间
      ?问题:直接访问一个jsp页面时,是否会创建session?
      会创建,因为我们默认情况下是可以在jsp页面中直接使用session内置对象的。
    public class MyHttpSessionListener implements HttpSessionListener {
        @Override
        public void sessionCreated(HttpSessionEvent httpSessionEvent) {
            System.out.println("httpSession对象创建了");
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
            System.out.println("httpSession对象销毁了");
        }
    }
    
    • HttpServletRequest创建和销毁
      Request对象是发送请求服务器就会创建它,当响应产生时,request对象就会销毁。
    public class MyHttpServletRequest implements ServletRequestListener {
        @Override
        public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
            System.out.println("httpServletRequest对象创建了");
        }
    
        @Override
        public void requestInitialized(ServletRequestEvent servletRequestEvent) {
            System.out.println("httpServletRequest对象销毁了");
        }
    }
    
    • Request域对象中属性变化
      在java的监听机制中,它的监听器中的方法都是有参数的,参数就是事件对象,而我们可以通过事件对象直接获取事件源。
    • session绑定javaBean
      1. javaBean对象自动感知被绑定到session中.
        HttpSessionBindingListener 这个接口是由javaBean实现的,并且不需要在web.xml文件中注册
    public class Book implements Serializable, HttpSessionBindingListener {
    
        private String id;
        private String name;
        private double price;
        private int pnum;
        private String category;
        private String description;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        public int getPnum() {
            return pnum;
        }
    
        public void setPnum(int pnum) {
            this.pnum = pnum;
        }
    
        public String getCategory() {
            return category;
        }
    
        public void setCategory(String category) {
            this.category = category;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        @Override
        public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {
            System.out.println("book对象被绑定");
        }
    
        @Override
        public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
            System.out.println("book对象解除绑定");
        }
    }
    
    1. javabean对象可以活化或钝化到session中。
      HttpSessionActivationListener如果javaBean实现了这个接口,那么当我们正常关闭服务器时,session中的javaBean对象就会被钝化到我们指定的文件中。
      当下一次在启动服务器,因为我们已经将对象写入到文件中,这时就会自动将javaBean对象活化到session中。
      我们还需要个context.xml文件来配置钝化时存储的文件
      在meta-inf目录下创建一个context.xml文件
    <Context>
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
    <Store className="org.apache.catalina.session.FileStore" directory="it315"/>
    </Manager>
    </Context>
    
    案例-定时销毁session
    1. 怎样可以将每一个创建的session全都保存起来?
      我们可以做一个HttpSessionListener,当session对象创建时,就将这个session对象装入到一个集合中.
      将集合List<HttpSession>保存到ServletContext域中。

    2. 怎样可以判断session过期了?
      在HttpSession中有一个方法public long getLastAccessedTime()
      它可以得到session对象最后使用的时间。
      可以使用invalidate方法销毁。

      我们上面的操作需要使用任务调度功能.
      在java中有一个Timer定时器类

    public class listenerDemo implements ServletContextListener {
       @Override
       public void contextInitialized(ServletContextEvent servletContextEvent) {
           //通过事件源对象得到事件源
           ServletContext application = servletContextEvent.getServletContext();
           //创建一个集合存储session对象
           List<HttpSession> list = Collections.synchronizedList(new ArrayList<HttpSession>());
    
           application.setAttribute("sessions",list);
    
           //创建一个定时器对象
           Timer t = new Timer();
           t.schedule(new TimerTask() {
               @Override
               public void run() {
                   System.out.println("开始扫描。。。。。。。。。。。");
                   for (Iterator iterator = list.iterator(); iterator.hasNext();) {
                       HttpSession session = (HttpSession) iterator.next();
                       long l = System.currentTimeMillis() - session.getLastAccessedTime();
                       if (l > 5000) {
                           session.invalidate();
                           iterator.remove();
                       }
                   }
                   //有问题Exception in thread "Timer-0" java.util.ConcurrentModificationException
    //                for (HttpSession session: list) {
    //                    long l = System.currentTimeMillis() - session.getLastAccessedTime();
    //                    if (l > 5000) {
    //                        session.invalidate();
    //                        list.remove(session);
    //                    }
    //                }
               }
           }, 2000, 5000);
       }
    
       @Override
       public void contextDestroyed(ServletContextEvent servletContextEvent) {
           System.out.println("ServletContext对象销毁了");
       }
    }
    
    public class MyHttpSessionListener implements HttpSessionListener {
        @Override
        public void sessionCreated(HttpSessionEvent httpSessionEvent) {
            //得到application对象中的list
    
            HttpSession session = httpSessionEvent.getSession();
            ServletContext application = session.getServletContext();
            List<HttpSession> sessions = (List<HttpSession>) application.getAttribute("sessions");
    
            sessions.add(session);
            System.out.println("添加"+session.getId());
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
            System.out.println("httpSession对象销毁了");
        }
    }
    
    

    Filter过滤器

    Javaweb中的过滤器可以拦截所有访问web资源的请求或响应操作。

    Filter快速入门
    1. 创建一个类实现Filter接口
    2. 重写接口中方法 doFilter方法是真正过滤的。
    3. 在web.xml文件中配置
      注意:在Filter的doFilter方法内如果没有执行chain.doFilter(request,response)
      那么资源是不会被访问到的。
    @WebFilter(filterName = "FilterDemo", urlPatterns = "/*")
    public class FilterDemo implements Filter {
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
             System.out.println("拦截开始");       
             chain.doFilter(req, resp);
            System.out.println("数据返回了"); 
        }
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    
    }
    

    FilterChain 是 servlet 容器为开发人员提供的对象,它提供了对某一资源的已过滤请求调用链的视图。过滤器使用 FilterChain 调用链中的下一个过滤器,如果调用的过滤器是链中的最后一个过滤器,则调用链末尾的资源。
    问题:怎样可以形成一个Filter链?
    只要多个Filter对同一个资源进行拦截就可以形成Filter链
    问题:怎样确定Filter的执行顺序?
    由<filter-mapping>来确定

    Filter生命周期

    Servlet生命周期:
    实例化 --》 初始化 --》 服务 --》 销毁

    1. 当服务器启动,会创建Filter对象,并调用init方法,只调用一次.
    2. 当访问资源时,路径与Filter的拦截路径匹配,会执行Filter中的doFilter方法,这个方法是真正拦截操作的方法.
    3. 当服务器关闭时,会调用Filter的destroy方法来进行销毁操作.
    FilterConfig

    在Filter的init方法上有一个参数,类型就是FilterConfig.
    FilterConfig它是Filter的配置对象,它可以完成下列功能
    1.获取Filtr名称
    2.获取Filter初始化参数
    3.获取ServletContext对象。


    image.png
    @WebFilter(filterName = "FilterDemo2", urlPatterns = "/*", initParams = {@WebInitParam(name = "encoding",value = "utf-8")})
    public class FilterDemo2 implements Filter {
        private FilterConfig config;
    
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            System.out.println("FilterDemo2");
            String encoding = config.getInitParameter("encoding");
            req.setCharacterEncoding(encoding);
            chain.doFilter(req, resp);
        }
    
        public void init(FilterConfig config) throws ServletException {
            this.config = config;
        }
    
    }
    
    Filter配置

    基本配置

        <filter>
            <filter-name>filter名称</filter-name>
            <filter-class>Filter类的包名.类名</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>filter名称</filter-name>
            <url-pattern>路径</url-pattern>
        </filter-mapping>
    

    关于其它配置

    1. <url-pattern>
      完全匹配 以”/demo1”开始,不包含通配符*
      目录匹配 以”/”开始 以*结束
      扩展名匹配 .xxx 不能写成/.xxx
    2. <servlet-name>
      它是对指定的servlet名称的servlet进行拦截的。
    3. <dispatcher>
      可以取的值有 REQUEST FORWARD ERROR INCLUDE
      它的作用是:当以什么方式去访问web资源时,进行拦截操作.
      1.REQUEST 当是从浏览器直接访问资源,或是重定向到某个资源时进行拦截方式配置的 它也是默认值
      2.FORWARD 它描述的是请求转发的拦截方式配置
      3.ERROR 如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
      4.INCLUDE 如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用

    相关文章

      网友评论

          本文标题:Listener and Filter

          本文链接:https://www.haomeiwen.com/subject/uqhobxtx.html