Java三大器(Filter/listener/(Interceptor))之过滤器(Filter)
Interceptor:是在面向切面编程的,就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法,是基于JAVA的反射机制。比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
servlet、filter、listener是配置到web.xml中(web.xml 的加载顺序是:context-param -> listener -> filter -> servlet ),interceptor不配置到web.xml中,struts的拦截器配置到struts.xml中。spring的拦截器配置到spring.xml中。
Filter,过滤器,用于在servlet之外对request 和response 进行修改。Filter 有一个 FilterChain 的概念,一个FilterChain 包括多个 Filter。客户端请求 request在抵达servlet 之前会经过 FilterChain 里面所有的 Filter,服务器响应 response 从servlet 抵达客户端浏览器之前也会经过 FilterChain 里面所有的 Filter 。
Filter简介
Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
Filter功能
在HttpServletRequest到达 Servlet 之前,拦截客户的HttpServletRequest 。根据需要检查HttpServletRequest,也可以修改HttpServletRequest 头和数据。
在HttpServletResponse到达客户端之前,拦截HttpServletResponse 。根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。
Filter 的实现
1、实现自定义的 Filter 需要满足一下条件:
1)实现 javax.servlet.Filter 接口,实现其 init、doFilter、destroy 三个方法。
2)实现在web.xml中的配置。
2、javax.servlet.Filter 接口
1) Filter 接口有三个方法:这三个方法反应了 Filter 的生命周期。
①、init:只会在 web 程序加载的时候调用,即启动如tomcat等服务器时调用。一般负责加载配置的参数。
②、destroy :web程序卸载的时候调用。一般负责关闭某些容器等。
③、doFilter:每次客户端请求都会调用一次。Filter 的所有工作基本都集中在该方法中进行。
配置 Filter:每个过滤器需要配置在web.xml中才能生效,一个Filter需要配置<filter> 和 <filter-mapping>标签。
1)<filter> :配置 Filter 名称,实现类以及初始化参数。可以同时配置多个初始化参数。
2)<filter-mapping> :配置什么规则下使用这个Filter 。
①、<url-pattern> :配置url的规则,可以配置多个,也可以使用通配符(*)。例如 /jsp/* 适用于本ContextPath下以“/jsp/ ”开头的所有servlet路径, *.do 适用于所有以“ .do”结尾的servlet路径。
②、<dispatcher> :配置到达servlet的方式,可以同时配置多个。有四种取值:REQUEST、FORWARD、ERROR、INCLUDE。如果没有配置,则默认为REQUEST。它们的区别是:
# REQUEST :表示仅当直接请求servlet时才生效。
# FORWARD :表示仅当某servlet通过forward转发到该servlet时才生效。
# INCLUDE :Jsp中可以通过<jsp:include/>请求某servlet, 只有这种情况才有效。
# ERROR :Jsp中可以通过<%@page errorPage="error.jsp" %>指定错误处理页面,仅在这种情况下才生效。
③、<url-pattern>和<dispatcher> 是且的关系,只有满足<url-pattern>的条件,且满足<dispatcher>的条件,该Filter 才能生效。
<!-- 过滤器配置 -->
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>servlet.filter.MyFilter</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>Sam-Sho</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/jsp/*</url-pattern>
<url-pattern>*.do</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
3)总结:一个Web程序可以配置多个Filter ,访问有先后顺序,<filter-mapping> 配置在前面的Filter 执行要早于配置在后面的Filter 。
常用 Filter
字符编码的 Filter
防盗链 Filter --> 防盗链需要使用到请求头 Referer
权限校验 Filter
文件上传 Filter
GZIP 压缩 Filter
//获取浏览器支持的压缩格式
String acceptEncoding = request.getHeader("Accept-Encoding");
System.out.println("Accept-Encoding: " + acceptEncoding);
if (acceptEncoding != null && acceptEncoding.toLowerCase().indexOf("gzip") != -1) {
// 如果客户浏览器支持 GZIP 格式, 则使用 GZIP 压缩数据
GZipResponseWrapper gzipResponse = new GZipResponseWrapper(response);
chain.doFilter(request, gzipResponse);
// 输出压缩数据
gzipResponse.getOutputStream();
gzipResponse.finishResponse();
} else {
// 否则, 不压缩
chain.doFilter(request, response);
}