一、过滤器和拦截器的区别
1、过滤器和拦截器触发机会不一样,过滤器是在请求进入容器后,但申请进入servlet之前进行预处理的。申请完结返回也是,是在servlet解决完后,返回给前端之前。
2、拦截器能够获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并治理的,spring的性能能够被拦截器应用,在拦截器里注入一个service,能够调用业务逻辑。而过滤器是JavaEE规范,只需依赖servlet api ,不须要依赖spring。
3、过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射
4、Filter是依赖于Servlet容器,属于Servlet标准的一部分,而拦截器则是独立存在的,能够在任何状况下应用。
5、Filter的执行由Servlet容器回调实现,而拦截器通常通过动静代理(反射)的形式来执行。
6、Filter的生命周期由Servlet容器治理,而拦截器则能够通过IoC容器来治理,因而能够通过注入等形式来获取其余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
@Configurationpublic 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拦截器与过滤器的利用场景及配置