监听器Listener和过滤器Filter学习笔记

Listener监听器

javaweb开发中的监听器,用于监听web常见对象

HttpServletRequest、HttpSession、ServletContext(三个域对象)

的创建与销毁、属性变化、session绑定javaBean的。

监听机制

1.事件:就是一个事情

2.事件源:产生这个事件的源头

3.监听器:用于监听指定事件的对象

4.注册监听:监听器要想可以监听到事件的产生,必须进行注册。

常见监听器

监听域对象创建与销毁域对象的属性变化
ServletContextServletContextListenerServletContextAttributeListener
HttpSessionHttpSessionListenerHttpSessionAttributeListener
HttpServletRequestServletRequestListenerServletRequestAttributeListener

 

监听session绑定javaBean

HttpSessionBindingListener

用于监听JavaBean对象是否绑定到session域

HttpSessionActivationListener

用于监听javaBean对象的活化与钝化(序列化文件的消失与生成)


关于域对象创建和销毁的监听接口只有两个方法:

...Created(...)监听创建的方法

...Destroyed(...)监听销毁的方法

关于域对象属性变化的监听接口只有三个方法:

attributeAdded(...)监听属性添加的方法

attributeRemoved(...)监听属性移除的方法

attributeReplaced(...)监听属性替换的方法

监听器快速入门

创建一个监听器的步骤

1.创建一个类实现指定的监听器接口

2.重写接口中的方法

3.在web.xml文件中对监听器进行注册

域对象创建销毁代码演示:

package com.aloha.listenerTest;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class Test1 implements ServletContextListener {

	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("ServletContext对象创建了");
	}

	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("ServletContext对象销毁了");
	}

}
  <!-- 在web.xml文件中对监听器注册 -->
  <listener>
  	<listener-class>com.aloha.listenerTest.Test1</listener-class>
  </listener>

 

打开服务时

关闭服务时 

 

Session的监听存在于:开启session时,第一次访问页面时session创建。关闭服务器,30分钟内不使用、session调用invalidate()方法、设置最大存活时间setMaxInactiveInterval(int interval)可以使session销毁。这里不做session的演示了。

ServletRequest的监听存在于:Servlet中的service()方法一执行,就创建了;service()方法执行完毕,就销毁了。JSP也是Servlet。

 

域对象属性变化演示:

package com.aloha.listenerTest;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;

public class Test2 implements ServletRequestAttributeListener{

	public void attributeAdded(ServletRequestAttributeEvent srae) {
		System.out.println("ServletRequest添加属性了");
	}

	public void attributeRemoved(ServletRequestAttributeEvent srae) {
		System.out.println("ServletRequest删除属性了");
	}

	public void attributeReplaced(ServletRequestAttributeEvent srae) {
		System.out.println("ServletRequest替换属性了");
		System.out.println(srae.getName()+" "+srae.getValue());
	}

}
  <listener>
  	<listener-class>com.aloha.listenerTest.Test2</listener-class>
  </listener>

jsp中代码片段:

  <body>
  		<%
  			request.setAttribute("tom", "cat");
  			request.setAttribute("tom", "miaomiaomiao");
  			request.removeAttribute("tom");
  		 %>
  </body>

 

 

 

一个定时销毁Session的Demo(部分代码):

代码实现功能:间隔两秒后,开始每隔5秒执行一次任务,任务内容是如果session存活时间超过5秒,则销毁session并将session从集合中移除。适用于秒杀类网页功能,可以节省session。

package com.aloha.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;


import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSession;

public class Mscl implements ServletContextListener{

	public void contextInitialized(ServletContextEvent sce) {
		//通过事件源对象得到事件源(ServletContext)
		ServletContext application = sce.getServletContext();
		//创建一个集合用于存储所有session对象
//		final List<HttpSession> list = new ArrayList<HttpSession>();//线程不安全,并发修改异常
		final List<HttpSession> list = Collections.synchronizedList( new ArrayList<HttpSession>());
		//把集合放到application中
		application.setAttribute("sessions", list);
		//创建一个计时器对象
		Timer t = new Timer();
		t.schedule(new TimerTask() {
			
			@Override
			public void run() {//遍历集合
				System.out.println("开始扫描了。。。");
				for (Iterator iterator = list.iterator(); iterator.hasNext();) {
					HttpSession session = (HttpSession) iterator.next();
					long l = System.currentTimeMillis() - session.getLastAccessedTime();
					if(l>5000){
						System.out.println("session移除了"+session.getId());
						session.invalidate();
//						list.remove(session);
						iterator.remove();
					}
				}
			/*	这种遍历方法不能进行运算修改!
			 * for (HttpSession session : list) {//匿名内部类必须得是final类型变量
					long l = System.currentTimeMillis() - session.getLastAccessedTime();
					if(l>5000){
						session.invalidate();
						list.remove(session);
					}
				}*/
			}
		}, 2000, 5000);//延迟两秒后间隔5秒执行一次
		
		
		//再在web.xml中注册
	}

