Filter过滤器(1)
Filter也称之为过滤器,它是Servlet技术中比较激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
其顺序图如下(Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,简单说,就是可以实现web容器对某资源的访问前截获进行相关的处理,还可以在某资源向web容器返回响应前进行截获进行处理。)

过滤器,设计执行流程:
- 用户访问服务器
- 过滤器: 对Servlet请求进行拦截
- 先进入过滤器, 过滤器处理
- 过滤器处理完后, 在放行, 此时,请求到达Servlet/JSP
- Servlet处理
- 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)的更多相关文章
- filter 过滤器(监听)
Filter 过滤器 1.简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, ...
- Java防止SQL注入2(通过filter过滤器功能进行拦截)
首先说明一点,这个过滤器拦截其实是不靠谱的,比如说我的一篇文章是介绍sql注入的,或者评论的内容是有关sql的,那会过滤掉:且如果每个页面都经过这个过滤器,那么效率也是非常低的. 如果是要SQL注入拦 ...
- Filter(过滤器)学习
一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态 ...
- javaweb学习总结(四十二)——Filter(过滤器)学习
一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态 ...
- Filter过滤器简单应用( 接口访问控制 )
一.描述 在提供安卓.IOS客户端接口时,可以在登陆接口分配Session给客户端,用于判断其他接口是否是合法访问,以避免将所有的接口都暴露在web中可以由路径直接访问.但是最近的一个项目中的移动接口 ...
- 如何配置Filter过滤器处理JSP中文乱码
参考Tomcat服务器目录webapps的examples示例 简单配置步骤:1.在项目web.xml文件添加过滤器标记<filter>和<filter-mapping>:2. ...
- Filter(过滤器)常见应用
孤傲苍狼 只为成功找方法,不为失败找借口! javaweb学习总结(四十六)——Filter(过滤器)常见应用 一.统一全站字符编码 通过配置参数charset指明使用何种字符编码,以处理Html F ...
- Servlet的学习之Filter过滤器技术(1)
本篇将讲诉Servlet中一项非常重要的技术,Filter过滤器技术.通过过滤器,可以对来自客户端的请求进行拦截,进行预处理或者对最终响应给客户端的数据进行处理后再输出. 要想使用Filter过滤器, ...
- javaWeb学习总结(10)- Filter(过滤器)学习
一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有 web资源:例如Jsp, Servlet, 静 ...
随机推荐
- Matlab 文件命名规则
Matlab 文件命名规则 1.文件名命名要用英文字符,第一个字符不能是数字和下划线. 2.文件名不要取为matlab的一个固有函数,m文件名的命名尽量不要是简单的英文单词,最好是由大小写英文.数字. ...
- 【NOIP 2012 国王游戏】 贪心+高精度
题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍 ...
- *[topcoder]LittleElephantAndIntervalsDiv1
http://community.topcoder.com/stat?c=problem_statement&pm=12822&rd=15707 第一次用C++提交,艰辛.首先想到可以 ...
- Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析
门面设计模式 门面设计模式在 Tomcat 中有多处使用,在 Request 和 Response 对象封装中.Standard Wrapper 到 ServletConfig 封装中.Applica ...
- Java JSON序列化杂谈
在C#中序列化是比较容易的,如果不用第三方的类库,那么C#提供的两个对象也够我们使用,一般的操作是定义一个不含有方法的类,这个类里面定义了要序列化的对象的属性,因为我C#用的比较多,这里直接给出泛型, ...
- input checkbox问题和li里面包含checkbox
<input type="checkbox" id="checkbox1"/> $("input#checkbox1").cli ...
- C# SerializableDictionary序列化/反序列化
说明:Dictionary对象本身不支持序列化和反序列化,需要定义一个继承自Dictionary, IXmlSerializable类的自定义类来实现该功能.感觉完全可以把这样的类封装到C#库中,很具 ...
- scp传入固件,sysupgrade xx.bin升级固件
scp传入固件,sysupgrade xx.bin升级固件
- hadoop2.2基准测试
<hadoop the definitive way>(third version)中的Benchmarking a Hadoop Cluster Test Cases的class在新的版 ...
- C#实现微信公众号群发消息(突破破解一天只能发一次的限制)
总体思路:1.首先必须要在微信公众平台上申请一个公众号. 2.然后进行模拟登陆.(由于我对http传输原理和编程不是特别懂,在模拟登陆的地方,不是特别清楚,希望有大神指教) 3.模拟登陆后会获得一个t ...