Filter&Listener(超详细)

1、Filter ?什么是过滤器

Filter 过滤器它是 JavaWeb 的三大组件之一。

三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器
Filter 过滤器它是 JavaEE 的规范。也就是接口
Filter 过滤器它的作用是:拦截请求,过滤响应。

拦截请求常见的应用场景有:

1.权限检查 2.日记操作 3.事务管理 ……等等

@WebFilter(filterName = "FilterDemo01",value = "/ServletDemo01")
public class FilterDemo01 implements Filter {
    public void init(FilterConfig config) throws ServletException {
        System.out.println("init....");
    }

    public void destroy() {
        System.out.println("destroy....");

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        chain.doFilter(request, response);
        System.out.println("过去了");
    }
}

这是我们第一个Fileter

过滤器执行流程
  1. 执行过滤器
  2. 执行放行后的资源
  3. 回来执行过滤器放行代码下边的代码
过滤器生命周期方法
  1. init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
  2. doFilter:每一次请求被拦截资源时,会执行。执行多次
  3. destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源

请添加图片描述

2、拦截配置

拦截路径配置:
  1. 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
  2. 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
  3. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
  4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行

案例

@WebFilter(filterName = "FilterDemo02", value = "*.jsp")
public class FilterDemo02 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("请求过去了");
        chain.doFilter(request, response);
        System.out.println("资源过去了");
    }
}

比如这个就会拦截所有jsp文件

拦截方式配置

注解配置:

  • 设置dispatcherTypes属性
    1. REQUEST:默认值。浏览器直接请求资源
    2. FORWARD:转发访问资源
    3. INCLUDE:包含访问资源
    4. ERROR:错误跳转资源
    5. ASYNC:异步访问资源

具体是什么意思呢

@WebFilter(filterName = "FilterDemo04",value = "/index.jsp",dispatcherTypes = DispatcherType.REQUEST )
public class FilterDemo04 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest req = (HttpServletRequest) request;//强转
        req.setAttribute("a","直接的请求的过去了");
        System.out.println("直接的请求的过去了");
        chain.doFilter(request, response);
    }
}
@WebFilter(filterName = "FilterDemo05",value = "/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
public class FilterDemo05 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        // 1、判断用户的session中是否有登录状态
        HttpServletRequest req = (HttpServletRequest) request;//强转
        req.setAttribute("a","转发的请求的过去了");
        System.out.println("转发的请求过去了");
        chain.doFilter(request, response);
    }
}

如图如果是转发的控制信息会在HTML页面上打印,那么复习一下转发用到的

request.getRequestDispatcher("/index.jsp").forward(request, response);

请添加图片描述
请添加图片描述

不错验证成功

完成一个判断用户是否登录的小案例

@WebFilter(filterName = "Filter2" ,value = "/user/*")
public class Filter2 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //0.强转
        HttpServletRequest req = (HttpServletRequest) request;
        //1.获取请求资源的请求路径
        String uri = req.getRequestURI();
        //2.判断是否含有登录相关路径
        if(uri.contains("/login.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") || uri.contains("/js/") || uri.contains("/fonts/") || uri.contains("/checkCode")  ){
            //包含,用户想登录,放行
            chain.doFilter(request, response);
        }else {
            //不包含,验证用户是否登录
            //从session中获取user
            Object user = req.getSession().getAttribute("user");
            if (user != null) {
                //登录了放行
                chain.doFilter(request, response);
            }
            else {
                //没有跳转到登录页面
                request.setAttribute("login_msg","您尚未登录,请完成登录");
                request.getRequestDispatcher("/login.jsp").forward(request, response);
            }
        }
        //chain.doFilter(request, response);

    }
}

当访问user路径时需要判断用户说否登录

3、istener(监听器)的作用和内部机制

作用:监听某个事件的发生,状态的改变
内部机制:接口回调

八个web监听器
实现监听:

创建类实现监听器接口
web.xml文件中配置(注册)监听器<listener> <listener-class>url</listener-class></listener> ,Servlet3.0后可以通过注解@WebListener 注册监听器

一、 Listener监听三个域对象创建与销毁

监听ServletContext域对象的创建与销毁:实现ServletContextListener接口。
ServletContext域对象的生命周期
创建:启动服务器时创建
销毁:关闭服务器或者从服务器移除项目

