过滤器链(FilterChain)
概念解释
过滤器链(FilterChain):在Java Web中,过滤器链是由多个过滤器组成的链式结构。当请求到达服务器时,会按照过滤器的配置顺序依次经过每个过滤器,每个过滤器可以对请求进行处理,然后决定是否将请求传递给下一个过滤器或目标资源。过滤器链的最后一个过滤器会将请求传递给目标Servlet或JSP。
过滤器链的作用:过滤器链允许我们在请求到达目标资源之前或响应返回客户端之前,对请求和响应进行一系列的预处理和后处理。通过过滤器链,我们可以实现复杂的请求处理逻辑,如权限控制、日志记录、编码转换等。
过滤器链的工作原理
- 请求到达:当客户端发送请求到服务器时,请求首先会被第一个过滤器拦截。
- 过滤器处理:第一个过滤器对请求进行处理,然后决定是否将请求传递给下一个过滤器。
- 传递请求:如果过滤器决定传递请求,它会调用
FilterChain
的doFilter
方法,将请求传递给下一个过滤器。 - 重复步骤:请求会依次经过过滤器链中的每个过滤器,每个过滤器都可以对请求进行处理。
- 到达目标资源:当请求经过所有过滤器后,最终会到达目标Servlet或JSP。
- 响应返回:目标资源处理请求并生成响应,响应会按照相反的顺序依次经过每个过滤器,每个过滤器可以对响应进行处理。
- 响应返回客户端:最终,响应会返回给客户端。
过滤器链的配置
在Spring Boot中,过滤器链的配置可以通过多种方式实现,包括使用@WebFilter
注解、FilterRegistrationBean
等。
使用@WebFilter
注解
import javax.servlet.annotation.WebFilter;
@WebFilter(urlPatterns = "/*")
public class FirstFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("FirstFilter 拦截到了请求...放行前逻辑");
chain.doFilter(request, response);
System.out.println("FirstFilter 拦截到了请求...放行后逻辑");
}
}
@WebFilter(urlPatterns = "/*")
public class SecondFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("SecondFilter 拦截到了请求...放行前逻辑");
chain.doFilter(request, response);
System.out.println("SecondFilter 拦截到了请求...放行后逻辑");
}
}
在启动类上添加@ServletComponentScan
注解,开启Servlet组件支持。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan
@SpringBootApplication
public class TliasWebManagementApplication {
public static void main(String[] args) {
SpringApplication.run(TliasWebManagementApplication.class, args);
}
}
使用FilterRegistrationBean
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<FirstFilter> firstFilterRegistrationBean() {
FilterRegistrationBean<FirstFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new FirstFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1); // 设置过滤器顺序
return registrationBean;
}
@Bean
public FilterRegistrationBean<SecondFilter> secondFilterRegistrationBean() {
FilterRegistrationBean<SecondFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new SecondFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(2); // 设置过滤器顺序
return registrationBean;
}
}
过滤器链的执行顺序
过滤器链中的过滤器执行顺序由过滤器的配置顺序决定。在Spring Boot中,可以通过@WebFilter
注解的order
属性或FilterRegistrationBean
的setOrder
方法来设置过滤器的执行顺序。
示例:使用@WebFilter
注解的order
属性
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
@WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name = "order", value = "1")})
public class FirstFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("FirstFilter 拦截到了请求...放行前逻辑");
chain.doFilter(request, response);
System.out.println("FirstFilter 拦截到了请求...放行后逻辑");
}
}
@WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name = "order", value = "2")})
public class SecondFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("SecondFilter 拦截到了请求...放行前逻辑");
chain.doFilter(request, response);
System.out.println("SecondFilter 拦截到了请求...放行后逻辑");
}
}
示例:使用FilterRegistrationBean
的setOrder
方法
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<FirstFilter> firstFilterRegistrationBean() {
FilterRegistrationBean<FirstFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new FirstFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1); // 设置过滤器顺序
return registrationBean;
}
@Bean
public FilterRegistrationBean<SecondFilter> secondFilterRegistrationBean() {
FilterRegistrationBean<SecondFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new SecondFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(2); // 设置过滤器顺序
return registrationBean;
}
}
总结
过滤器链是Java Web中一个强大的机制,允许我们在请求到达目标资源之前或响应返回客户端之前,对请求和响应进行一系列的预处理和后处理。通过合理配置过滤器链,我们可以实现复杂的请求处理逻辑,如权限控制、日志记录、编码转换等。在Spring Boot中,我们可以使用@WebFilter
注解或FilterRegistrationBean
来配置和管理过滤器链。