Filter接口定义在 javax.servlet
包中,是Servlet规范定义的,作用于Request/Response前后,被Servlet容器调用,Filter不能使用Spring容器资源。
自定义的过滤器需要实现 javax.servlet.Filter
,Filter接口中有三个方法:
init(FilterConfig filterConfig)
:过滤器初始化的被调用。
doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
:在 doFilter()
方法中, chain.doFilter()
前的一般是对request执行的过滤操作, chain.doFilter
后面的代码一般是对response执行的操作, chain.doFiter()
执行下一个过滤器或者业务处理器。
destory()
:过滤器销毁的时候被调用。
@Configuration public class WebConfig{ @Bean public FilterRegistrationBean xxxFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new xxxFilter()); registrationBean.setUrlPatterns(Arrays.asList("/*")); registrationBean.setOrder(1); // 过滤器的优先级 return registrationBean; } } 复制代码
@WebFilter
和 @ServletComponentScan
通过 @WebFilter
的方式定义Filter,默认使用Filter的类名设置优先级。使用 FilterRegistrationBean
可以指定优先级。Filter使用白名单过滤Url的方式,配置需要拦截的Url,如果想设置不过滤某些Url需要在 doFilter
方法中指定。
定义一个Interceptor需要实现 org.springframework.web.servlet.HandlerInterceptor
接口,Interceptor是Spring容器定义的,它可以使用Spring容器的任何资源,只要通过IoC注入到Interceptor即可,Interceptor可以深入到业务处理方法的执行前后和抛出异常的时候,而Filerter无法做到这一点,所以Interceptor相比Filter具有更大的弹性。
实现 HandlerInterceptor
或者继承 HandlerInterceptorAdapter
public interface HandlerInterceptor { default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } } 复制代码
preHandle:在业务处理器处理请求之前被调用。
postHandle:在业务处理器处理请求后并生成视图前被调用,此时有机会修改ModelAndView。
afterCompletion:业务处理处理器处理完请求后(已经渲染视图)被执行,并可以处理业务方法发生异常的场景。
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { InterceptorRegistration registration = registry.addInterceptor(new TimeInterceptor()); registration.excludePathPatterns("/user"); registration.excludePathPatterns("/*"); } } 复制代码
Interceptor既可以指定要过滤的Url也可以指定不拦截的Url,缺省情况拦截所有Url。