Java web基础总结七之—— Filter与Listener

Java web基础总结七之—— Filter与Listener

一.Filter
1. Filter简介

Filter是Servlet体系中非常重要的一个技术。Filter的意思是过滤器,那么它过滤的是什么呢?就是web服务器管理的所有web资源。例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。它的代码逻辑执行在访问这些资源之前,从而进行一些特殊的操作。例如实现权限访问控制、编码和词汇的过滤等一些高级功能。

Servlet API中提供了一个Filter接口,我们一般编写一个Java类实现这个接口。可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。

2. Filter的实现原理

Filter和filterChain是一个典型的责任链设计模式。Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在访问这个web资源之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可以实现:调用目标资源之前,让一段代码执行;是否让用户访问web资源;调用目标web资源之后,让一段代码执行.

在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个FilterChain。web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

3. Filter开发的步骤

首先,编写java类实现Filter接口,并实现其doFilter方法。例如下面的防止xss注入的filter。

XssFilter.java代码:

<span style="font-size:14px;">package com.cc;

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

public class XssFilter implements Filter {
    FilterConfig filterConfig = null;

    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    public void destroy() {
        this.filterConfig = null;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {
        chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
    }
}
</span>

XssHttpServletRequestWrapper.java代码:

<span style="font-size:14px;">package com.cc;

import org.springframework.web.util.HtmlUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
        super(servletRequest);
    }

    public String[] getParameterValues(String parameter) {
        String[] values = super.getParameterValues(parameter);
        if (values == null) {
            return null;
        }
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = cleanXSS(values[i]);
        }
        return encodedValues;
    }

    public String getParameter(String parameter) {
        String value = super.getParameter(parameter);
        if (value == null) {
            return null;
        }
        return cleanXSS(value);
    }

    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (value == null)
            return null;
        return cleanXSS(value);
    }

    private String cleanXSS(String value) {
        return HtmlUtils.htmlEscape(value);
    }

}
</span>

然后,在 web.xml 文件中使用<filter>和<filter-mapping>元素对编写的filter类进行注册,并设置它所能拦截的资源。如:

    <filter>
        <filter-name>XssSqlFilter</filter-name>
        <filter-class>com.cc.XssFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>XssSqlFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

<filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。

<filter-class>元素用于指定过滤器的完整的限定类名。

<init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。

<filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径

<filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字

<url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)

<servlet-name>指定过滤器所拦截的Servlet名称。

<dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher>子元素用来指定 Filter 对资源的多种调用方式进行拦截。<dispatcher> 子元素可以设置的值及其意义:

REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。

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

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

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

4. Filter的生命周期。

Filter和Servlet一样,创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init(FilterConfig filterConfig)方法,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作。filter对象只会创建一次,init方法也只会执行一次

Filter的doFilter方法会在每一次请求相关的web资源时,都会被调用。

在Web容器卸载 Filter 对象之前,调用destroy()方法。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。

我们在配置filter时,可以使用<init-param>为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得:

String getFilterName():得到filter的名称。

String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.

ServletContext getServletContext():返回ServletContext的对象。

二.Listener

Listener的主要作用是: 做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等。我们可以编写一个实现了javax.servlet.ServletContextListener 接口的java类,在这个类中实现响应的逻辑代码。它web应用启动时,Listener也会首先随之启动,接着进行初始化,只初始化一次,当web应用停止时,他也会被web容器销毁。

例如,spring的实现的入口就是一个Listener:

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
三.servlet 、listener、 filter的加载顺序

servlet 、listener和 filter的加载顺序与它们在web.xml 文件中的先后顺序无关。并不是注册在web.xml 文件中前面的会被先加载,通过他们各自的作用。可以很显然的得到一个结论:listener 最先加载,其次是filter ,最后是 servlet。但是,如果还配置了context-param,它用于向 ServletContext
提供键值对,即应用程序上下文信息。由于listener, filter 等在初始化时会用到这些上下文中的信息,所以 context-param配置的东西会被最先加载。

例如,spring的配置文件的加载,需要在web.xml文件中注册:

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:spring/spring.xml
        </param-value>
    </context-param>
时间: 2024-08-04 08:10:28

Java web基础总结七之—— Filter与Listener的相关文章

Java Web 基础 --- Filter 综述

摘要: 伴随J2EE一起发布的Servlet规范中还包括一个重要的组件--过滤器(Filter).过滤器可以认为是Servlet的一种加强版,它主要用于对用户请求进行预处理以及对服务器响应进行后处理,是个典型的处理链.Servlet规范使用了三个接口对过滤器进行了抽象,即Filter是对具体过滤器的抽象,FilterChain是基于AOP理念对责任链方面的抽象,FilterConfig则是对Filter配置的抽象.本文概述了Filter的提出动机.工作原理.使用流程和应用实例,并指出Java W