@WebListener
public class MyServletContextListener implements ServletContextListener{
		
		@Override
		public void contextInitialized(ServletContextEvent arg0) {
			System.out.println("初始化");
		}
		@Override
		public void contextDestroyed(ServletContextEvent arg0) {
			System.out.println("销毁了");
		}
	
	}

作用: 利用ServletContextListener监听器在创建ServletContext域对象时完成一些想要初始化的工作或者执行自定义任务调度。

监听ServletRequest域对象的创建与销毁:实现ServletRequestListener接口。
ServletRequest域对象的生命周期
创建:访问服务器任何资源都会发送请求(ServletRequest)出现,访问.html和.jsp和.servlet都会创建请求。
销毁:服务器已经对该次请求做出了响应。

@WebListener
public class MyServletRequestListener implements ServletRequestListener{		
			@Override
			public void requestDestroyed(ServletRequestEvent arg0) {
				System.out.println("ServletRequest销毁了");
			}
		
			@Override
			public void requestInitialized(ServletRequestEvent arg0) {
				System.out.println("ServletRequest创建了");
			}
		
		}

监听HttpSession域对象的创建与销毁:实现HttpSessionListener接口:
HttpSession域对象的生命周期
创建:只要调用了getSession()方法就会创建,一次会话只会创建一次,
销毁:1.超时(默认为30分钟)2.非正常关闭,销毁3.正常关闭服务器(序列化)

@WebListener
public class MyHttpSessionListener implements HttpSessionListener{
			@Override
			public void sessionCreated(HttpSessionEvent arg0) {
				System.out.println("HttpSession创建了");
			}
			@Override
			public void sessionDestroyed(HttpSessionEvent arg0) {
				System.out.println("HTTPSession销毁了");
			}
		}

作用:每位用户登录网站时都会创建一个HTTPSession对象,利用这个统计在线人数。

二、 Listener监听三个域对象属性状态的改变

监听HttpSession属性的改变:实现HttpSessionAttributeListener接口。
监听ServletContext属性的改变:实现ServletContextAttribute接口。
监听ServletRequest属性的改变:实现ServletRequestAttribute接口。
三、 Listener监听HttpSession域对象存值的状态变更
这两种监听器不用注册。

监听对象与session绑定和解除绑定的动作,让JavaBean实现HttpSessionBindingListener接口:

public class MyHttpSessionBindingListener implements HttpSessionBindingListener {
		@Override
		public void valueBound(HttpSessionBindingEvent arg0) {
				// TODO Auto-generated method stub
				System.out.println("绑定了");
			}
			@Override
			public void valueUnbound(HttpSessionBindingEvent arg0) {
				// TODO Auto-generated method stub
				System.out.println("解绑了");
			}
		}

用于监听现在session的值是钝化(序列化)还是活化(反序列化)的动作,JavaBean实现HttpSessionActivationListener接口和Serializable接口。
钝化(序列化):把内存中的数据存储到硬盘中
活化(反序列化):把硬盘中的数据读取到内存中

	public class Bean implements HttpSessionActivationListener ,Serializable{
		@Override
		public void sessionDidActivate(HttpSessionEvent arg0) {
			System.out.println("活化了");
		}
		@Override
		public void sessionWillPassivate(HttpSessionEvent arg0) {
			System.out.println("钝化了");
		}
	}

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

Tomcat里面 conf/context.xml中配置:配置后对所有运行在该服务器中的项目生效。
Tomcat里面conf/Catalina/localhost/context.xml中配置(没有就创建一个context.xml文件):对localhost生效,如localhost:8080/
在自己的web工程项目中的META-INF/context.xml中配置:只对当前的工程项目生效。
配置内容:
maxIdleSwap:设置经过该时间就钝化。
directory:设置钝化后存放的目录,没有就自动创建。

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

TA-INF/context.xml中配置:只对当前的工程项目生效。 配置内容:maxIdleSwap:设置经过该时间就钝化。directory`:设置钝化后存放的目录,没有就自动创建。

<Context>
	<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
		<Store className="org.apache.catalina.session.FileStore" directory="lrving"/>
	</Manager>
</Context>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值