1.过滤器是什么?
过滤器是处于客户端与服务器资源文件之间的一道过滤网,在访问资源文件之前,通过一系列的过滤器对请求进行修改、判断等,把不符合规则的请求在中途拦截或修改。也可以对响应进行过滤,拦截或修改响应。
- 过滤器依赖Servlet容器,属于Servlet规范的一部分。
- 在实现上基于Servlet容器的函数回调,可以对几乎所有请求进行过滤。
- Filter的生命周期由Servlet容器管理。
2.过滤器执行流程
过滤器是随着web应用的启动而启动的,只会初始化一次,之后便可以拦截过滤相关的请求或响应,当web应用停止或重新部署的时候才会被销毁。
下面我们通过代码示例来学习如何使用它。
3.应用场景
- 1.判断用户是否已经登陆
- 2.统一设置字符编码
- 3.判断有没有权限访问页面
- 4.判断敏感字符过滤
- 5.等等…
4.配置方法:
4.1 创建Filter
输入过滤器名称,创建位置。
4.2 代码分析
package com.cy.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(filterName = "TestFilter")
public class TestFilter implements Filter {
/*销毁时调用*/
public void destroy() {
}
/**
*过滤方法
* 对request和response进行处理,
* 然后交给下一个过滤器或Servlet处理
*/
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//交给下一个过滤器或servlet处理
chain.doFilter(req, resp);
}
/**
* 初始化方法
* @param config 接收一个FilterConfig类型的参数
* 该参数是对Filter的一些配置
*/
public void init(FilterConfig config) throws ServletException {
}
}
在代码中,我们可以发现在Filter
接口中定义了一个doFilter
方法,这个方法正是过滤器执行过滤动作的方法,每个过滤器都有权访问filterConfig
对象,并从中获取初始化参数;当我们编写好Filter
的实现类,并在web应用程序的部署描述符「web.xml」中配置好需要拦截过滤的web资源后,web服务器就会在调用web资源的service方法之前先调用这个doFilter方法 。
此时你就可以针对需要拦截过滤的web资源(Request、Response)进行业务逻辑判断和处理,从而简化操作。
4.3 常用配置项
urlPatterns
配置要拦截的资源
1.以指定资源匹配。例如"/index.jsp"
2.以目录匹配。例如"/servlet/*"
3.以后缀名匹配,例如"*.jsp"
4.通配符,拦截所有web资源。"/*"
initParams
配置初始化参数,跟Servlet配置一样
例如:
initParams = {
@WebInitParam(name = "key",value = "value")
}
dispatcherTypes
配置拦截的类型,可配置多个。默认为DispatcherType.REQUEST**
例如:
dispatcherTypes = {DispatcherType.ASYNC,DispatcherType.ERROR}
其中DispatcherType是个枚举类型,有下面几个值
FORWARD,//转发的
INCLUDE,//包含在页面的
REQUEST,//请求的
ASYNC,//异步的
ERROR;//出错的
4.4 修改代码
1.编写java类,实现Filter接口及其方法
package com.cy.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
@WebFilter(filterName = "CharsetFilter",urlPatterns = "/*",/*通配符(*)表示对所有的web资源进行拦截*/
initParams = {@WebInitParam(name = "charset", value = "utf-8")})/*这里可以放一些初始化的参数*/
public class TestFilter implements Filter {
private String url;
/**
* 在销毁Filter时自动调用。
*/
@Override
public void destroy() {
System.out.println("TestFilter被销毁!");
}
/**
*过滤方法
* 对request和response进行处理,
* 然后交给下一个过滤器或Servlet处理
*/
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
long start = System.currentTimeMillis();
System.out.println(start + " Filter doFilter before...");
chain.doFilter(req, resp);
long end = System.currentTimeMillis();
System.out.println(end + "Filter doFilter after...");
//交给下一个过滤器或servlet处理
chain.doFilter(req, resp);
}
/**
* 初始化方法
* @param config 接收一个FilterConfig类型的参数
* 该参数是对Filter的一些配置
*/
public void init(FilterConfig config) throws ServletException {
/*初始化方法 接收一个FilterConfig类型的参数 该参数是对Filter的一些配置*/
this.url = config.getInitParameter("URL");
System.out.println("Filter init...");
}
}
这样一个简单的字符集编码处理的过滤器就完成了。
4.6 理解
4.6.1 思考
拦截器与过滤器是否相同?(过滤器和拦截器不同,struts中拦截器是核心)
4.6.2 区分差异
-
过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。(理解:就是一堆字母中取一个B)
-
拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。(理解:就是一堆字母中,干预他,通过验证的少点,顺便干点别的东西)。
拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
过滤器:是在javaweb中,你传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符。
两者的本质区别:从灵活性上说拦截器功能更强大些,拦截器是AOP的一种实现,底层通过动态代理模式完成,Filter能做的事情,他都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类),太细的话,还是建议用interceptor。不过还是根据不同情况选择合适的。
4.6.3 使用场景
springMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。
5、OpenSessionInView:如hibernate,在进入处理器打开Session,在完成后关闭Session。