一、过滤器和拦截器的区别
1、过滤器和拦截器 触发机会不一样 , 过滤器是 在请 求进入容器后 ,但申请 进入 servlet 之前 进行预处理 的。申请完结返回也是,是在 servlet 解决完后,返回给前端之前。
2、拦截器 能够获取 IOC 容器中的各个 bean,而过滤器就不行,因为拦 截器是 spring 提供并治理的,spring 的性能能够被拦截器应用,在拦截器里注入一个 service,能够调用业务逻辑。而过滤器是 JavaEE 规范,只需依赖 servlet api,不须要依赖 spring。
3、过滤器的实现 基于 回调函数 。而 拦截器 (代理模式)的实现 基于反射
4、Filter是依 赖于 Servlet 容 器,属于 Servlet 标准的一部分 ,而 拦截器则是独立存 在的,能够在任何状况下应用。
5、Filte r 的执行由 Servlet 容器回调实现,而 拦截器 通常通 过动静代理(反射)的形式来执行。
6、Filter 的生命周 期由 Servlet 容器治理 ,而 拦截器则 能够通过 I oC 容器来治理,因而能够通过注入等形式来获取其余 Bean 的实例,因而应用会更不便。
过滤器和拦截器十分类似,然而它们有很大的区别
最简单明了的区别就是 ** 过滤器能够批改 request,而拦截器不能
过滤器须要在 servlet 容器中实现,拦截器能够实用于 javaEE,javaSE 等各种环境
拦截器能够调用 IOC 容器中的各种依赖,而过滤器不能
过滤器只能在申请的前后应用,而拦截器能够具体到每个办法 **
区别很多,大家能够去查下
总的来说
过滤器就是筛选出你要的货色,比方 requeset 中你要的那局部
拦截器在做平安方面用的比拟多,比方终止一些流程
网上有一张图片很不错,这里拷过去给大家看一下
过滤器(Filter):能够拿到原始的 http 申请,然而拿不到你申请的控制器和申请控制器中的办法的信息。
拦截器(Interceptor):能够拿到你申请的控制器和办法,却拿不到申请办法的参数。
切片(Aspect): 能够拿到办法的参数,然而却拿不到 http 申请和响应的对象
二、过滤器
两种形式:
1、应用 spring boot 提供的 FilterRegistrationBean 注册 Filter
2、 应用 原生 servlet 注解定义 Filter
两种形式的实质都是一样的,都是去 FilterRegistrationBean 注册自定义 Filter
形式一:(应用 spring boot 提供的 FilterRegistrationBean 注册 Filter)
①、先定义 Filter:
package com.corwien.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {@Override public void init(FilterConfig filterConfig) throws ServletException { }
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // do something 解决 request 或 response
// doFilter()办法中的 servletRequest 参数的类型是 ServletRequest,须要转换为 HttpServletRequest 类型不便调用某些办法
System.out.println("filter1"); // 调用 filter 链中的下一个 filter
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String ip = request.getRemoteAddr();
String url = request.getRequestURL().toString();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = new Date();
String date = sdf.format(d);
System.out.printf("%s %s 拜访了 %s%n", date, ip, url);
filterChain.doFilter(request, response);
}
@Override public void destroy() {}
}
②、注册自定义 Filter
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean registrationBean() {** FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new** **MyFilter());**
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
}
形式一的①②步骤能够用上面这段代码代替:
@Configuration public class FilterConfig {@Bean public **FilterRegistrationBean** registFilter() {**FilterRegistrationBean registration** **= new FilterRegistrationBean();
registration.setFilter(new** **LogCostFilter());**
registration.addUrlPatterns("/*");
registration.setName("LogCostFilter");
registration.setOrder(1); return registration;
}
}
public class LogCostFilter implements Filter {@Override public void init(FilterConfig filterConfig) throws ServletException { }
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {long start = System.currentTimeMillis();
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Execute cost="+(System.currentTimeMillis()-start));
}
@Override public void destroy() {}
形式二:(应用 原生 servlet 注解定义 Filter)
// 注入 spring 容器
@Component // 定义 filterName 和过滤的 url
@WebFilter(filterName = "my2Filter" ,urlPatterns = "/*") public class My2Filter implements Filter {@Override public void init(FilterConfig filterConfig) throws ServletException { }
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("filter2");
}
@Override public void destroy() {}
}
这里间接用 @WebFilter 就 能够进行配置,同样,可 以设置 url 匹配模式,过滤器名称 等。这里须要留神一点的是 @WebFilter 这个注解是 Servlet3.0 的标准,并不是 Spring boot 提供 的。除了这个注解以外,咱们还需在 启动类中加另外一个注解:@ServletComponetScan,指定扫描的包。
三、拦截器的配置
实现拦截器能够通过继承 HandlerInterceptorAdapter
类也能够通过实现 HandlerInterceptor
这个接口。另外,如果 preHandle
办法return true
,则持续后续解决。
首先咱们实现拦截器类:
public class LogCostInterceptor implements HandlerInterceptor {long start = System.currentTimeMillis();
@Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {start = System.currentTimeMillis(); return true;
}
@Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {System.out.println("Interceptor cost="+(System.currentTimeMillis()-start));
}
@Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {}}
咱们 还须要 实现 HandlerInterceptor 这个接口,这个接口包含三个办法,preHandle 是申请执行前 执行的,postHandler 是申请完结 执行的,但 只有 preHandle 办法返回 true 的时候才会执 行,afterCompletion 是视图渲染实现后才执行,同样须要 preHandle 返回 true,该办法通常用于清理资源等工作。除了实现下面的接口外,咱们还需对其进行配置:
@Configuration public class InterceptorConfig extends WebMvcConfigurerAdapter {@Override public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LogCostInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry);
}
}
这里咱们 继承了 WebMVCConfigurerAdapter,这里咱们 重写了 addInterceptors 这个办法 ,进行拦截器的配置, 次要配置项就两个 ,一个是 指定拦截器 ,第二个是 指定拦挡的 URL。
坑坑坑:
拦截器不失效常见问题:
1)是否有加 @Configuration
2)拦挡门路是否有问题 **
和 *
3)拦截器最初门路肯定要“/**
”,如果是目录的话则是 /*/
总结一下: 创立拦截器须要两步:
1、自定义拦截器
2、注册拦截器
四、利用场景
拦截器是在 DispatcherServlet 这个 servlet 中执行的,因而所有的申请最先进入 Filter,最初来到 Filter。其程序如下。
Filter->Interceptor.preHandle->Handler->Interceptor.postHandle->Interceptor.afterCompletion->Filter
拦截器利用场景
拦截器实质上是面向切面编程(AOP),合乎横切关注点的性能都能够放在拦截器中来实现,次要的利用场景包含:
- 登录验证,判断用户是否登录。
- 权限验证,判断用户是否有权限拜访资源,如校验 token
- 日志记录,记录申请操作日志(用户 ip,拜访工夫等),以便统计申请访问量。
- 解决 cookie、本地化、国际化、主题等。
- 性能监控,监控申请解决时长等。
- 通用行为:读取 cookie 失去用户信息并将用户对象放入申请,从而不便后续流程应用,还有如提取 Locale、Theme 信息等,只有是多个处理器都须要的即可应用拦截器实现)
过滤器利用场景
1)过滤敏感词汇(避免 sql 注入)
2)设置字符编码
3)URL 级别的权限访问控制
4)压缩响应信息
相干文章:
spring boot 过滤器、拦截器的区别与应用
springboot 下应用拦截器和过滤器
SpringBoot2.x 拦截器与过滤器的利用场景及配置