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

xiaoxiao2025-12-14  8

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过滤器链过滤)。 [img]/upload/attachment/96710/9bb8556e-fa96-3920-b51f-850f7350d023.jpg[/img] 过滤器的主要功能包括: * 对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, ServletExceptionpublic 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() ;%>
转载请注明原文地址: https://www.6miu.com/read-5040863.html

最新回复(0)