过滤器和监听器

过滤器

Filter译为过滤器。 由于 Servlet 规范是开放的,借助于公众与开源社区的力量, Servlet 规范越来越科学,功能也越来越强大。

运行原理:

当客户端向服务器端发送一个请求时,如果有对应的过滤器进行拦截,过滤器可以改变请求的内容、或者重新设置请求协议的相关信息等,然后再将请求发送给服务器端的Servlet进行处理。当Servlet对客户端做出响应时,过滤器同样可以进行拦截,将响应内容进行修改或者重新设置后,再响应给客户端浏览器。在上述过程中,客户端与服务器端并不需要知道过滤器的存在 在一个Web应用程序中,可以部署多个过滤器进行拦截,这些过滤器组成了一个过滤器链。过滤器链中的每个过滤器负责特定的操作和任务,客户端的请求在这些过滤器之间传递,直到服务器端的Servlet。具体执行流程如下:

快速入门

1.编写一个类实现Filter过滤接口

2.重写接口中的方法

 

package com.bhf.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;


/**
 * 过滤器的生命周期
 *   创建对象   LoginFilter()   服务器启动时  调用一次
 *   初始化     init    对象创建完成后  调用一次
 *   执行过滤的方法    doFilter    一次请求执行一次
 *   销毁方法       destroy   服务器关闭时 被调用  调用一次
 */

//   "/*"表示拦截所有请求,进入doFilter,
//   执行filterChain.doFilter(servletRequest,servletResponse);放行请求
@WebFilter("/*")
public class TestFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

应用的实例

1.解决请求参数的乱码问题

2.非法访问的拦截(当用户未登录时,拦截请求到登录页面)

拦截所有资源: /*

需要被放行的资源: 不需要登录即可访问的资源

1、放行指定页面:不需要登录可以访问的页面(例如:登录页面、注册页面等)

2、放行静态资源: (例如: css. js. image等资源)

3、放行指定操作:不需要登录即可执行的操作(例如:登录操作、注册操作等)

4、登录状态放行(如果存在指定session对象。则为登录状态)

package com.bhf.filter;

import com.bhf.pojo.User;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {


        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        //处理中文乱码
        req.setCharacterEncoding("utf-8");
        //放行特定页面
        String servletPath = req.getServletPath();
        System.out.println("servletPath"+servletPath);

        if("/login.jsp".equals(servletPath)||"/register.jsp".equals(servletPath)){
            filterChain.doFilter(req,resp);
            return;
        }
        //放行特定的请求 /user method=getCode
        String method = req.getParameter("method");
        if("getCode".equals(method)||"login".equals(method)||"register".equals(method)||"checkUserName".equals(method)){
            filterChain.doFilter(req,resp);
            return;
        }

        //放行特定静态资源 .css .js .img
        if(servletPath.startsWith("/static")) {
            filterChain.doFilter(req,resp);
            return;
        }


        //1.判断session中是否有user对象
        User user = (User) req.getSession().getAttribute("user");

        //2.判断user是否为null
        if(user==null){
            //没有登录跳转
            req.setAttribute("login_msg","您未登录");
            req.getRequestDispatcher("/login.jsp").forward(req,resp);
        }

        filterChain.doFilter(req,resp);



    }

    @Override
    public void destroy() {

    }
}

监听器

web监听器由servlet规范提供的,它可以监听客户端的请求,服务端的操作,监听的对象包括:

  • ServletContext

  • HttpSession

  • ServletRequest

三个域对象(内置对象),分别对应aplication,session,request

 

Web监听器概念 Servlet规范中定义的一种特殊类,用于监听ServletContext,HttpSession和ServletRequest等域对象的创建与销毁事件,用于监听域对象的属性发生增、删、改的事件,可以在事件发生前,发生后做一些必要的处理

监听三个对象的创建和销毁

1.application域对象的监听器

package com.aiit.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 *  application域对象的监听器
 *   1.监听域对象的创建和销毁
 *  ServletContextListener
 */
@WebListener
public class ApplicationListener implements ServletContextListener {
    // 一旦有application对象被创建 则该方法会被自动调用
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("application对象被创建");
    }
    // 一旦有application对象被销毁 则该方法会被自动调用
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("application对象被销毁");
    }
}

2.session对象的监听器 

package com.aiit.listener;

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

/**
 *  session对象的创建和销毁的监听
 *
 *  session 对象 什么时候被创建
 *   浏览器向服服务器成功发送一次请求 则会话对象被创建  同一次会话只会创建一个会话对象    Cookie
 *  session 对象 什么时候被销毁
 *  1. 手动销毁
 *   2. 默认销毁  浏览器在30分钟之内没有向服务器发送请求 则会话对象自动销毁
 */
