1.实现Filter接口,添加@Component成为bean
java
@Component
public class MyFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(MyFilter.class);
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("1.实现Filter接口,添加@Component成为bean");
HttpServletRequest request = (HttpServletRequest) servletRequest;
String uri = request.getRequestURI();
if (uri.startsWith("/user/")) {
log.info("execute plan A");
} else if (uri.startsWith("/goods/")) {
log.info("execute plan B");
} else {
log.info("execute plan C");
}
filterChain.doFilter(servletRequest, servletResponse);
}
}
这里的 Filter 的全路径是:jakarta.servlet.Filter。
这种创建过滤器的方式默认会拦截所有接口,需要在 doFilter 方法中手动添加处理逻辑。
因为这里的过滤器是一个 bean,可以用 @Order 注解或者实现 Ordered 接口设置优先级。
Ordered 接口 > @Order 注解。
java
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
}
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
default void destroy() {
}
}
Filter 里面有三个方法,init 和 destroy 是默认方法,可以不重写。
如果需要在这个过滤器的生命周期做事情的话再重写。
2.实现Filter接口,通过FilterRegistrationBean注册成为bean
依旧让一个类实现 Filter 接口,但是不需要添加 @Component 注解。
java
public class MyFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(MyFilter.class);
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("2.实现Filter接口,通过FilterRegistrationBean注册成为bean");
log.info("do something");
filterChain.doFilter(servletRequest, servletResponse);
}
}
java
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistrationBean() {
FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new MyFilter());
bean.setOrder(1);
bean.addUrlPatterns("/*");
return bean;
}
}
在配置类中返回 FilterRegistrationBean 对象作为 bean。
在配置类中可以设置拦截规则、优先级。
但是有个问题,这里的 MyFilter 是我们自己手动创建的,new MyFilter() 嘛,所以这个对象不会被 Spring 管理,在 MyFilter 中无法自动注入其他 bean,会抛 NullPointerException。
如果需要在 MyFilter 中注入 bean,就要让 MyFilter 被 Spring 管理,也就是给 MyFilter 添加 @Component 注解。
java
@Configuration
public class FilterConfig {
@Autowired
private MyFilter myFilter;
@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistrationBean() {
FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(myFilter);
bean.setOrder(1);
bean.addUrlPatterns("/*");
return bean;
}
}
3.实现Filter接口,添加@WebFilter,启动类添加@ServletComponentScan
java
@WebFilter(urlPatterns = "/*", filterName = "myFilter")
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("3.实现Filter接口,添加@WebFilter,启动类添加@ServletComponentScan");
log.info("do something");
filterChain.doFilter(servletRequest, servletResponse);
}
}
MyFilter 要实现 Filter 接口,然后添加 @WebFilter 注解。
java
@SpringBootApplication
@ServletComponentScan
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
启动类要添加 @ServletComponentScan 注解,否则 MyFilter 不会生效。
第三种方式比较特殊:
- MyFilter 中可以注入 bean。
- 但是无法通过 @Order 注解和 Ordered 接口指定优先级,而是按照类名排序,类名就是字符串嘛,所以是根据字符串排序。(不是 filterName,是类名)
4.继承OncePerRequestFilter,添加@Component成为bean
java
@Component
public class MyFilter extends OncePerRequestFilter {
private static final Logger log = LoggerFactory.getLogger(MyFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
log.info("4.继承OncePerRequestFilter,添加@Component成为bean");
filterChain.doFilter(request, response);
}
}
OncePerRequestFilter 是 Spring 提供的过滤器,保证一次请求只执行一次。
跟第一种方式一样,可以注入 bean,可以设置优先级。
也可以像第二种方式一样,在配置类中注册到 FilterRegistrationBean 中。
java
@Configuration
public class FilterConfig {
@Autowired
private MyFilter myFilter;
@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistrationBean() {
FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(myFilter);
bean.setOrder(1);
bean.addUrlPatterns("/api/*");
return bean;
}
}