蒋振飞的博客 - Java提升06:Listener与Filter   
正在加载蒋振飞的博客...
V3.0
蒋振飞的博客

Java提升06:Listener与Filter

发布时间: 2018年11月08日 发布人: 蒋振飞 热度: 497 ℃ 评论数: 0

一、Listener

    1.监听器的作用

        监听某一个事件的发生,或者状态发生改变。

    2.监听器的内部机制

        其实就是接口回调。

    3.接口回调

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

    4.Web监听器

        总共有8个,划分成三种类型。

        ①定义一个类,实现接口。
        ②注册,配置监听器。

二、监听三个作用域创建和销毁

    1.ServletContextListener

        1) servletcontext创建

            ①启动服务器的时候

        2) servletContext销毁

            ①关闭服务器. 从服务器移除项

        3) ServletContextListener作用

            ①完成自己想要的初始化工作
            ②执行自定义任务调度,如Timer

public class MyServletContextListener implements ServletContextListener{
	
    // 初始化时候调用
    public void contextInitialized(ServletContextEvent arg0) {
    // TODO Auto-generated method stub
        System.out.println("ServletContext初始化了...");
    }
    // 销毁时候调用
    public void contextDestroyed(ServletContextEvent arg0) {
        // TODO Auto-generated method stub
        System.out.println("ServletContext被销毁了...");		
    }	
}

// 以下是web.xml注册			  
<listener>
    <listener-class>com.jzfblog.listener.MyServletContextListener </listener-class>
</listener>

    2.ServletRequestListener

        1) request创建

            访问服务器上的任意资源都会有请求出现。
                ①访问 html:会
                ②访问 jsp:会
                ③访问 servlet:会 

        2) request销毁

            服务器已经对这次请求作出了响应。

public class MyRequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("servletrequest 销毁了");
    }
				
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("servletrequest 初始化了");
    }
}

// 以下是web.xml注册			  
<listener>
    <listener-class>com.jzfblog.listener.MyRequestListener</listener-class>
</listener>

    3.HttpSessionListener

        1) session的创建

            只要调用getSession。
                ①html:不会
                ②jsp:会,getSession();
                ③servlet:会

        2) session的销毁

            ①超时(30分钟)
            ②非正常关闭(销毁)
            ③正常关闭服务器(序列化)

        3) HttpSessionListener作用

            ①统计在线人数

public class MySessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("创建session了");
    }
			
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("销毁session了");
    }
}
// 以下是web.xml注册			  
<listener>
    <listener-class>com.jzfblog.listener.MySessionListener </listener-class>
</listener>

三、监听三个作用域属性状态变更

    1.用于监听在作用域中值的添加、替换、移除等动作

        ①servletContext:ServletContextAttributeListener
        ②request:ServletRequestAttributeListener
        ③session:HttpSessionAttributeListener

    2.以HttpSessionAttributeListener为例,其他与此类似

public class MyHttpSession implements HttpSessionAttributeListener{

    public void attributeAdded(HttpSessionBindingEvent arg0) {
        System.out.println("属性被添加进来了");
    }

    public void attributeRemoved(HttpSessionBindingEvent arg0) {
        System.out.println("属性被移除了");
    }

    public void attributeReplaced(HttpSessionBindingEvent arg0) {
        System.out.println("属性被替换了");	
    }
}

        jsp页面如下,还需注意,该监听器必须在web.xml中注册

<% 
    session.setAttribute("name", "feiji");
    session.setAttribute("name", "huojian");
    session.removeAttribute("name");
%>

四、监听httpSession里面存值的状态变更

    1.HttpSessionBindingListener

        这一类监听器不用注册,监听对象与session绑定和解除绑定的动作,让javaBean 实现该接口即可。

public class Bean implements HttpSessionBindingListener{

    private String name;
	
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("对象被绑定进来了");
    }
		
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("对象被解除绑定");
    }
}

    jsp页面如下,此类监听器无需注册

<%
    Bean bean = new Bean();
    bean.setName("zhangsan");
    session.setAttribute("bean", bean);
%>

    2.HttpSessionActivationListener

        用于监听现在session的值是钝化(序列化)还是活化(反序列化)的动作。

        1) 钝化(序列化) 

            把内存中的数据 存储到硬盘上。

        2) 活化(反序列化)

            把硬盘中的数据读取到内存中。

public class Bean02 implements HttpSessionActivationListener, Serializable{

    private String name;
	
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

    public void sessionWillPassivate(HttpSessionEvent arg0) {
        System.out.println("session被钝化");
    }
}

        3) session的钝化活化的用意何在

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

    3.如何让session的在一定时间内钝化

        1) 在tomcat里面 conf/context.xml 里面配置

            对所有的运行在这个服务器的项目生效。

        2) 在conf/Catalina/localhost/context.xml 配置

            对 localhost生效,localhost:8080。

        3) 在自己的web工程项目中的 META-INF/context.xml

            只对当前的工程生效。

        4) maxIdleSwap

            1分钟不用就钝化。

        5) directory

            钝化后的那个文件存放的目录位置。 