java web基础 --- URL重定向Filter

java web基础 --- URL重定向Filter httpRequest.getRequestDispatcher("/helloWorld").forward(httpRequest, response); 服务器端转发,不改变浏览器端URL地址,常用 httpResponse.sendRedirect(uri); 浏览器端重定向,改变URL在浏览器地址栏 URLOverWriteFilter.java 1 package com.web1.util; 2 3 import j

Java Web基础知识之Filter:过滤一切你不想看到的事情

不要相信客户端, 所以做后端的人都应该铭记的事情.因为前端传过来的数据并不总是合法和有效的,所以后端是对访问资源的最后一道保护伞.之前我们在Spring中说到过AOP编程,AOP基础知识,它就可以在执行我们的方法之前进行一些预处理和验证来保护后端的资源.不难想到她的实现方式和本篇要说的过滤器的实现原理应该是相同的,都是通过Java的动态代理实现的(自己的理解). 在Java Web的开发中,过滤器用于拦截请求,并对ServletRequest对象进行处理,我们可以想到的,它可以用来验证权限.加密

从Java Web 基础看SSH架构

Java Web开发现在已然成为大型Wed项目的标准,之前一直盲目的使用框架,往往知其然不知其所以然.在经过一段时间的学习与开发,大概掌握了其脉络的基础上,对其做一定总结. 一.Java Web 基础 一个典型的Java Web项目往往包含这些元素:Jsp页面.Servlet.Listener.Filter,以及配置文件web.xml.其中: Jsp和Servlet基本是一回事,主要用来响应客户端的请求.当然Jsp中可以直接嵌入HTML标签,主要还是负责展现. Listener则是负责监听Web

Java Web基础 --- Jsp 综述(上)

摘要: J2EE是一套规范,而Servlet/Jsp是J2EE规范的一部分,是Tomcat的主要实现部分.在最初的应用实践中,当用户向指定Servlet发送请求时,Servlet利用输出流动态生成HTML页面,这导致Servlet开发效率极为低下.JSP技术通过实现普通静态HTML和动态部分混合编码,使得逻辑内容与外观相分离,大大简化了表示层的实现,提高了开发效率.本文以JSP的本质是Servlet为主线,结合JSP转译后所得的Servlet,详细探讨了JSP的原理.执行过程.脚本元素.编译指令

Java Web基础 --- Jsp 综述(下)

摘要: JSP脚本中包含九个内置对象,它们都是Servlet-API接口的实例,并且JSP规范对它们进行了默认初始化.本文首先通过一个JSP实例来认识JSP内置对象的实质,紧接着以基于请求/响应架构应用的运行机制为背景,引出JSP/Servlet的通信方式与内置对象的作用域,并对每个内置对象的常见用法进行深入介绍和总结. 一. JSP 九大内置对象概述及相关概念说明 JSP脚本中包含九个内置对象,这九个内置对象都是 Servlet API 接口的实例,并且JSP规范对它们进行了默认初始化(由 J

Java Web基础 --- Servlet 综述(实践篇)

摘要: 伴随 J2EE 6一起发布的Servlet 3.0规范是Servlet规范历史上最重要的变革之一,它的许多新的特性都极大的简化了 Java Web 应用的开发.本文从一个简单的 Servlet 例子开始,说明了如何开发.配置一个 Servlet.此外,还重点叙述了Servlet的一些新特性,包括Servlet 异步处理.Servlet 非阻塞IO 以及 Servlet 文件上传等内容,以便我们对Servlet有一个更全面的了解. 本篇主要介绍 Servlet 实践方面的知识,更多关注于S

Java web基础总结四之—— Servlet基础

Java web基础总结四之-- Servlet基础 一.什么是Servlet? 通过名字就能看出来,Servlet 就是在服务器上运行的小程序.Servlet是sun公司(现在已经属于oracle了)实现的一门用于开发动态java web资源的技术.Sun公司在其API中提供了一个servlet接口,如果你想开发一个动态的java web资源,需要完成以下2个步骤:编写一个Java类,实现servlet接口.把开发好的Java类部署到web服务器中. Servlet接口已经有了两个默认的实现类

Java web基础总结十之—— jsp EL表达式

Java web基础总结十之-- jsp EL表达式 一.EL表达式简介 EL 是Expression Language的缩写.在jsp中有很大的作用,EL主要有以下一些作用:获取数据,替换JSP页面中的脚本表达式,以从各种类型的web域中检索java对象.获取数据.还可以执行运算,利用EL表达式可以在JSP页面中执行一些基本的关系运算.逻辑运算和算术运算,以在JSP页面中完成一些简单的逻辑运算,例如 ${user==null}.还可以获取web开发常用的jsp的隐式对象,利用这些隐式对象,we