Filter&&Listener

Listener监听器

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

监听器的内部机制原理

其实就是接口回调.

接口回调

简单理解:A在执行循环,当循环到5的时候, 通知B。

事先先把一个对象传递给 A , 当A 执行到5的时候,通过这个对象,来调用B中的方法。 但是注意,不是直接传递B的实例,而是传递一个接口的实例过去。

在这里插入图片描述

Web监听器

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

ServletContextListner  : 应用被部署的时候, 服务器加载这个项目的时候,做一些初始化工作, 任务调度。
		1. 完成自己想要的初始化工作   比如加载spring的配置类
		2. 执行自定义任务调度。 执行某一个任务。 Timer  
HttpSessionListener	: 统计在线人数
HttpSessionActivationListener  : 钝化活化处理

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

xxxListener

request  	   	---httpServletRequest	监听器implement ServletRequestListener
session  	  	---httpSession			监听器implement HttpSessionListener
application  	--- ServletContext   	监听器implement ServletContextListener

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

xxxAttributeListener

request     implement  ServletRequestAttributeListener
session  	implement  HttpSessionAttributeListener
application implement  ServletContextAttributeListener

监听HttpSession存值的状态变更

HttpSessionBindingListener			绑定与解绑
HttpSessionActivationListener		钝化与活化

监听器使用

  • 定义一个类,实现以上接口
  • 注册 | 配置监听器
<listener>
    <listener-class>com.listener.MyServletContextListener</listener-class>
</listener>

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

request  	   	---httpServletRequest	监听器implement ServletRequestListener
session  	  	---httpSession			监听器implement HttpSessionListener
application  	--- ServletContext   	监听器implement ServletContextListener
1. ServletContextListener

servletcontext创建:
启动服务器的时候
servletContext销毁:
关闭服务器, 从服务器移除项目

public class MyServletContextListener implements ServletContextListener{
	
	public void contextInitialized(ServletContextEvent arg0) {
		//1 tomcat启动的时候调用
		System.out.println("ServletContextListener init");
	}
	
	public void contextDestroyed(ServletContextEvent arg0) {
		//2 从项目移除 
		System.out.println("ServletContextListener destroy");
	}
}

web.xml中注册监听器
<listener>
    <listener-class>com.listener.MyServletContextListener</listener-class>
  </listener>
2 ServletRequestListener

ServletRequestListener创建与销毁
request创建:
访问服务器上的任意资源都会有请求出现。
访问 html: 会
访问 jsp: 会
访问 servlet : 会
request销毁:
服务器已经对这次请求作出了响应。

public class MyServletRequestListener implements ServletRequestListener{

	public void requestDestroyed(ServletRequestEvent arg0) {
		// 服务器对请求做出响应
		System.out.println("requestListener Destroyed");
	}

	public void requestInitialized(ServletRequestEvent arg0) {
		// html,jsp,servlet都属于请求
		// 访问服务器的任意紫烟都会有请求出现
		System.out.println("requestListener.java init");
	}

}
    
web.xml中注册监听器
<listener>
    <listener-class>com.listener.MyServletRequestListener</listener-class>
  </listener>
3 HttpSessionListener
HttpSessionListener创建与销毁		
	只要调用getSession		
	html:		不会		
	jsp:getSession();		
	servlet: 	会
session的销毁		
	 超时  30分钟				
 	 非正常关闭 销毁		
 	 正常关闭服务器(序列化)
	
public class MyHttpSessionListener implements HttpSessionListener {

	public void sessionCreated(HttpSessionEvent arg0) {
		//html 不  jsp可以 有 session  servlet可以
		System.out.println("sessionCreated");
	}

	public void sessionDestroyed(HttpSessionEvent arg0) {
		System.out.println("sessionDestroyed");
	}
}

web.xml中注册监听器
<listener>
    <listener-class>com.listener.MyHttpSessionListener</listener-class>
  </listener>		

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

可以监听在作用域中值 添加 | 替换 | 移除的动作。

  • servletContext — ServletContextAttributeListener
    在这里插入图片描述

  • request — ServletRequestAttributeListener
    在这里插入图片描述

  • session — HttpSessionAttributeListener
    在这里插入图片描述

