第6章 filter(4课时)过滤器和监听器

课程目标

掌握过滤器概念及两种编写方法

过滤器Filter

过滤器也叫拦截器,在一个层面上解决问题。
应用:用来做统一编码解码、用来做权限验证、做网站计数等等
特殊说明:过滤器可以是一个链。也就是说可以配置多个过滤器,我们也可以通过配置来控制顺序

怎么建filter

servlet3.0以后。可以用向导建
例如:我建一个统一做编码处理的

我们之前在每个servlet里要写

request.setChararcterEncoding("utf-8");
response.setChararcterEncoding("utf-8");

file-new -Filter-按向导一步步配置。
step1 为filter起个文件名CharacterFilter
step2 设置初始化参数 encoding:UTF-8
step3 mapping 配置过滤对象(1--可以对指定的servlet进行过滤 2--可以配置过滤规则)

配置完成后生成如下代码:

package com.neuedu.utils;

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;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;


@WebFilter(
        urlPatterns = { "/*" }, 
        initParams = { 
                @WebInitParam(name = "encoding", value = "UTF-8")
        })
public class CharacterFilter implements Filter {


public CharacterFilter() {
// TODO Auto-generated constructor stub
}

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        // place your code here

        // pass the request along the filter chain
        chain.doFilter(request, response);
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

}

我们看到有三个主要方法

init() 初始化方法:做准备工作

doFilter() 业务方法
需要注意的是:j里面有一个
chain.doFilter(request, response);这句话的意思是执行完该过滤器后去执行下一个过滤器
用@WebFilter方式配置的过滤器执行顺序是按filterName首字母的先后顺序执行。

destroy() 销毁方法:做清理工作

完整代码如下:

package com.neuedu.utils;

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;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;

/**
 * Servlet Filter implementation class CharacterFilter
 */
@WebFilter(
        filterName="MyFilter",
        urlPatterns = { "/*" }, 
        initParams = { 
                @WebInitParam(name = "encoding", value = "UTF-8")
        })
public class CharacterFilter implements Filter {
    String encode="";
     /**
 * Default constructor. 
 */
public CharacterFilter() {
// TODO Auto-generated constructor stub
}
    
    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        //在初始化时准备好编码方式
        encode=fConfig.getInitParameter("encoding");
    }
   
/**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encode);
        response.setCharacterEncoding(encode);
        //执行下一个过滤器
        chain.doFilter(request, response);
    }
    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        encode="";
    }
}

filter另外一种创建方式

servlet3.0之前

简化版

java类

public class TestFilter implements Filter {
    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig fconfig) throws ServletException {
    }

}

配置:

<filter>
        <filter-name>TestFilter</filter-name>
        <filter-class>com.neuedu.utils.TestFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>TestFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

分两步
step1 写一个类实现filter接口

package com.neuedu.utils;

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 MyFilter implements Filter {
    FilterConfig fconfig=null;
    @Override
    public void destroy() {
        fconfig=null;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        String encode=fconfig.getInitParameter("encode");
        request.setCharacterEncoding(encode);
        response.setCharacterEncoding(encode);
        //执行下一个过滤器
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        fconfig=config;
    }

}

step2 在WEB-INF\web.xml里配置
配置分两步
第一步filter 第二步配置filter-mapping

 <filter>
  <filter-name>MyFilter</filter-name>
  <filter-class>com.neuedu.utils.MyFilter</filter-class>
  <init-param>
  <param-name>encode</param-name>
  <param-value>utf-8</param-value>
  </init-param>
  </filter>
  
  <filter-mapping>
   <filter-name>MyFilter</filter-name>
   <url-pattern>/*</url-pattern>
  </filter-mapping>

过滤器使用

日志记录
登录验证
编码处理

后台登录拦截

可以定个规则,比如所有需要登录才能访问的jsp和servlet都加上/admin前缀

    @WebFilter("/admin/*")
    public class LoginFilter implements Filter {
    
        /**
         * Default constructor. 
         */
        public LoginFilter() {
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see Filter#destroy()
         */
        public void destroy() {
            // TODO Auto-generated method stub
        }
    
        /**
         * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
         */
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            // place your code here
            System.out.println("进入拦截器");
            //在此处做用户是否登录的验证
            //判断session里是否存在loginUser
            HttpServletRequest httprequest=(HttpServletRequest)request;
            HttpSession session=httprequest.getSession();
            Object obj=session.getAttribute("loginUser");
            if(obj!=null){
                //如果有就放行
                chain.doFilter(request, response);
                return ;
            }else{
                //如果没有,就回登录页
                HttpServletResponse httpresponse=(HttpServletResponse)response;
                httpresponse.sendRedirect(httprequest.getContextPath()+"/login.jsp");
            }
        }
    
        /**
         * @see Filter#init(FilterConfig)
         */
        public void init(FilterConfig fConfig) throws ServletException {
            // TODO Auto-generated method stub
        }
    
    }

监听器

监听事件,比如session建立,系统启动,请求到达
本质也是java类。
建立方式
file-new listener-输入名称-选择监听器种类

比如我选择了以下三个 ServletContextListener, HttpSessionListener, ServletRequestListener
系统会自动生成如下类

package com.neuedu.utils;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * Application Lifecycle Listener implementation class TestLisenter
 *
 */
