Jsp/Servlet复习笔记-----第5章 过滤器和事件监听器

5.1.1 概念
过滤器(filter)是能够对请求和响应的头属性(header)和能容体(body)进行操作的特殊Web构件。与一般Web构件(如servlet,JSP)不同的是,过滤器自身并不直接生成Web响应,若干个过滤器可以依次对一个Web资源的请求和响应进行作用。
过滤器取代了早先的Servlet链接的功能。更主要的是,过滤器是Servlet2.3版本之后的标准Web构件。它的使用方法比较方便,功能也相当强。如图5-1所示,过滤器可以在Web请求到达servlet(或JSP)之前和在servlet返回响应之后对二者进行操作。过滤器和servlet之间是多对多的关系,一个过滤器可以对多个servlet的请求和响应进行过滤(如Filter A),一个servlet也可以被多个过滤器作用(如servlet3被Filter B,C,D过滤器链过滤)。

Jsp/Servlet复习笔记-----第5章 过滤器和事件监听器

过滤器的主要功能包括:
* 对Web请求进行分析,对输入数据进行预处理
* 阻止请求和响应的进行;
* 根据功能改动请求的头信息和数据体;
* 根据功能改动响应的头信息和数据体;
* 和其他Web资源协作。
* 对用户请求进行统一认证;
* 对用户发送的数据进行过滤或替换;
* 对用户的访问进行记录和审核;
读者可能会提出一个问题:这些功能在servlet中都可以实现。确实。前面讲到的servlet API 能够对Web请求和响应进行各种各样的操作,而过滤器的主要意义是提供了一种更方便高效的编程结构。对于许多servlet都需要的功能,使用过滤器独立实现会简化servlet,避免功能重复。另外,Web容器提供了方便的过滤器管理机制,可以让编程人员更轻松地编写Web程序。
可见过滤器程序的特点是通用性和可移植性。如果一个过滤器在程序中只能用在一个servlet或JSP上面而不能被其他Web程序借用,这个过滤器的存在就没有太大意义。通常的过滤器可以用在多种情况下,比如安全保护、运行记录、图像转化、数据压缩、加密解码以及XML转化等。
5.1.2 过滤器的使用
Servlet技术中有关过滤器的API包括javax.servlet包中的Filter,FilterChain和FilterConfig接口。
过滤器要实现javax.servlet.Filter接口。与servlet相似,Filter接口中有init(),destroy()方法。Init方法在初始化时做准备工作,destroy方法在它被Web容器清除之前完成收尾工作,主要的过滤功能在doFilter方法中实现。
程序5.1是javax.servlet.Filter接口的源代码:

package javax.servlet;

import java.io.IOException;

public interface Filter {
	public void init(FilterConfig filterConfig) throws ServletException;
	
    public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain )
		throws IOException, ServletException;

	public void destroy();
}


程序 5.1
5.1.3 如何使用过滤器实现职责链模式
5.1.4 如何使用过滤器实现装饰器(decrator)设计模式
5.1.5 用MyEclipse开发过滤器使用的例子
登陆验证:

package org.sky.darkness.filter ;

import java.io.* ;
import javax.servlet.* ;
import javax.servlet.http.* ;

public class LoginFilter implements Filter
{
	public void init(FilterConfig filterConfig) throws ServletException{}
	public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain)
              throws IOException,
                     ServletException
	{
		// Session属于HTTP范畴,所以ServletRequest对象需要先转换成HttpServletRequest对象
		HttpServletRequest req = (HttpServletRequest)request ;
		HttpSession session = req.getSession() ;
		// 如果session不为空,则可以浏览其他页面
		if(session.getAttribute("uname")!=null)
		{
			chain.doFilter(request,response) ;
		}
		else
		{
			// 通过requestDispatcher跳转到登陆页
			request.getRequestDispatcher("login.jsp").forward(request,response) ;
		}
	}
	public void destroy() {}
};
/*
  <filter>
	<filter-name>login</filter-name>
	<filter-class> org.sky.darkness.filter.LoginFilter</filter-class>
  </filter>
  <filter-mapping>
	<filter-name>login</filter-name>
	<url-pattern>/*</url-pattern>
  </filter-mapping>


Servlet程序的主要分类?
 标准Servlet(JSP)-MVC
 过滤Servlet(过滤器)
 监听Servlet(监听器)

过滤器在WEB中主要起什么作用:
1. 过滤器是程序运行之后加入的
2. 功能:
 任何网站都需要对用户是否登陆进行过滤
 网上聊天系统,屏蔽非法文字
 对请求内容进行统一编码
写一个Filter类都必须继承(implements) Filter接口
public void init(FilterConfig filterConfig)
          throws ServletException
过滤器初始化是在容器启动时自动初始化的

public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain)
              throws java.io.IOException,
                     ServletException

public void destroy()


package org.sky.darkness.filter ;

import java.io.* ;
import javax.servlet.* ;

public class FirstFilter implements Filter
{
	public void init(FilterConfig filterConfig)
          throws ServletException
	{
		System.out.println("** 过滤器初始化...") ;
	}
	public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain)
              throws IOException,
                     ServletException
	{
		System.out.println("** 过滤器 doFilter (chain之前)...") ;
		chain.doFilter(request,response) ;
		System.out.println("** 过滤器 doFilter (chain之后)...") ;
	}
	public void destroy()
	{
		System.out.println("** 过滤器销毁...") ;
	}
};
/*
  <filter>
	<filter-name>first</filter-name>
	<filter-class> org.sky.darkness.filter.FirstFilter</filter-class>
  </filter>
  <filter-mapping>
	<filter-name>first</filter-name>
	<url-pattern>/*</url-pattern>
  </filter-mapping>
*/