@WebListener
public class SessionListener implements HttpSessionListener {

    //会话对象被创建
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("sessionCreated");
    }
    //会话对象被销毁
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("sessionDestroyed");
    }
}

3.request对象的监听器

package com.aiit.listener;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class RequestListener implements ServletRequestListener {

    //会话对象被创建
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("requestDestroyed");
    }

    //会话对象被销毁
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("requestInitialized");

    }
}

监听三个对象中值的变化

1.监听域对象中值的改变,实现ServletContextAttributeListener接口

package com.aiit.listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.annotation.WebListener;

/**
 * application域对象的监听器
 *2.监听域对象中值的改变
 * ServletContextAttributeListener
 *
 */
@WebListener
public class ApplicationAttributeListener implements ServletContextAttributeListener {
    //application中有值被添加
    @Override
    public void attributeAdded(ServletContextAttributeEvent event) {
        String name = event.getName();
        System.out.println("name = " + name);
        Object value = event.getValue();
        System.out.println("value = " + value);
        System.out.println("application attributeAdded");
    }
    //application中有值被删除
    @Override
    public void attributeRemoved(ServletContextAttributeEvent event) {
        System.out.println("application attributeRemoved");
    }
    //application中有值被替换
    @Override
    public void attributeReplaced(ServletContextAttributeEvent event) {
        System.out.println("application attributeReplaced");
    }
}

2.监听域对象中值的改变,实现HttpSessionAttributeListener接口

与1相同省略

3.监听域对象中值的改变,实现ServletRequestAttributeListener接口

与1相同省略

使用监听器防止一个账号多段登录

单点登录思路分析
1.用户登录成功后会向session域中添加一个key --> user
2.向session对象中添加值时会被HttpSessionAttributeListener attributeAdded 获取到
3.判断改登录的用户是否已经登录过一次了 -->Map<String(username),HttpSession(session) > tom  session  ;jack session
4.用户已经登录则根据用户名在map集合中取出对应的session并销毁 第一次登录的用户就会被剔除 再次请求后台接口是就会被拦截到登录页面
5.将第二次登录的用户相关信息存入map集合 user session
@WebListener
public class LoginListener implements HttpSessionAttributeListener {

	private Map<String, HttpSession> sessions = new HashMap<String, HttpSession>();
   
	 public void attributeReplaced(HttpSessionBindingEvent arg0)  { 
	     
	 }
	 
	    public void attributeAdded(HttpSessionBindingEvent event)  { 
	    	System.out.println("session值被添加");
	    	//获取添加session的名字
	    	String name = event.getName();
	    	System.out.println(name);
	    	if("username".equals(name)) {//该用户的session 已存在 在map中移出
	    		String username =(String)event.getValue();
	    		if(sessions.containsKey(username)) {
	    			HttpSession httpSession = sessions.get(username);
		    		//设置session失效
		    		httpSession.invalidate();
		    		System.out.println("session被移出");
	    		}
	    		
	    		//将刚生成的session放入 集合
	    		sessions.put(username, event.getSession());
	    	}
	         
	    }
    public void attributeRemoved(HttpSessionBindingEvent event)  { }
    public void attributeReplaced(HttpSessionBindingEvent event) { }
          
}

Web监听器的常用用途

  • 统计在线人数

  • 系统启动时加载初始化信息

实例1

/**
 * 使用session监听器实现统计在线人数
 * @author USER
 * date 2021年7月13日
 * @version 1.0
 */
@WebListener
public class SessionListener implements HttpSessionListener {

    public void sessionCreated(HttpSessionEvent arg0)  { 
         System.out.println("session监听器初始化完毕");
         CountUtil.add();
         arg0.getSession().getServletContext().setAttribute("online", CountUtil.getCount());
    }

    public void sessionDestroyed(HttpSessionEvent arg0)  { 
    	System.out.println("session监听器销毁完毕");
    	 CountUtil.sub();
    	 arg0.getSession().getServletContext().setAttribute("online", CountUtil.getCount());
    }
	
}

实例2

/**
 * Application域生命周期的监听 设置全局的路径
 * @author USER
 * date 2021年7月12日
 * @version 1.0
 */
@WebListener
public class ApplicationListener implements ServletContextListener {

	
    public void contextDestroyed(ServletContextEvent arg0)  { 
    	System.out.println("上下文销毁化完毕");
    	
    }

    public void contextInitialized(ServletContextEvent arg0)  { 
    	System.out.println("上下文初始化完毕");
    	arg0.getServletContext().setAttribute("bp", arg0.getServletContext().getContextPath());
    }
	
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值