Spring Interceptor 与 Filter 的区别

在 Web 应用程序中,FilterInterceptor都是用于处理请求和响应的重要组件。它们可以在请求处理的不同阶段进行干预,实现诸如身份验证、日志记录、数据过滤等功能。本文将详细介绍 Spring 中InterceptorFilter的实现方式,帮助您更好地理解和应用这两种技术。

一、Interceptor 和 Filter 的区别

InterceptorFilter都是 AOP(面向切面编程)的实现方式,但它们有一些区别:

  1. 拦截对象不同:Interceptor主要用于拦截控制器方法的执行,而Filter可以拦截所有的请求和响应。
  2. 执行顺序不同:Filter的执行顺序在Interceptor之前。
  3. 配置方式不同:Interceptor通常通过配置类或注解进行配置,而Filter需要在web.xml文件中进行配置。

二、Filter 的实现方式

在 Spring 中,创建Filter非常简单。您只需要创建一个实现了Filter接口的类,并在该类中实现相应的方法即可。Filter接口定义了三个方法:

  1. init(FilterConfig filterConfig):在Filter初始化时被调用。
  2. doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain):在请求处理过程中被调用。如果返回true,则继续执行后续的Filter;否则,中断请求处理。
  3. destroy():在Filter销毁时被调用。

三、Interceptor 的实现方式

Interceptor的实现方式, 要实现HandlerInterceptor接口,或者继承HandlerInterceptorAdapter类,然后覆写下面几个方法:

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handler):在控制器处理请求之前被调用。如果返回true则继续流程,返回false则中断。
  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView):在控制器处理请求后,视图被渲染之前被调用。
  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex):在整个请求完成后被调用,即视图被渲染后。

例如:

四、配置 Filter

在Spring框架中,添加过滤器(Filter)通常有以下几种方式:

1. 通过WebFilter注解

在Spring Boot应用程序中,你可以直接在Filter类上使用@WebFilter注解来注册一个过滤器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 你的过滤器逻辑
System.out.println("Filtering request");
// 继续执行其他过滤器或目标资源
chain.doFilter(request, response);
}
}

2. 通过FilterRegistrationBean

在Spring配置类中,你可以使用FilterRegistrationBean来注册过滤器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
@Configuration
public class FilterConfig {
@Bean
public Filter myFilter() {
return new MyFilter();
}
@Bean
public FilterRegistrationBean<MyFilter> filterRegistrationBean() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(myFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1); // 设置过滤器的执行顺序
return registrationBean;
}
}

3. 通过DelegatingFilterProxy

如果你的过滤器需要被Spring容器管理(例如,需要注入Spring管理的Bean),你可以使用DelegatingFilterProxy
首先,你需要在Spring配置中声明一个Bean:

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
@Configuration
public class WebConfig {
@Bean
public DelegatingFilterProxy myFilterProxy() {
DelegatingFilterProxy filterProxy = new DelegatingFilterProxy("myFilter");
// 可以设置其他属性,例如targetFilterLifecycle
return filterProxy;
}
}

然后,在web.xml中配置DelegatingFilterProxy

1
2
3
4
5
6
7
8
<filter>
<filter-name>myFilterProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilterProxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

或者,如果你使用的是Spring Boot,你可以在application.propertiesapplication.yml中配置:

1
2
3
# application.properties
spring.servlet.filter.registration.order=1
spring.servlet.filter.myFilterProxy.urlPatterns=/*

确保你的过滤器实现了javax.servlet.Filter接口,并覆盖了doFilter方法。上述任何一种方式都可以在Spring应用程序中添加并注册过滤器。

五、配置 Interceptor

在Spring框架中,添加拦截器(Interceptor)通常用于处理HTTP请求,例如日志记录、权限检查或请求预处理。以下是在Spring应用程序中添加拦截器的方法:

1. 实现HandlerInterceptor接口

首先,创建一个类实现HandlerInterceptor接口,并覆盖其中的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 请求处理前调用
System.out.println("Pre-handle");
return true; // 如果返回true则继续流程,返回false则中断
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 请求处理后调用
System.out.println("Post-handle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 请求结束后调用
System.out.println("After-completion");
}
}

2. 注册拦截器

接下来,你需要将拦截器注册到Spring的拦截器链中。这通常在配置类中完成。

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**") // 添加拦截路径
.excludePathPatterns("/exclude/**"); // 排除拦截路径
}
}

在上面的代码中,addPathPatterns方法用于指定拦截器应该拦截哪些路径,而excludePathPatterns方法用于排除一些路径不进行拦截。

注意事项:

  • preHandle方法返回true时,请求将继续被处理;返回false时,请求将被终止。
  • postHandle方法在Controller方法执行完毕后调用,但在视图渲染之前。
  • afterCompletion方法在整个请求完成后调用,即在视图渲染之后。
    通过上述步骤,你可以在Spring MVC应用程序中添加并注册一个拦截器。拦截器提供了一种方便的方式来处理请求前后的逻辑,而无需修改实际的业务逻辑。

六、总结

InterceptorFilter都是 Spring 框架中非常重要的组件,它们可以帮助您实现对请求和响应的拦截和处理,从而实现各种横切关注点的功能。本文详细介绍了InterceptorFilter的实现方式、区别、配置和使用,希望对您有所帮助。