xml文件中的配置:

<filter>
   <filter-name> first </filter-name>
   <filter-class> org.sky.darkness.filter.FirstFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name> first </filter-name>
   <url-pattern>/*</url-pattern>//与servlet的不一样,此处表示对哪个页面进行过滤
</filter-mapping>


如果过滤器要将内容传递到目的地,则需要FilterChain,将请求继续向下转发chain.doFilter(request, response)

过滤器执行两次,chain之前执行一次,chain之后执行一次
1.过滤非法文字:

string content = request.getParameter(“content”);
    if(content != null){
if(content.indexOf(“AAA”)==-1)chain.doFilter(req,res);
else  out .println(“有非法文字!!!”);
   }else chain.doFilter(req,res);


package org.sky.darkness.filter ;

import java.io.* ;
import javax.servlet.* ;

public class CharFilter implements Filter
{
	public void init(FilterConfig filterConfig)
          throws ServletException
	{
		// System.out.println("** 过滤器初始化...") ;
	}
	public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain)
              throws IOException,
                     ServletException
	{
		String content = request.getParameter("content") ;
		// 如果indexOf返回-1则表示没有查到所要的内容
		if(content!=null)
		{
			if(content.indexOf("AAA")==-1)
			{
				chain.doFilter(request,response) ;
			}
			else
			{
				System.out.println("有非法文字") ;
				// 如果需要的话,此处依然可以使用RequestDispatcher进行跳转
			}	
		}
		else
		{
			chain.doFilter(request,response) ;
		}
	}
	public void destroy()
	{
		// System.out.println("** 过滤器销毁...") ;
	}
};
/*
  <filter>
	<filter-name>char</filter-name>
	<filter-class>org.sky.darkness.filter.CharFilter</filter-class>
  </filter>
  <filter-mapping>
	<filter-name>char</filter-name>
	<url-pattern>/*</url-pattern>
  </filter-mapping>
*/


2. 进行统一编码

request.setCharacterEncoding(“gb2312”)


package org.sky.darkness.filter ;

import java.io.* ;
import javax.servlet.* ;

public class EncodingFilter implements Filter
{
	public void init(FilterConfig filterConfig)
          throws ServletException
	{
		// System.out.println("** 过滤器初始化...") ;
	}
	public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain)
              throws IOException,
                     ServletException
	{
		try
		{
			request.setCharacterEncoding("GB2312") ;	
		}
		catch (Exception e)
		{
		}
		
		chain.doFilter(request,response) ;
	}
	public void destroy()
	{
		// System.out.println("** 过滤器销毁...") ;
	}
};
/*
  <filter>
	<filter-name>encoding</filter-name>
	<filter-class> org.sky.darkness.filter.EncodingFilter</filter-class>
  </filter>
  <filter-mapping>
	<filter-name>encoding</filter-name>
	<url-pattern>/*</url-pattern>
  </filter-mapping>
*/


3.登陆验证
   Session属于HTTP范畴,所以ServletRequset对象需要先转换为 HttpServletRequest对象

HttpServletRequest req = (HttpServletRequest)req;
   HttpSession session = req.getSession();
   if(session.getAttribute(“uname”) != null)
       chain.doFilter(req,res);
   else
       request.getRequestDispatcher(“login.jsp”).forward(req,res);


package org.sky.darkness.filter ;

import java.io.* ;
import javax.servlet.* ;
import javax.servlet.http.* ;