@WebListener
public class TestLisenter implements ServletContextListener, HttpSessionListener, ServletRequestListener {

/**
 * Default constructor. 
 */
public TestLisenter() {
// TODO Auto-generated constructor stub
}

    /**
 * @see HttpSessionListener#sessionCreated(HttpSessionEvent)
 */
public void sessionCreated(HttpSessionEvent arg0)  { 
 // TODO Auto-generated method stub
}

    /**
 * @see ServletRequestListener#requestDestroyed(ServletRequestEvent)
 */
public void requestDestroyed(ServletRequestEvent arg0)  { 
 // TODO Auto-generated method stub
}

    /**
 * @see ServletRequestListener#requestInitialized(ServletRequestEvent)
 */
public void requestInitialized(ServletRequestEvent arg0)  { 
 // TODO Auto-generated method stub
}

    /**
 * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
 */
public void sessionDestroyed(HttpSessionEvent arg0)  { 
 // TODO Auto-generated method stub
}

    /**
 * @see ServletContextListener#contextDestroyed(ServletContextEvent)
 */
public void contextDestroyed(ServletContextEvent arg0)  { 
 // TODO Auto-generated method stub
}

    /**
 * @see ServletContextListener#contextInitialized(ServletContextEvent)
 */
public void contextInitialized(ServletContextEvent arg0)  { 
 // TODO Auto-generated method stub
}

}

仿照下面程序做一个在线人数统计计数器

https://blog.csdn.net/troubleshooter/article/details/78416857

注意:
1、application 的类型为ServletContext
2、可使用哪些方法取得Web容器环境ServletContext对象?
request.getServletContext 、 sessoin.getServletContext 、 servletConfig.getServletContext
在编写Servlet时,需要继承HttpServlet类,在Servlet中声明doGet()和doPost()需要HttpServletRequest和HttpServletResponse类型的两个参数。
ServletContextListener:服务启动和停止时触发期初始化和销毁(生命周期最长)
HttpSessionListener:session的建立和销毁(session超时或调用invalidate()方法)时触发期初始化和销毁(其次)
ServletRequestListener:一次请求和响应有效(最短)

如果同时存在监听器和过滤器,先走监听器再走过滤器.

在线人数统计

    package com.neuedu.utils;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextAttributeEvent;
    import javax.servlet.ServletContextAttributeListener;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    /**
     * Application Lifecycle Listener implementation class MyFilter
     *
     */
    @WebListener
    public class MyListener implements ServletContextListener {
    
        /**
         * Default constructor. 
         */
        public MyListener() {
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see ServletContextListener#contextDestroyed(ServletContextEvent)
         */
        public void contextDestroyed(ServletContextEvent arg0)  { 
            System.out.println("上下文销毁");
        }
    
        /**
         * @see ServletContextListener#contextInitialized(ServletContextEvent)
         * ServletContext---application
         */
        public void contextInitialized(ServletContextEvent applicationEvent)  { 
            ServletContext application=applicationEvent.getServletContext();
            //在线人数,初始化为0
            application.setAttribute("onlinenumber", 0);
             System.out.println("上下文创建");
        }
        
    }


    package com.neuedu.utils;
    
    import javax.servlet.ServletContext;
    import javax.servlet.annotation.WebListener;
    import javax.servlet.http.HttpSession;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    /**
     * Application Lifecycle Listener implementation class MySessionListenter
     *
     */
    @WebListener
    public class MySessionListenter implements HttpSessionListener {
    
        /**
         * Default constructor. 
         */
        public MySessionListenter() {
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see HttpSessionListener#sessionCreated(HttpSessionEvent)
         */
        public void sessionCreated(HttpSessionEvent sessionEvent)  { 
             System.out.println("sessionCreated建立");
             //从session/request里都可以得到ServletContext--->sessionEvent.getSession可以获取
             HttpSession session=sessionEvent.getSession();
             ServletContext application= session.getServletContext();
             int old_online=(Integer)application.getAttribute("onlinenumber");
             //如果有用户访问,我们就把计数器加1
             int new_online=old_online+1;
             application.setAttribute("onlinenumber", new_online);
             System.out.println("新的在线人数"+new_online);
        }
    
        /**
         * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
         */
        public void sessionDestroyed(HttpSessionEvent sessionEvent)  { 
             System.out.println("sessionDestroyed");
             //从session/request里都可以得到ServletContext--->sessionEvent.getSession可以获取
             HttpSession session=sessionEvent.getSession();
             ServletContext application= session.getServletContext();
             int old_online=(Integer)application.getAttribute("onlinenumber");
             //如果有用户访问,我们就把计数器加1
             int new_online=old_online-1;
             application.setAttribute("onlinenumber", new_online);
             System.out.println("新的在线人数"+new_online);
            //如果有用户退出或超时,我们就把计数器-1
        }
        
    }

前台页面

    在线人数:${onlinenumber}

如果登录成功才认为是在线

@Override
public void attributeAdded(HttpSessionBindingEvent sessionEvent) {
    // TODO Auto-generated method stub
    User user=(User)sessionEvent.getSession().getAttribute("loginUser");
    HttpSession session=sessionEvent.getSession();
    ServletContext application= session.getServletContext();
    int old_online=(Integer)application.getAttribute("onlinenumber");
    //如果有用户访问,我们就把计数器加1
    if(user!=null){
    int new_online=old_online+1;
    application.setAttribute("onlinenumber", new_online);
    System.out.println("新的在线人数"+new_online);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容