过滤器Filter
web开发中,通过Filter可以对web服务器中的所有web资源进行拦截和处理,从而实现一些特殊的需求
应用场景:
- 非法访问过滤(比如:没有登录就不能访问网站上的资源)
- 将请求响应进行统一编码
- 过滤敏感词
Filter简述
JavaWeb三大组件(Servlet、Filter、Listener)之一。
Servlet API中提供了一个Filter接口,我们编写一个类实现这个接口,那么这个类就是一个过滤器。我们通过这个过滤器技术就可以实现——客户端浏览器访问目标资源时,会先经过我们的过滤器,由过滤器来判断是否放行,让其访问到目标资源,或者作出拦截和响应
编写一个过滤器Filter
1、编写一个Filter,定义类实现接口Filter,实现接口中的抽象方法,
import javax.servlet.*;
import javax.servlet.Filter;//包一定不要导错
import java.io.IOException;
public class HelloFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("=============请求到达过滤器=============");
//放行,进入下一个过滤器或者到达目标资源
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("=============响应到达过滤器=============");
}
}
2、在web.xml文件中配置访问过滤路径(和Servlet的配置有些相似)
<filter>
<filter-name>helloFilter</filter-name>
<filter-class>com.bdit.filter.HelloFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>helloFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-
Filter的url-pattern配置和Servlet相同,分为完全匹配、目录匹配、后缀名匹配
-
路径符合该url-pattern的请求都会先到到达该过滤器
使用注解的配置方式:
@WebFilter(urlPatterns = {"/*"})
public class HelloFilter implements Filter {······
urlPatterns 设置为 /* ,此时访问该web项目下的所有资源都会经过这个过滤器
Filter生命周期
- tomcat服务器启动时,就会创建过滤器对象,(对象只会创建一个,init方法也只会调用一次)
- init(FilterConfig filterConfig)
- 当有请求访问属于过滤范围的路径时,先进入过滤器,执行过滤方法(每一个请求到达过滤器,都会调用一次doFilter方法)
- doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
- tomcat服务器关闭时,过滤器对象会被销毁(只会被调用一次,会释放过滤器所占用的资源)
- destroy()
还是刚才的HelloFilter,继续重写Filter接口中的两个默认方法
@WebFilter(urlPatterns = {"/*"})
public class HelloFilter implements Filter {
//无参的构造方法
public HelloFilter(){
System.out.println("-------------过滤器被创建------------");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("-------------过滤器初始化------------");
}
@Override
public void destroy() {
System.out.println("-------------过滤器被销毁------------");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("=============请求到达过滤器=============");
//放行,进入下一个过滤器或者到达目标资源
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("=============响应到达过滤器=============");
}
}
此时启动web服务器,访问任意资源,然后停止服务器,就可以看到效果
示例:
写一个过滤器用来给请求和响应统一编码格式:
/**
* 将所有请求和响应进行编码过滤,都设置为utf-8
*/
@WebFilter(urlPatterns = {"/*"})
public class EncodeFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
filterChain.doFilter(servletRequest, servletResponse);
}
}
过滤器链FilterChain
在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链
一个FilterChain包含多个Filter
FilterChain接口中只有一个方法:
-
void doFilter(ServletRequest var1, ServletResponse var2)throws IOException, ServletException;
-
用于通知 Web 容器把请求交给 Filter链中的下一个Filter去处理,如果当前调用此方法的 Filter对象是Filter 链中的最后一个Filter,那么将把请求交给目标 Servlet 程序去处理。
FilterChain实现类对象由Tomcat引擎创建
Filter的执行顺序:
- 在web.xml文件中根据Filter注册顺序(< filter-mapping>)
- 如果使用注解,根据每一个Filter的名字字母顺序(AFilter先执行然后BFilter···)
- 如果配置文件和注解都有,会先执行配置文件中的Filter