session举例

监听器

public class HttpSessionListener implements HttpSessionAttributeListener {

    public void attributeAdded(HttpSessionBindingEvent arg0) {
        System.out.println("attributeAdded");
    }

    public void attributeRemoved(HttpSessionBindingEvent arg0) {
        System.out.println("attributeRemoved");
    }

    public void attributeReplaced(HttpSessionBindingEvent arg0) {
        System.out.println("attributeReplaced");
    }
}

注册
<listener>
    <listener-class>com.listener2.HttpSessionListener</listener-class>
  </listener>

通过页面进行值得改变

</head>
<body>
	<%
		session.setAttribute("name", "zhangsan");
		session.setAttribute("name", "zhangsanupdate");
		session.removeAttribute("name");
	%>
</body>

访问页面即可看到效果

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

这一类监听器不用注册

直接定义类实现即可 但是钝化(序列化)活化(反序列化)需要多实现一个Serializable(序列化)接口

HttpSessionBindingListener

监听对象session 绑定和解除绑定 的动作

实现监听器的对象是否存放在session作用域中

绑定:session.setAttribute(“bean”,bean )

解绑:session.removeAttribute(“bean”)

1. 让javaBean 实现该接口即可
public class Bean implements HttpSessionBindingListener {
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	// 绑定到session作用于上
	public void valueBound(HttpSessionBindingEvent arg0) {
		System.out.println("对象 被  value Bound");
	}
	// 解除绑定
	public void valueUnbound(HttpSessionBindingEvent arg0) {
		System.out.println("对象 被 value UnBound");
	}
	
}

页面代码 将该bean对象存到session域中触发监听器

session.setAttribute(“bean”, bean)

<title>验证绑定和解除HttpSessionBindingListener</title>
</head>
<body>
	<%
		Bean bean = new Bean();
		bean.setName("zhangsan");
		session.setAttribute("bean", bean);
		session.removeAttribute("bean");
	%>
</body>

HttpSessionActivationListener

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

  • 钝化 (序列化)

把内存中的数据 存储到硬盘上 :正常关闭服务器钝化

  • 活化 (反序列化)

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

  • session的钝化活化的用意何在

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

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

做配置即可

META-INF/context.xml配置

1. 在tomcat里面 conf/context.xml 里面配置
	对所有的运行在这个服务器的项目生效  
	
2. 在conf/Catalina/localhost/context.xml 配置
		对 localhost生效。  localhost:8080
		
3. 在自己的web工程项目中的 META-INF/context.xml
		只对当前的工程生效。
	maxIdleSwap : 1分钟不用就钝化
	directory :  钝化后的那个文件存放的目录位置。 
	 D:\tomcat\apache-tomcat-7.0.52\work\Catalina\localhost\ListenerDemo\itheima

META-INF/context.xml

<Context>
<!-- maxIdleSwap="最大时间不用便钝化" -->
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<!--  directory=""钝化存放在tomcat\work\Catalina\localhost\项目名\ 下面的路径下的目录名" -->
	<Store className="org.apache.catalina.session.FileStore" directory="hlc"/>
</Manager>
</Context>

<!--
  1 tomcat里面conf/context.xml 自己创建
  对所有运行在这个服务器的项目有效
  2 conf/Catalina/locahost/context.xml
  域名locahost生效
  3 web项目 META-INF/context.xml
  当前工程有效
-->

bean

public class Bean2 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被钝化了");		
	}
}

钝化 :正常关闭服务器

<body>
<!-- 默认
A:\1WorkF\Application\apache-tomcat-7.0.52\work\Catalina\localhost\Listener1\SESSIONS.ser-->
<!-- 手动配置context.xml钝化的文件 META-INF里面创建context.xml
A:\1WorkF\Application\apache-tomcat-7.0.52\work\Catalina\localhost\Listener1\hlc -->
	<%
		Bean2 bean = new Bean2();
		bean.setName("zhangsan");
		session.setAttribute("bean", bean);
		//session.removeAttribute("bean");
	%>
</body>

活化:取值

<title>取值才能活化 实现序列化 HttpSessionActivationListener</title>
</head>
<body>
	${bean.name }