public class LoginFilter implements Filter
{
	public void init(FilterConfig filterConfig)
          throws ServletException
	{
		// System.out.println("** 过滤器初始化...") ;
	}
	public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain)
              throws IOException,
                     ServletException
	{
		// Session属于HTTP范畴,所以ServletRequest对象需要先转换成HttpServletRequest对象
		HttpServletRequest req = (HttpServletRequest)request ;
		HttpSession session = req.getSession() ;
		// 如果session不为空,则可以浏览其他页面
		if(session.getAttribute("uname")!=null)
		{
			chain.doFilter(request,response) ;
		}
		else
		{
			// 通过requestDispatcher跳转到登陆页
			request.getRequestDispatcher("login.jsp").forward(request,response) ;
		}
	}
	public void destroy()
	{
		// System.out.println("** 过滤器销毁...") ;
	}
};
/*
  <filter>
	<filter-name>login</filter-name>
	<filter-class> org.sky.darkness.filter.LoginFilter</filter-class>
  </filter>
  <filter-mapping>
	<filter-name>login</filter-name>
	<url-pattern>/*</url-pattern>
  </filter-mapping>
*/



原则:开发时只专注于具体的业务实现,而对于登陆之类的验证,肯定属于组件,向整个程序中单独加入的。


监听器
5.2.1概念  
5.2.2 事件监听器的使用
5.2.3 MyEclipse开发事件监听器使用的例子
监听器是指对于整个WEB环境的监听
主要有以下三类:
 ServletContext:Servlet上下文
 Session:对Session监听
 Request监听

一、 对ServletContext的监听
在web端实现监听 = 实现一系列的监听接口
1、 ServletContextListener:对整个 servlet上下文进行监听(启动,销毁)
public void contextInitialized(ServletContextEvent sce):上下文初始化
public void contextDestroyed(ServletContextEvent sce):上下文销毁

ServletContextEvent事件:取得一个ServletContext (Applicaton)对象
public ServletContext getServletContext()
2、 ServletContextAttributeListener:对Servlet上下文属性进行监听
public void attributeAdded(ServletContextAttributeEvent scab):增加属性(setAttribute)
public void attributeRemoved(ServletContextAttributeEvent scab) :属性删除(removeAttribute)
public void attributeReplaced(ServletContextAttributeEvent scab):属性替换(第二次设置同一个属性)

ServletContextAttributeEvent事件:
public java.lang.String getName()
public java.lang.Object getValue()

回顾: 设置属性的方法
    Public void setAttribute (String name ,Object  value)

package org.sky.darkness.listener ;

import javax.servlet.* ;

public class ServletContextDemo
	implements ServletContextListener,ServletContextAttributeListener
{
	private ServletContext application = null ;
	// 实现方法
	public void contextInitialized(ServletContextEvent sce)
	{
		this.application = sce.getServletContext() ;
		System.out.println("** 上下文初始化 ...") ;
		System.out.println("** 当前虚拟目录的绝对路径:"+this.application.getRealPath("/")) ;
	}
	public void contextDestroyed(ServletContextEvent sce)
	{
		System.out.println("** 上下文销毁 ...") ;
	}

	public void attributeAdded(ServletContextAttributeEvent scab)
	{
		System.out.println("** 增加属性:"+scab.getName()+" --> "+scab.getValue()) ;
	}
	public void attributeRemoved(ServletContextAttributeEvent scab)
	{
		System.out.println("** 删除属性:"+scab.getName()+" --> "+scab.getValue()) ;
	}
	public void attributeReplaced(ServletContextAttributeEvent scab)
	{
		System.out.println("** 替换属性:"+scab.getName()+" --> "+scab.getValue()) ;
	}
};

/*
  <listener>
	<listener-class> org.sky.darkness.listener.ServletContextDemo</listener-class>
  </listener>
*/


<!--测试页面-->

<%
	// getServletContext().setAttribute("name","LiXingHua") ;
	getServletContext().removeAttribute("name") ;
%>


上下文监听主要是针对容器的:初始化、销毁、属性操作
二、 对Session监听

对session的创建、销毁、属性操作

Session属于http协议下的内容:javax.servlet.http.HttpSessionXxxx
1、 HttpSessionListener:对session的整体状况的监听
public void sessionCreated(HttpSessionEvent se)
public void sessionDestroyed(HttpSessionEvent se):session销毁

HttpSessionEvent事件:
public HttpSession getSession():取得当前操作的 session
2、 HttpSessionAttributeListener

public void attributeAdded(HttpSessionBindingEvent se)
public void attributeRemoved(HttpSessionBindingEvent se)
public void attributeReplaced(HttpSessionBindingEvent se)

