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

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

  要想使用Filter过滤器,非常简单,只要实现Servlet  API中的Filter接口即可,同时在该web应用【WEB-INF】目录下的web.xml文件中配置<filter>和<filter-mapping>两个标签。其中可以根据配置指定过滤的页面或者Servlet。

  也就是说我们在web工程中光光写Filter过滤器的Java代码是不会起作用的,要在web.xml文件中对过滤器进行注册和映射,在学习Filter之前我们先来学习如何注册和映射

关于注册:

  需要在web.xml文件中配置<filter>标签,这还不够,<filter>标签下的<filter-name>与<filter-class>是必须要填的内容。

  <filter>标签中有如下子元素:

  <description>用于描述该标签,非必须;

  <filter-name>为过滤器指定一个名称,必须的

  <filter-class>指定该过滤器使用的web工程中的哪一个filter类,包含包名与类名,必须的;

  <init-param>为过滤器的初始化提供参数,非必须,后面有例子。

关于映射:

  需要在web.xml文件中配置<filter-mapping>标签,这还不够,<filter-mapping>标签下的<filter-name>以及<url-pattern>或<servlet-name>之一是必须的。

  <filter-mapping>标签中有如下子元素:

  <filter-name>设置要映射过滤器的名称,该名称必须同<filter>标签下的<filter-name>的值一致。

  <url-pattern>设置过滤器要拦截过滤的请求路径,例如“/*”则表示对该web应用下所有的请求都进行拦截过滤,这个值的书写与《Servlet的学习(四)》 中关于<servlet-mapping>下的<url-mapping>是一致的写法。

  <servlet-name>如果只要拦截过滤访问某个Servlet,就可以使用该标签来替代<url-pattern>。

  <dispatcher>设置拦截过滤客户端请求的方式,有REQUEST,INCLUDE,FORWARD,ERROR四种(请注意均为大写)。非必须则默认为REQUEST,使用多个<dispatcher>标签来设置多种请求方式。

  关于<dispathcer>的四种方式,这里再简单的介绍一下:

  REQUEST:当用户直接访问我们的资源时,这时我们设置的过滤器就会进行拦截。但如果以转发和包含方式访问资源,那么该过滤器则不会被调用。

  INCLUDE:当使用RequestDispatch的include方法请求时,该过滤器会被调用。

  FORWARD:当使用RequestDispatch的forward方法时请求资源时,该过滤器会被调用,尤其是在MVC设计模式下,JSP都被保护起来,必须要通过Servlet进行转发才能访问JSP,那么该过滤器就是在Servlet转发到JSP这个过程中被执行。

  ERROR:当请求是通过错误异常进行跳转时就会调用该过滤器。

  一个简单的对过滤器的注册和映射的示例:

<filter>
  	<filter-name>FilterDemo1</filter-name>
  	<filter-class>com.fjdingsd.web.filter.FilterDemo1</filter-class>
  </filter>

  <filter-mapping>
  	<filter-name>FilterDemo1</filter-name>
  	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>FORWARD</dispatcher>
</filter-mapping>

  在Servlet API 中关于Filter举例了使用过滤器能用来做些什么:

  

  这里我也说明下平时Filter能在哪些方面会被经常用到:

  ① Filter可以作用在请求资源执行之前,进行权限检查,检查用户是否有权限,如有权限则放行请求;如果没有,则拒绝访问。

  ② Filter可以作用在请求资源执行之前,对Request和Response对象进行预处理操作,从而实现一些web应用的全局性设置,比如解决中文乱码问题。

  ③ Filter可以作用在最终响应输出之前,对输出Response对象中的数据进行处理,例如将输出的数据进行压缩。

  Filter只有3个方法:

  

  其中destroy()方法和init(…)方法是生命周期方法,因为过滤器无论如何都要在请求任何资源之前进行,所以任何Web应用在部署的时候,服务器就会调用Filter过滤器的init方法进行初始化,而关于过滤器的销毁,则是将该过滤器移除或者服务器关闭就会执行destory方法。

  而我们通常要使用过滤器处理请求,则重点在于doFilter(…)方法。当请求要经过一个过滤器的时候,就会由服务器调用doFilter方法。

  我们先来看看一个带有过滤器Filter的web应用的请求和响应流程:

  

  记住:从请求到响应这个流程会经过Filter对象两次!

  在doFilter这一个方法中就可以对着两次经过的过程进行处理,那么这里就有一个问题了,如果能通过过滤器,那么就到过滤器后面了,貌似应该是执行完doFilter方法了,而服务器的响应又经过过滤器,难道又要执行doFilter方法一次?但是这个方法里面的代码不是也有处理最开始请求的吗?

  这就跟doFilter方法中的第三个参数FilterChain有关了,FilterChain对象是过滤器链,这个我们稍后会介绍。在FilterChain对象中只有一个方法:

  

  也是叫doFilter方法(千万别和Filter接口的doFilter方法弄混了)。简单的说下这个方法,只要调用了这个方法,就会将请求交给后面一个Filter进行过滤(一个Web应用中可以有多个Filter),如果该Filter是最后一个,那么调用该方法则将执行请求,也就是到我们的应用中获取资源。

  因此从请求到响应这个流程经过Filter的两次处理分别是在FilterChain.doFilter方法的前面和后面!如下图所示:

  

  那么下面我们就先以一个简单的例子来熟悉下Filter吧:

例1

  创建web工程FilterLearning,创建一个FilterDemo1类,同时这个类要实现javax.servlet.Filter接口。如下代码:

 1 public class FilterDemo1 implements Filter {
 2
 3     @Override
 4     public void doFilter(ServletRequest request, ServletResponse response,
 5             FilterChain chain) throws IOException, ServletException {
 6
 7         System.out.println("hello filter");
 8     }
 9
10     //此处省略init方法和destory方法
11 }

  写好Filter的Java代码还没完,还要在web应用下的web.xml文件中配置如下信息:

1 <filter>
2       <filter-name>FilterDemo1</filter-name>
3       <filter-class>com.fjdingsd.web.filter.FilterDemo1</filter-class>
4   </filter>
5
6   <filter-mapping>
7       <filter-name>FilterDemo1</filter-name>
8       <url-pattern>/*</url-pattern>
9 </filter-mapping>

  注意:因为我在<url-pattern>中配置为“/*”,则访问我wen应用中任何资源都会经过该Filter过滤器。如果只想对于index.jsp主页的请求进行过滤,可以设为<url-pattern>/index.jsp</url-pattern>。

  我们在index.jsp中简单的使用JSP脚本来演示如果有请求来就输入一段文本到控制台上:

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2
 3 <!DOCTYPE HTML>
 4 <html>
 5   <head>
 6     <title>index</title>
 7   </head>
 8
 9   <body>
10     <%
11         System.out.println("Long live SD !");
12      %>
13   </body>
14 </html>

  接下来将该web应用部署到服务器中,我们就访问index.jsp,以下是我们访问了index.jsp后控制台的情况:

  

  首先,我们可以保证在我们访问index.jsp后这个请求确实经过了Filter过滤器,但是我们的请求好像就只到过滤器而没有到我们真正需要的资源index.jsp?这是因为我们没有在Filter的doFilter方法中调用过滤器链FilterChain对象的doFilter方法,自然无法将请求继续往后面传递。我们将在例2中修改。

例2

  我们将例1中的FilterDemo1类进行修改,使其能访问到我们所需要的资源,很简单,在doFilter的方法中添加过滤器链FilterChain对象的doFilter方法即可:

 1 public class FilterDemo1 implements Filter {
 2
 3     @Override
 4     public void doFilter(ServletRequest request, ServletResponse response,
 5             FilterChain chain) throws IOException, ServletException {
 6
 7         System.out.println("hello filter");
 8         chain.doFilter(request, response);
 9     }
10     //此处省略init方法和destory方法
11 }

  其他如web.xml中的配置和index.jsp中的代码保持不变,现在我们再来访问下该web应用中的index.jsp,并观察控制台:

  

  可以看到我们的请求经过过滤器,执行了过滤器的一段代码(System.out.println(“hello filter”)),然后将请求继续执行!正是因为FilterChain.doFilter方法才使我们通过过滤器继续向后寻找我们所需的资源。

  那么还记得我们之前说过的从请求到响应会经过两次过滤器吗,是的在获取了我们所需的资源后还会到过滤器一趟,而至于这时候是否将响应再做处理取决于过滤器链FilterChain.doFilter方法后面还是否有代码。我们将在例3中完整的展现从请求到响应经过过滤器两次的流程。

例3

  我们将例2中的FilterDemo1类进行修改,只要在FilterChain.doFilter方法后面添加代码,就是第二次(即响应)经过过滤器所要执行的处理:

 1 public class FilterDemo1 implements Filter {
 2
 3     @Override
 4     public void doFilter(ServletRequest request, ServletResponse response,
 5             FilterChain chain) throws IOException, ServletException {
 6
 7         System.out.println("hello filter");
 8         chain.doFilter(request, response);
 9         System.out.println("goodbye filter");
10     }
11     //此处省略init方法和destory方法
12 }

  其他如web.xml中的配置和index.jsp中的代码保持不变,现在我们再来访问下该web应用中的index.jsp,并观察控制台:

  

  这个结果证明了从请求到响应确实经过过滤器两次,同时也说明了在Filter的doFilter方法中“过滤——取资源——再过滤”执行的顺序。

  现在我们再回到Filter接口的init方法,我们可以看到在这个方法内有一个参数FilterConfig,这个是由服务器传给我们的对象。如果我们在web.xml文件中配置了过滤器的初始化参数,就可以通过该FilterConfig对象来在代码中获取使用。

  这个过滤器参数的初始化配置可以在<filter>标签中配置<init-param>,并在这个<init-param>标签下再配置<param-name>和<param-value>。

  FilterConfig有如下方法:

  

  当然如果我们是要获取配置的初始化参数则只需关注getInitParameter方法或getInitParameterNames方法。

  一般来说我们可以在init方法中获取配置初始化参数并进行处理;也可以通过对象引用将FilterConfig对象在doFilter方法中处理参数,如例4所示。

例4

  在web.xml文件中配置过滤器和初始化参数:

 1 <filter>
 2       <filter-name>FilterDemo1</filter-name>
 3       <filter-class>com.fjdingsd.web.filter.FilterDemo1</filter-class>
 4       <init-param>
 5           <param-name>Love</param-name>
 6           <param-value>LRR</param-value>
 7       </init-param>
 8   </filter>
 9
10   <filter-mapping>
11       <filter-name>FilterDemo1</filter-name>
12       <url-pattern>/*</url-pattern>
13 </filter-mapping>

  在Java中编写Filter接口的实现类FilterDemo1:

 1 public class FilterDemo1 implements Filter {
 2     private FilterConfig filterConfig ;
 3
 4     @Override
 5     public void doFilter(ServletRequest request, ServletResponse response,
 6             FilterChain chain) throws IOException, ServletException {
 7
 8         String value = filterConfig.getInitParameter("Love");
 9         System.out.println(value);
10     }
11
12     @Override
13     public void init(FilterConfig filterConfig) throws ServletException {
14         this.filterConfig = filterConfig;
15     }
16     //此处省略destroy方法
17 }

  因为配置的原因,所以我们随便访问个资源都可以经过该过滤器,那么就访问index.jsp好了,看看控制台的结果:

  

  正如我们在web.xml文件所配置的初始化参数一样。

  

  上面介绍的都是只有一个Filter过滤器的情况下,有时候我们会因为要过滤的功能不同添加多个过滤器,这就有一个顺序的问题了,尤其是从取得资源后再返回到过滤器的顺序。下面这张图就能很清晰的看到我们要注意的顺序了:

  

例5

  来写两个Filter来说明下从请求到响应过滤器的处理顺序。

  创建一个web工程,创建一个FilterDemo1类,同时这个类要实现javax.servlet.Filter接口。如下代码:

 1 public class FilterDemo1 implements Filter {
 2
 3     public void doFilter(ServletRequest request, ServletResponse response,
 4             FilterChain chain) throws IOException, ServletException {
 5
 6         System.out.println("Hello filter 1");
 7         chain.doFilter(request, response);
 8         System.out.println("Goodbye filter 1");
 9     }
10 //此处省略init方法和destroy方法
11 }

  创建第二个Filter接口实现类FilterDemo2,代码如下:

 1 public class FilterDemo2 implements Filter {
 2
 3     public void doFilter(ServletRequest request, ServletResponse response,
 4             FilterChain chain) throws IOException, ServletException {
 5         System.out.println("Hello filter 2");
 6         chain.doFilter(request, response);
 7         System.out.println("Goodbye filter 2");
 8     }
 9 //此处省略init方法和destroy方法
10 }

  过滤器要想能被服务器调用,还必须要在该web工程下的web.xml中配置过滤器及其映射,而这个配置的顺序就是影响多个过滤器工作先后的顺序:

 1 <filter>
 2       <filter-name>FilterDemo1</filter-name>
 3       <filter-class>com.fjdingsd.web.filter.FilterDemo1</filter-class>
 4 </filter>
 5
 6   <filter-mapping>
 7       <filter-name>FilterDemo1</filter-name>
 8       <url-pattern>/*</url-pattern>
 9   </filter-mapping>
10
11   <filter>
12       <filter-name>FilterDemo2</filter-name>
13       <filter-class>com.fjdingsd.web.filter.FilterDemo2</filter-class>
14   </filter>
15
16   <filter-mapping>
17       <filter-name>FilterDemo2</filter-name>
18       <url-pattern>/*</url-pattern>
19 </filter-mapping>

  而我们要访问的资源文件就以index.jsp为例好了,那么我们用一段JSP脚本通过在控制台打印来验证过滤器工作的顺序过程:

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2
 3 <!DOCTYPE HTML>
 4 <html>
 5   <head>
 6     <title>index</title>
 7   </head>
 8
 9   <body>
10     <%
11         System.out.println("Long live SD !");
12      %>
13   </body>
14 </html>

现在启动服务器,部署该工程,通过访问index.jsp来看看控制台情况:

  

  以上简单的说明了关于Servlet技术中的Filter过滤器的使用方法和一些简单的说明,下一篇将介绍一些常用的Filter功能案例。

时间: 2024-10-13 22:44:37

Servlet的学习之Filter过滤器技术(1)的相关文章

javaweb学习总结——Filter(过滤器)学习

一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息等一些高级功能. Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter.通过F

【Servlet】Java Servet Filter 过滤器

Filter的设计思想Filter是一种AOP的设计思想 : 面向切面 下面这是一个使用filter的登录案例:我们通过一张图片理解理解filer面向切面下面是项目的结构: 下面是jsp文件: <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W

AngularJS学习之filter过滤器的用法

系统的学习angularjs,发现angularjs的有些思想根php的模块smarty很像,例如数据绑定,filter.如果对smarty比较熟悉的话,学习angularjs会比较容易一点.这篇简单说一下angularjs的filter功能,angularjs的filter功能可分为二种,一种是内置的过滤器,一种是自定义的. 一,内置的过滤器 1,uppercase,lowercase大小转换 {{ "lower cap string" | uppercase }}   //结果:L

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

首先说明一点,这个过滤器拦截其实是不靠谱的,比如说我的一篇文章是介绍sql注入的,或者评论的内容是有关sql的,那会过滤掉:且如果每个页面都经过这个过滤器,那么效率也是非常低的. 如果是要SQL注入拦截,可以在数据访问上层的业务层用方法的形式进行手动过滤还靠谱些. 或者使用SQL的参数形式进行,这个绝对是百分百搞得定. 关于SQL注入解释,参考:http://www.cnblogs.com/EasonJim/p/6223216.html 关于filter过滤器使用教程,参考:http://www

Servlet组件之一——Filter过滤器

1 学习目标 1. 能够说出过滤器的生命周期 2. 能够写出过滤器的映射路径 3. 能够说出过滤器的四种过滤类型 4. 能够利用FilterConfig获取过滤器的配置参数 5. 能够说出什么是过滤器链 6. 能够说出过滤器链的执行顺序2 过滤器的入门 Java Web的三大组件( 1)都需要交给web服务器运行  2)在web.xml文件中配置  ) 1. Servlet:  javax.servlet.Servlet 通过HTTP协议接收客户端的请求,并且做出响应的一个Java应用程序. 2

Servlet JSP 二重修炼:Filter过滤器

原网站:http://www.cnblogs.com/Alandre/p/4090491.html 摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢! 真正的朋友就是,当你蒙蔽了所有人的眼睛,也能看穿你真实的样子和心底的痛楚. 前言 好久没写博客了.哈哈~宝刀未老呀,操起笔来准备11.11华华丽丽的来一篇.都说温故知新,这句话绝对正确.按着人的记忆曲线,温故是巩固记忆力的好办法.就像我还是经常翻翻自己写的博客.回头来看看

Servlet Filter 过滤器

Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源: 例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能. 例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息等一些高级功能. Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter. 通过Filter技术,

Filter(过滤器)学习

Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp,Servlet,静态图片文件或静态html文件等进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息等一些高级功能. Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter.通过Filter技

Servlet Filter过滤器

Servlet FilterJavaEE Servlet规范中描述到的三种技术,Servlet Filter ListenerServlet技术是生成动态web资源Filter技术对服务器web资源进行拦截(权限控制)Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感