<Context>
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="jzfblog"/>
    </Manager>
</Context>

五、Filter

    1.过滤器

        对客户端发出来的请求进行过滤,起到的是拦截作用。

    2.作用

        ①对一些敏感词汇进行过滤
        ②统一设置编码
        ③自动登录

    3.使用Filter

        定义一个类, 实现Filter

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 {
    }
}

        在web.xml里面注册,注册的手法与servlet基本一样

<filter>
    <display-name>FilterDemo</display-name>
    <filter-name>FilterDemo</filter-name>
    <filter-class>com.jzfblog.filter.FilterDemo</filter-class>
</filter>
<filter-mapping>
    <filter-name>FilterDemo</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

    4.Filter的生命周期

        ①创建:在服务器启动的时候就创建。
        ②毁:服务器停止的时候。

    5.Filter执行顺序

        ①客户端发出请求,先经过过滤器,如果过滤器放行,才能到servlet。
        ②如果有多个过滤器,那么他们会按照注册的映射顺序来排队。 只要有一个过滤器,不放行,那么后面排队的过滤器以及servlet都不会收到请求。
        ③如果想放行,那么在doFilter方法里面操作,使用参数 chain

chain.doFilter(request, response);

    6.针对 dispatcher 设置

        ①REQUEST只要是请求过来,都拦截,默认就是REQUEST
        ②FORWARD:只要是转发都拦截。
        ③ERROR:页面出错发生跳转。 
        ④INCLUDE:包含页面的时候就拦截。

六、Filter自动登录案例

    1.登录servlet代码

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    try {
        String userName = request.getParameter("username");
        String password = request.getParameter("password");
        String autoLogin = request.getParameter("auto_login");
        UserBean user = new UserBean();
        user.setUsername(userName);
        user.setPassword(password);
	
        UserDao dao = new UserDaoImpl();
        UserBean userBean = dao.login(user);
	
        if(userBean != null){
        
            // 4.判断是否选择自动登录
            if("on".equals(autoLogin)) {
					
                // 发送cookie给客户端
                Cookie cookie = new Cookie("auto_login", username+"#jzfblog#"+password);
                cookie.setMaxAge(60*60*24*7); // 七天有效期
                cookie.setPath(request.getContextPath());
                response.addCookie(cookie);
            }
        
            // 成功了,进入首页
            request.getSession().setAttribute("userBean", userBean);
            response.sendRedirect("index.jsp");
        }else{
            // 不成功...
            request.getRequestDispatcher("login.jsp").forward(request, response);
        }
	
    } catch (SQLException e) {
        e.printStackTrace();
    }

    2.过滤器代码(重点)

        过滤器的核心不是完成拦截不给 , 还是放行显示。 它的核心是在放行之前,帮用户完成登录的功能。 

        1) 先判断session是否有效,如果有效,就不用取cookie了,直接放行

        2) 如果session失效了,那么就取 cookie

            ①没有cookie,放行。
            ②有cookie ,取出来cookie的值,然后完成登录,再把这个用户的值存储到session中,最后放行。

public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    try {
        HttpServletRequest request = (HttpServletRequest) req;

        // 1.先判断,现在session中还有没有那个userBean
        UserBean userBean = (UserBean) request.getSession().getAttribute("userBean");
	
        // 还有,有效。
        if(userBean != null){
            chain.doFilter(request, response);
        }else{
            // 代表session失效了
		
            // 来请求的时候,先从请求里面取出cookie , 但是cookie有很多的key-value
            Cookie[] cookies = request.getCookies();
            // 从一堆的cookie里面找出我们以前给浏览器发的那个cookie
            Cookie cookie = CookieUtil.findCookie(cookies, "auto_login");
		
            // 判断用户是否有在Servlet设置的那个cookie,没有就表示第一次来
            if(cookie == null){
                chain.doFilter(request, response);
            }else{
			
                // 不是第一次
                String value = cookie.getValue();
                String username = value.split("#itheima#")[0];
                String password = value.split("#itheima#")[1];

                // 完成登录
                UserBean user = new UserBean();
                user.setUsername(username);
                user.setPassword(password);

                UserDao dao = new UserDaoImpl();
                userBean = dao.login(user);

                // 使用session存这个值到域中,方便下一次未过期前还可以用。
                request.getSession().setAttribute("userBean", userBean);
			
                chain.doFilter(request, response);
            }
		
        }

    } catch (Exception e) {
        e.printStackTrace();
        chain.doFilter(req, response);
    }
}

打赏 蒋振飞

取消

感谢您的支持,我会继续努力的!

扫码支持
一分也是爱     一块不嫌多

点击 支付宝 或 微信 打赏蒋振飞

打开支付宝扫一扫,即可进行扫码打赏哦

评论列表