HttpSessionBindingEvent事件:
public HttpSession getSession():取得当前的Session
public java.lang.String getName():取得属性的名称
public java.lang.Object getValue()

package org.sky.darkness.listener ;

import javax.servlet.http.* ;

public class HttpSessionDemo 
	implements HttpSessionListener,HttpSessionAttributeListener
{
	private HttpSession session ;
	// 实现方法
	public void sessionCreated(HttpSessionEvent se)
	{
		this.session = se.getSession() ;
		System.out.println("** Session 创建 ....") ;
		System.out.println("** SessionID --> "+this.session.getId()) ;
	}
	public void sessionDestroyed(HttpSessionEvent se)
	{
		System.out.println("** Session 销毁 ....") ;
	}
	public void attributeAdded(HttpSessionBindingEvent se)
	{
		System.out.println("** Session 增加属性:"+se.getName()+" --> "+se.getValue()) ;
	}
	public void attributeRemoved(HttpSessionBindingEvent se)
	{
		System.out.println("** Session 删除属性:"+se.getName()+" --> "+se.getValue()) ;
	}
	public void attributeReplaced(HttpSessionBindingEvent se)
	{
		System.out.println("** Session 替换属性:"+se.getName()+" --> "+se.getValue()) ;
	}
};
/*
  <listener>
	<listener-class> org.sky.darkness.listener.HttpSessionDemo</listener-class>
  </listener>
*/

<%
	// session.setAttribute("name","LXh") ;
	// session.removeAttribute("name") ;
	session.invalidate() ;
%>


Session如何销毁?
1、 session超时
需要在xml文件中进行配置
<session-config>
<session-timetout>1</session-timeout>//session一分钟失效
</session-config>
2、 手工使session失效
Invalidate()

案例:
统计在线人员列表
实现那几个接口?
1、 在线人员列表是对所有人都起作用,所有的数据必须保存在application之中,这意味着在OnlineDemo中必须有一个ServletContext对象
2、 是针对session的变化进行的操作
如果登陆成功,则将用户名保存在session中
3、 如果用户注销,则将相应的用户名删除掉

因为用户名是多个,所以无法确定个数,使用list

package org.sky.darkness.listener ;

import java.util.* ;
import javax.servlet.* ;
import javax.servlet.http.* ;

public class OnLineDemo 
	implements ServletContextListener,HttpSessionListener,HttpSessionAttributeListener
{
	// 声明一个ServletContext对象
	private ServletContext application = null ;
	public void contextInitialized(ServletContextEvent sce)
	{
		// 容器初始化时,向application中存放一个空的容器
		this.application = sce.getServletContext() ;
		this.application.setAttribute("alluser",new ArrayList()) ;
	}

	public void contextDestroyed(ServletContextEvent sce)
	{}

	public void sessionCreated(HttpSessionEvent se)
	{}
	public void sessionDestroyed(HttpSessionEvent se)
	{
		// 将用户名称从列表中删除
		List l = (List)this.application.getAttribute("alluser") ;
		String value = (String)se.getSession().getAttribute("uname") ;
		l.remove(value) ;
		this.application.setAttribute("alluser",l) ;
	}

	public void attributeAdded(HttpSessionBindingEvent se)
	{
		// 如果登陆成功,则将用户名保存在列表之中
		List l = (List)this.application.getAttribute("alluser") ;
		l.add(se.getValue()) ;
		this.application.setAttribute("alluser",l) ;
	}
	public void attributeRemoved(HttpSessionBindingEvent se)
	{}
	public void attributeReplaced(HttpSessionBindingEvent se)
	{}
};
/*
  <listener>
	<listener-class>cn.mldn.lxh.listener.OnLineDemo</listener-class>
  </listener>
*/


<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.util.*"%>
<form action="online.jsp" method="post">
用户名:
<input type="text" name="name">
<input type="submit" value="登陆">
<a href="logout.jsp">注销</a>
</form>
<!-- 向session接收输入的用户名 -->
<%
	if(request.getParameter("name")!=null)
	{
		session.setAttribute("uname",request.getParameter("name")) ;
	}
%>
<h2>在线人员</h2>
<hr>
<%
	List l = (List)application.getAttribute("alluser") ;
	Iterator iter = l.iterator() ;
	while(iter.hasNext())
	{
%>
		<li><%=iter.next()%>
<%
	}
%>
-------------------------------------------------------logout.jsp-------------------
<%
	session.invalidate() ;
%>




你可能感兴趣的:(jsp,Web,servlet,浏览器,MyEclipse)