</body>
</html>

Filter

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
</dependency>
Filter(javax.servlet)

过滤器 , 其实就是对客户端发出来的请求进行过滤。 浏览器发出, 然后服务器派servlet处理。 在中间进行过滤, 其实过滤器起到的是拦截的作用。

作用

  • 权限控制
  • 对一些敏感词汇进行过滤
  • 统一设置编码
  • 自动登录 … …

使用Filter

  1. 定义一个类, 实现Filter
public class FilterDemo1 implements Filter {
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		System.out.println("欢迎Filter1");
		//放行 
		chain.doFilter(request, response);
		System.out.println("服务器发送经过过滤器顺序 Filter1");
	}
    
	public void init(FilterConfig fConfig) throws ServletException {
		//inti的参数filterConfig可以获取filter注册的名字参数等信息类似于servletConfig
		System.out.println("项目在服务器启动时创建");
	}
	public void destroy() {
		System.out.println("项目在服务器停止时destroy");
	}
}

  1. 注册过滤器

在web.xml里面注册,注册与servlet基本一样。

<filter>
    <display-name>FilterDemo1</display-name>
    <filter-name>FilterDemo1</filter-name>
    <filter-class>com.filter.FilterDemo1</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>FilterDemo1</filter-name>
    <url-pattern>/*</url-pattern>
<!--request 只要是请求都拦截
   	forword 只要是转发都拦截
   	error 	错误跳转都拦截   	-->
    <dispatcher>REQUEST</dispatcher>
 </filter-mapping>

关键方法

public class FilterDemo1 implements Filter {
    //过滤  是否放心
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {		
		chain.doFilter(request, response);	//放行 
	}    
    //inti的参数filterConfig可以获取filter注册的名字参数等信息类似于servletConfig项目在服务器启动时创建
	public void init(FilterConfig fConfig) throws ServletException {}	
	public void destroy() {	}//项目在服务器停止时destroy
}

Filter的生命周期

创建

在服务器启动的时候就创建。

销毁

关闭服务器或者从服务器中移除项目的时候

Filter执行顺序

客户端发出请求,先经过过滤器, 如果过滤器放行,那么才能到servlet

如果有多个过滤器(如下图), 那么他们会按照注册的映射顺序来排队。 只要有一个过滤器, 不放行,那么后面排队的过滤器以及servlet都不会收到请求。

在这里插入图片描述

Filter细节:

1 init方法的参数 FilterConfig , 可以用于获取filter在注册的名字 以及初始化参数。 其实这里的设计的初衷与ServletConfig是一样的。

2 如果想放行,那么在doFilter 方法里面操作,使用参数 chain

	chain.doFilter(request, response); 放行, 让请求到达下一个目标。

3 拦截匹配

<filter>
  <display-name>FilterDemo1</display-name>
  <filter-name>FilterDemo1</filter-name>
  <filter-class>com.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
  <filter-name>FilterDemo1</filter-name>
  <url-pattern>/*</url-pattern>
<!--request 只要是请求都拦截
 	forword 只要是转发都拦截
 	error 	错误跳转都拦截   	-->
  <dispatcher>REQUEST</dispatcher>
</filter-mapping>

< url-pattern>/*< /url-pattern> 写法格式与servlet一样。

/* 只要是客户端发送来的请求 都过滤

1、全路径匹配 以 / 开始 LoginServlet项目所有都过滤

	/LoginServlet

2、以目录匹配 以 / 开始 以 * 结束 demo01下的页面发出的请求

/demo01/*  

3、以后缀名匹配 以 * 开始 以后缀名结束

*.jsp  *.html *.do 

4、拦截servlet <servlet-name

5、针对请求类型 针对 dispatcher 设置

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

自动登录原理分析

需求分析

在这里插入图片描述

过滤器的核心是在放行之前,帮用户完成登录的功能。

  • 实现思路
  1. 先判断session是否有效, 如果有效,就不用取cookie了,直接放行。

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

  3. 没有cookie 放行

  4. 有cookie

    1. 取出来cookie的值,然后完成登录

    2. 把这个用户的值存储到session中

    3. 放行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值