Filter也称之为过滤器,它是Servlet技术中比较激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

  其顺序图如下(Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,简单说,就是可以实现web容器对某资源的访问前截获进行相关的处理,还可以在某资源向web容器返回响应前进行截获进行处理。)

过滤器,设计执行流程:

  1. 用户访问服务器
  2. 过滤器: 对Servlet请求进行拦截
  3. 先进入过滤器, 过滤器处理
  4. 过滤器处理完后, 在放行, 此时,请求到达Servlet/JSP
  5. Servlet处理
  6. Servlet处理完后,再回到过滤器, 最后在由tomcat服务器相应用户;

Filter的生命周期

(1)、init(FilterConfig filterConfig)throws ServletException:

  与servlet一样(Filter其实也是一个servlet),Filter的创建和销毁是由web服务器负责的。web服务器一启动,就会调用init()方法,完成对象的初始化功能

  (注:filter对象只会创建一次,init方法也只会执行一次。)

(2)、destroy():

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

(3)、doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

   The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.(大概的意思是在每次请求/响应时由容器创建)过滤器业务拦截的业务处理方法


程序示例

首先写一个要被访问的servlet,如下:

package com.gqx.filter;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class IndexServlet extends HttpServlet {
	/**
	 * 处理用户http request
	 */
	private static final long serialVersionUID = 1L;
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("4、处理用户请求开始!");
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}
}

然后就是去访问之前需要对请求或响应内容做处理的过滤器

package com.gqx.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
 * 测试的过滤器
 * @author Administrator
 *
 */
public class HelloFilter implements Filter {
	//创建实例
	public HelloFilter() {
	// TODO Auto-generated constructor stub
		System.out.println("1、过滤器用例开始创建了。");
	}
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("2、执行过滤器初始化方法!");
	}
	//过滤器业务处理方法,在请求到达servlet之前进入此方法处理公用的业务逻辑操作
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		System.out.println("3、执行过滤器的业务处理方法!");
		//放行(去到Servlet)
		chain.doFilter(request, response);

		System.out.println("5、Servlet处理完成,又回到Filter了!");
	}
	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		System.out.println("6、同时过滤器被销毁了!");
	}
}