	public void contextDestroyed(ServletContextEvent sce) {
		
	}

}
package com.aloha.test;

import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class Msl implements HttpSessionListener{

	public void sessionCreated(HttpSessionEvent se) {
		//通过时间元对象获取session对象
		HttpSession session = se.getSession();
		//通过session对象获取Servlet应用对象
		ServletContext application = session.getServletContext();
		//通过应用对象获取session并将session对象放到list集合中
		List<HttpSession> list = (List<HttpSession>) application.getAttribute("sessions");
		
		list.add(session);
		System.out.println("添加了"+session.getId());
	}

	public void sessionDestroyed(HttpSessionEvent se) {
		
	}

}

 

Filter过滤器

对于图书管理系统,我们就可以使用Filter来区分登陆者是管理员还是普通用户。

Filter的位置?如果我们添加了过滤器,那么浏览器每次发请求的时候都会先将请求发给过滤器,过滤器也是servlet,过滤器通过我们规定的过滤,将过滤后的内容发送给服务器。服务器给浏览器的响应也是如此,响应的时候会对数据进行压缩。

Filter对象要在web.xml中配置,可以做验证操作,起过滤拦截的作用。

javaweb中过滤器可以拦截所有访问web资源的请求或响应操作。

Filter步骤

1.创建一个类实现Filter接口。

2.该类中实现Filter接口中的doFilter()方法。

3.在web.xml文件中加入过滤器的注册。

注意:在实现类中的doFilter(...)方法中我们需要使用chain.doFilter(request,response) 方法放行,否则资源无法被访问到。

Filter生命周期

服务器启动时会创建Filter对象,并调用init方法,只调用一次;

当访问资源时,路径与拦截路径匹配,则执行Filter中的doFilter方法;

服务器关闭时,调用Filter中的destroy方法进行销毁操作。

 

其实和Servlet生命周期相同。

FilterConfig

 

方法摘要
 StringgetFilterName()
          Returns the filter-name of this filter as defined in the deployment descriptor.
 StringgetInitParameter(String name)
          Returns a String containing the value of the named initialization parameter, or null if the parameter does not exist.
 EnumerationgetInitParameterNames()
          Returns the names of the filter's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the filter has no initialization parameters.
 ServletContextgetServletContext()
          Returns a reference to the ServletContext in which the caller is executing.

     1.<url-pattern>

              完全匹配   以”/demo1”开始,不包含通配符*

              目录匹配   以”/”开始  以*结束      所有资源  /*

              扩展名匹配  *.xxx  不能写成/*.xxx

     2.<servlet-name>

              它是对指定的servlet名称的servlet进行拦截的。

     3.<dispatcher>

       可以取的值有  REQUEST  FORWARD  ERROR  INCLUDE

它的作用是:当以什么方式去访问web资源时,进行拦截操作.     

1.REQUEST 当是从浏览器直接访问资源,或是重定向到某个资源时进行拦截方式配置的 它也是默认值

2.FORWARD 它描述的是请求转发的拦截方式配置

3.ERROR 如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

4.INCLUDE 如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用

 

自动登录案例

创建表

USE jdbctest;
SELECT DATABASE();

CREATE TABLE usera(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(100),
PASSWORD VARCHAR(100)
);

INSERT INTO usera VALUES(NULL,'tom','123');

一个网页自动登录的案例,Servlet的综合应用

 

全局过滤解决乱码问题

 对于post方法提交的表单,可以使用下面的过滤器实现编码过滤:

public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		req.setCharacterEncoding("UTF-8");
		
		chain.doFilter(request, response);
	}

对于get方法提交的表单,这种方法是无效的,解决办法是:1.不要写get(哈哈哈,开玩笑)2.使用装饰者模式:

写一个装饰者类提供iso-8859-1到UTF-8的转换功能:

public class MyRequest extends HttpServletRequestWrapper {

	private HttpServletRequest request;

	public MyRequest(HttpServletRequest request) {
		super(request);
		this.request = request ;
	}

	@Override
	public String getParameter(String name) {
		name = request.getParameter(name);
		try {
			return new String(name.getBytes("iso-8859-1"), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}
}

装饰:

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;	
		req = new MyRequest(req);
		chain.doFilter(req, response);
	}

 

 

装饰着使用Map集合,对多个标签处理(部分代码):

@Override
	public String getParameter(String name) {
		Map<String, String[]> map = getParameterMap();
		return map.get(name)[0];
	}

	@Override
	public String[] getParameterValues(String name) {
		Map<String, String[]> map = getParameterMap();
		return map.get(name);
	}

	private boolean flag = true;

	@Override
	public Map<String, String[]> getParameterMap() {
		Map<String, String[]> map = request.getParameterMap();// 乱码
		if (flag) {
			for (Map.Entry<String, String[]> m : map.entrySet()) {
				String[] values = m.getValue();
				for (int i = 0; i < values.length; i++) {
					try {
						values[i] = new String(
								values[i].getBytes("iso-8859-1"), "UTF-8");
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
				}

			}
			flag = false;
		}
		return map;

	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值