一、拦截器与过滤器主要区别
-
Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
-
Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。
-
Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
二、过滤器
过滤器是 JavaEE 的标准,依赖于 Servlet 容器,使用的时候是配置在 web.xml 文件中的,可以配置多个,执行的顺序是根据配置顺序从上到下。常用来配置请求编码以及过滤一些非法参数,垃圾信息或者是网站登录验证码。
- spring下的过滤器配置
<!-- filter -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- filter end -->
public class CaptchaFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String servletPath = request.getServletPath();
//获取验证码
if(servletPath.matches("/captcha.jpg")) {
response.setContentType("image/jpeg");
//禁止图像缓存。
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
//参数:宽、高、字符数、干扰量
CaptchaProductor vCode = new CaptchaProductor(70,30,4,75);
//根据token保存验证码内容
CaptchaBean bean = new CaptchaBean();
bean.setCaptcha(vCode.getCode());
bean.setCreateTime(new Date());
HttpSessionUtils.setSessionValue(request, "sessionCaptcha", bean);
vCode.write(response.getOutputStream());
return;
}
}
}
- Spring boot中配置
@Configuration
public class FilterConfig{
@Bean
public FilterRegistrationBean userFilternBean() {
CaptchaFilter captchaFilter = new CaptchaFilter();
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setName("captchaFilter"); // 过滤器名称
registrationBean.setFilter(captchaFilter); // 注入过滤器
registrationBean.setOrder(1); //过滤器顺序
registrationBean.setUrlPatterns(Arrays.asList("/*")); //拦截规则
return registrationBean;
}
}
@WebFilter注解也可以配置, 需要注意一点的是@WebFilter这个注解是Servlet3.0的规范,并不是Spring boot提供的。除了这个注解以外,我们还需在配置类中加另外一个注解:@ServletComponetScan,指定扫描的包。
三、拦截器
拦截器 Interceptor 不依赖 Servlet 容器,依赖 Spring 等 Web 框架,在 SpringMVC 框架中是配置在SpringMVC 的配置文件中,在 SpringBoot 项目中也可以采用注解的形式实现。拦截器是 AOP 的一种应用,底层采用 Java 的反射机制来实现的。与过滤器一个很大的区别是在拦截器中可以注入 Spring 的 Bean,能够获取到各种需要的 Service 来处理业务逻辑,而过滤器则不行。
- spring下配置
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器,顺序执行 -->
<bean class="com.test.admin.interceptor.AuthInterceptor"/>
</mvc:interceptors>
public class AuthInterceptor extends HandlerInterceptorAdapter {
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//todo
super.postHandle(request, response, handler, modelAndView);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//todo
return super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
- springboot 配置
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors() {
registry.addInterceptor(new AuthInterceptor())
.excludePathPatterns("/goodlist")
.addPathPatterns("/api/index");
}
}
四、执行顺序
过滤器的执行顺序首先跟在 web.xml 中配置的顺序有关,先配置的先执行,但是并不是说是等上一个过滤器执行结束了再执行下一个,它们之间是通过链来执行的,具体的过滤器和拦截器的执行过程我画了个图,可以看下。