最后就是要去web.xml中去配置好先关的过滤器设置

        <!-- 过滤器的配置 -->
	<filter>
		<!-- filter内部名称 -->
		<filter-name>HelloFilter</filter-name>
		<!-- 过滤器类的全名 -->
		<filter-class>com.gqx.filter.HelloFilter</filter-class>
	</filter>
	<filter-mapping>
		<!-- filter内部名称 -->
		<filter-name>HelloFilter</filter-name>
		<!-- 拦截所有的资源 -->
		<url-pattern>/*</url-pattern>
	</filter-mapping>

一切都ok了现在我在各个打印语句之前都设置了断点,可以观察到如下图所示的变化


当有多个过滤器的时候,如下

<!-- 过滤器的配置 -->
	<filter>
		<!-- filter内部名称 -->
		<filter-name>HelloFilter</filter-name>
		<!-- 过滤器类的全名 -->
		<filter-class>com.gqx.filter.HelloFilter</filter-class>
	</filter>
	<filter-mapping>
		<!-- filter内部名称 -->
		<filter-name>HelloFilter</filter-name>
		<!-- 拦截所有的资源 -->
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<!-- 配置第二个过滤器 -->
	<filter>
		<filter-name>HelloFiler2</filter-name>
		<filter-class>com.gqx.filter.HelloFilter2</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>HelloFiler2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

  

同理在第一个HelloFilter的doFilter()的方法中写入

          System.out.println("3、第一个过滤器:执行过滤器的业务处理方法!");
		//放行(去到Servlet)
		chain.doFilter(request, response);

		System.out.println("5、第一个过滤器:Servlet处理完成,又回到Filter了!");

在HelloFiler2的doFilter()的方法中写入

System.out.println("第二个过滤器!");
		chain.doFilter(request, response);
		System.out.println("第二个过滤器结束了!");

 同样在这些语句中设置断点会发现如下结果

这个时候就可以知道服务器启动后,用户去访问,根据xml中的过滤器的先后顺序来执行对应的过滤器,执行其对应的doFilter的方法放行request/response,被放行后他们就进入了第二个过滤器HelloFiler2,被第二个过滤器放行后才会回到对应的servlet,servlet运行完之后,回到第二个过滤器,再回到第一个过滤器。(如下图)


过滤器相关Api

(1)、|-- interface  Filter                            过滤器核心接口

Void  init(filterConfig);    初始化方法,在服务器启动时候执行

   Void  doFilter(request,response,filterChain);   过滤器拦截的业务处理方法

   Void destroy();                         销毁过滤器实例时候调用

(2)|-- interface  FilterConfig   获取初始化参数信息(方法类似于servletConfig)

  String getInitParameter(java.lang.String name)

  Enumeration getInitParameterNames() 


与servlet同样,在web.xml中配置先关信息

        <filter>
		<!-- 配置初始化参数 -->
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>path</param-name>
			<param-value>c:/...</param-value>
		</init-param>
		<filter-name>FilterApi</filter-name>
		<filter-class>com.gqx.filter.FilterApi</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>FilterApi</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

(注意:有时候会出现错误 cvc-complex-type.2.4.a: Invalid content was found starting with element 这个时候可以将“http://www.springmodules.org/schema/cache/springmodules-cache.xsd http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd”这段话加入到xml文件的"xmlns:xsi="的标签中)

如下:

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance http://www.springmodules.org/schema/cache/springmodules-cache.xsd http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

然后就是他的过滤器先关的内容了

public class FilterApi implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("获取过滤器在web.xml中配置的初始化参数!");
		String encoding=filterConfig.getInitParameter("encoding");
		System.out.println(encoding);
		//filterConfig.getFilterName() 获取单个
		Enumeration<String> enums=filterConfig.getInitParameterNames();
		while (enums.hasMoreElements()) {
			//获取对应的参数名称
			String name = (String) enums.nextElement();
			//获取对应名称的值
			String value=filterConfig.getInitParameter(name);
			System.out.println(name+"\t"+value);
		}
	}
	@Override
	public void destroy() {
		// TODO Auto-generated method stub
	}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
	}
}

启动服务器就会看到控制台打印的先关数据

(3)、|-- interface  FilterChain     过滤器链参数;一个个过滤器形成一个执行链;

void doFilter(ServletRequest request, ServletResponse response)  ;  执行下一个过滤器或放行


对指定的请求拦截

刚才看到的是对所有的请求进行拦截

      <filter-mapping>
		<filter-name>FilterApi</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		System.out.println("指定过滤器的拦截。。。。。");
		chain.doFilter(request, response);
	}

  

当访问index.jsp的时候,就会出现

当要对多个指定的请求进行拦截时,可以这样写

        <filter>
        <filter-name>PontedFilter</filter-name>
        <url-pattern>/index.jsp</url-pattern>
        <url-pattern>/list.jsp</url-pattern>
        <!-- 根据servlet的内部名称拦截
        <servlet-name>IndexServlet</servlet-name> -->
        <!-- 拦截指定的servlet -->
        <url-pattern>/IndexServlet</url-pattern>

	</filter-mapping>     

规则有点像servlet的配置

对类型的拦截

         <!-- 指定的拦截类型 -->
		<dispatcher>REQUEST</dispatcher>  <!-- 默认的拦截方式 -->
		<dispatcher>FORWARD</dispatcher>  <!-- 拦截转发 -->
		<dispatcher>INCLUDE</dispatcher>  <!-- 拦截包含的页面(RequestDispatcher.include(/page.jsp);    对page.jsp也执行拦截) -->
		<dispatcher>ERROR</dispatcher>

  

默认拦截的类型:(直接访问或者重定向)

<dispatcher>REQUEST</dispatcher>

拦截转发:

<dispatcher>FORWARD</dispatcher>

拦截包含的页面(RequestDispatcher.include(/page.jsp);    对page.jsp也执行拦截)

<dispatcher>INCLUDE</dispatcher>

拦截声明式异常信息:

<dispatcher>ERROR</dispatcher>

      类似于如下代码

       <error-page>
		<error-code>404</error-code>
		<exception-type></exception-type>
		<location></location>
	</error-page>

如下代码示例

<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>  <!-- 拦截转发 -->

 在ServletTets中写下

	request.getRequestDispatcher("IndexServlet").forward(request, response);

请求的转发就会被拦截住。

Filter过滤器(1)的更多相关文章

  1. filter 过滤器(监听)

    Filter 过滤器 1.简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, ...

  2. Java防止SQL注入2(通过filter过滤器功能进行拦截)

    首先说明一点,这个过滤器拦截其实是不靠谱的,比如说我的一篇文章是介绍sql注入的,或者评论的内容是有关sql的,那会过滤掉:且如果每个页面都经过这个过滤器,那么效率也是非常低的. 如果是要SQL注入拦 ...

  3. Filter(过滤器)学习

    一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态 ...

  4. javaweb学习总结(四十二)——Filter(过滤器)学习

    一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态 ...

  5. Filter过滤器简单应用( 接口访问控制 )

    一.描述 在提供安卓.IOS客户端接口时,可以在登陆接口分配Session给客户端,用于判断其他接口是否是合法访问,以避免将所有的接口都暴露在web中可以由路径直接访问.但是最近的一个项目中的移动接口 ...

  6. 如何配置Filter过滤器处理JSP中文乱码

    参考Tomcat服务器目录webapps的examples示例 简单配置步骤:1.在项目web.xml文件添加过滤器标记<filter>和<filter-mapping>:2. ...

  7. Filter(过滤器)常见应用

    孤傲苍狼 只为成功找方法,不为失败找借口! javaweb学习总结(四十六)——Filter(过滤器)常见应用 一.统一全站字符编码 通过配置参数charset指明使用何种字符编码,以处理Html F ...

  8. Servlet的学习之Filter过滤器技术(1)

    本篇将讲诉Servlet中一项非常重要的技术,Filter过滤器技术.通过过滤器,可以对来自客户端的请求进行拦截,进行预处理或者对最终响应给客户端的数据进行处理后再输出. 要想使用Filter过滤器, ...

  9. javaWeb学习总结(10)- Filter(过滤器)学习

    一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有 web资源:例如Jsp, Servlet, 静 ...

随机推荐

  1. 解决win8 plsql无法登录

    今天安装完oracle客户端,然后打开 plsql 之后,就一个提示框,提示没有登录,后来解决方法如下: 在plsql的图标上点右键,以管理员身份运行,即可! 如果不想一直点右键执行,就图标上点右键- ...

  2. 年度十佳 DevOps 博客文章(前篇)

    如果说 15 年你还没有将 DevOps 真正应用起来,16 年再不实践也未免太落伍了.国内 ITOM 领军企业 OneAPM 工程师为您翻译整理了,2015 年十佳 DevOps 文章,究竟是不是深 ...

  3. SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-006- 如何保持重定向的request数据(用model、占位符、RedirectAttributes、model.addFlashAttribute("spitter", spitter);)

    一.redirect为什么会丢数据? when a handler method completes, any model data specified in the method is copied ...

  4. Show username instead of "System Account" in SharePoint 2010

    Problems: When I load my local SharePoint site, the account always show as "System Account" ...

  5. 栈和队列的面试题Java

    栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...

  6. 归纳决策树ID3(Java实现)

    先上问题吧,我们统计了14天的气象数据(指标包括outlook,temperature,humidity,windy),并已知这些天气是否打球(play).如果给出新一天的气象指标数据:sunny,c ...

  7. 转:理解 Linux 的硬链接与软链接

    Linux 的文件与目录 现代操作系统为解决信息能独立于进程之外被长期存储引入了文件,文件作为进程 创建信息的逻辑单元可被多个进程并发使用.在 UNIX 系统中,操作系统为磁盘上的文本与图像.鼠标与键 ...

  8. BZOJ_1607_ [Usaco2008_Dec]_Patting_Heads_轻拍牛头_(筛数)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1607 给出一组n个数,求每个数能被多少个其他的数整除. 分析 暴力一点的做法就是每个数去筛它的 ...

  9. easyui treegrid 封装(不用分页,用加载更多按钮)延迟加载加加载更多

    /** * @author wsf数据加载 */ ; var intervalId = null; (function (win,$){ $.myCache = { dataCache : {},// ...

  10. 使用 Azure Site Recovery 灾难恢复至 Azure 的功能现已正式发布

    ABHISHEK A. HEMRAJANI 云 + Enterprise项目经理 自我们宣布发布使用 Azure SiteRecovery 灾难恢复至 Azure的功能预览版以来,这几个月着实令人 ...