Java过滤器(Filter)
1.什么是过滤器
Servlet中的过滤器Filter实现了javax.servlet.Filter接口的服务器端程序,主要用途是过滤字符编码,做一些业务逻辑判断如是否有权限访问页面等
拦截请求,过滤响应
2.运行原理
当客户端向服务器端发送一个请求时,如果有对应的过滤器进行拦截,过滤器可以改变请求的内容、或者重新设置请求协议的相关信息等,然后再将请求发送给服务器端的Servlet进行处理。当Servlet对客户端做出响应时,过滤器同样可以进行拦截,将响应内容进行修改或者重新设置后,再响应给客户端浏览器。在上述过程中,客户端与服务器端并不需要知道过滤器的存在。
在一个Web应用程序中,可以部署多个过滤器进行拦截,这些过滤器组成了一个过滤器链。过滤器链中的每个过滤器负责特定的操作和任务,客户端的请求在这些过滤器之间传递,直到服务器端的Servlet。具体执行流程如下
应用场景
自动登录
统一设置编码格式
访问权限控制
敏感字符过滤等
@Order(1)//@Order里边的数字越小代表越先被该Filter过滤
@WebFilter(filterName = "firstFilter",urlPatterns = "/*")//@WebFilter代表这是个Filter类并把这个类注入到容器中
@Component
public class MyFilterTest implements Filter {
//初始化方法
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("MyFilterTest 初始化 init(FilterConfig filterConfig)");
//获取Filter的名称 filter-name 的内容(web-xml 中配置的名称)
String filterName = filterConfig.getFilterName();
System.out.println("filter-name:"+filterConfig.getFilterName());
System.out.println("初始化参数url的值是:"+filterConfig.getInitParameter("url"));
//获取ServletContext 对象
System.out.println(filterConfig.getServletContext());
//返回过滤器的所有初始化参数的名字的枚举集合。
Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
System.out.println(filterName);
while (initParameterNames.hasMoreElements()) {
String paramName = (String) initParameterNames.nextElement();
System.out.println(paramName);
}
}
//销毁方法
@Override
public void destroy() {
System.out.println("MyFilterTest 销毁");
}
//过滤方法 主要是对request和response进行一些处理,然后交给下一位过滤器或者servlet处理
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("MyFilterTest执行前");
chain.doFilter(request,response);//让目标资源执行,放行
System.out.println("MyFilterTest执行后");
}
}
注:@ServletComponentScan注解的含义在SpringBootApplication(启动类)上使用@ServletComponentScan注解后,Servlet、Filter(过滤器)、Listener(监听器)可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码!@WebFilter+@ServletComponentScan 注解方式支持对 Filter 匹配指定URL,但是不支持指定 Filter 的执行顺序。
使用方式 | 排序 | 指定URL |
---|---|---|
@Component @Order | 1 | 0 |
@WebFilter @ServletComponentScan | 0 | 1 |
JavaConfig | 1 | 1 |
2.Filter的生命周期
1.构造器方法
2.init 初始化方法
3.doFilter 过滤方法
- 通过控制对chain.doFilter方法的调用,来决定是否需要目标资源。比如可以在用户权限验证,判断用户是否有访问某些资源的权限,有权限放行,没权限不执行chain.doFilter方法
- 解决中文乱码的问题
- Filter不仅可以通过url-pattern来指定拦截哪些url匹配的资源。而且还可以通过servlet-name来指定拦截哪个指定的servlet(专门为某个servlet服务了,servlet-name对应Servlet的相关配置)
4.destroy 销毁方法
3.Filter的执行流程
在我们的请求到达Servle之间是可以经过多个Filter的,一般来说,建议Filter之间不要有关联,各自处理各自的逻辑即可。这样,我们也无需关心执行顺序问题。 如果一定要确保执行顺序,就要对配置进行修改了,执行顺序如下
在web.xml中,filter执行顺序跟的顺序有关,先声明的先执行 使用注解配置的话,filter的执行顺序跟名称的字母顺序有关,例如AFilter会比BFilter先执行 如果既有在web.xml中声明的Filter,也有通过注解配置的Filter,那么会优先执行web.xml中配置的Filter
@Order(1)//@Order里边的数字越小代表越先被该Filter过滤
@Order(1)//@Order里边的数字越小代表越先被该Filter过滤
@WebFilter(filterName = "firstFilter",urlPatterns = "/*")//@WebFilter代表这是个Filter类并把这个类注入到容器中
@Component
public class FirstFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("first filter 1");
System.out.println("before:" + response);
chain.doFilter(request, response);
System.out.println("after:" + response);
System.out.println("first filter 2");
}
}
@Order(2)
@WebFilter(filterName = "secondFilter",urlPatterns = "/*")
@Component
public class SecondFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("second filter 1");
System.out.println("before:" + response);
chain.doFilter(request, response);
System.out.println("after:" + response);
System.out.println("second filter 2");
}
}
控制台打印
first filter 1
before:org.apache.catalina.connector.ResponseFacade@5be0afc
second filter 1
before:org.apache.catalina.connector.ResponseFacade@5be0afc
1login
session 创建成功...
after:org.apache.catalina.connector.ResponseFacade@5be0afc
second filter 2
after:org.apache.catalina.connector.ResponseFacade@5be0afc
first filter 2
4.FilterConfig类
FilterConfig类 是Filter过滤器的配置文件类
Tomcat每次创建Filter的时候,会同时创建一个FilterConfig类,这里包含了Filter配置文件的配置信息
- 获取 Filter 的名称 filter-name 的内容
- 获取在 Filter 中 wen.xml 配置的 init-param 初始化参数
- 获取 ServletContext 对象
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean registerMyFilter(){
FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
bean.setOrder(1);
bean.setFilter(new MyFilter());
// 匹配"/hello/"下面的所有url
bean.addUrlPatterns("/hello/*");
return bean;
}
@Bean
public FilterRegistrationBean registerMyAnotherFilter(){
FilterRegistrationBean<MyAnotherFilter> bean = new FilterRegistrationBean<>();
bean.setOrder(2);
bean.setFilter(new MyAnotherFilter());
// 匹配所有url
bean.addUrlPatterns("/*");
return bean;
}
}