过滤器(Filter)与拦截器(Interceptor )区别
1.过滤器(Filter)
Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是设置字符集、控制权限、控制转向、做一些业务逻辑判断等。其工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应(Request、Response)统一设置编码,简化操作;同时还可进行逻辑判断,如用户是否已经登陆、有没有权限访问该页面等等工作。它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。
Filter可以认为是Servlet的一种“加强版”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。Filter也可以对用户请求生成响应,这一点与Servlet相同,但实际上很少会使用Filter向用户请求生成响应。使用Filter完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
2.Filter的简单实现
字面意思:过滤器就是过滤的作用,在web开发中过滤一些我们指定的url
那么它能帮我们过滤什么呢?
那功能可就多了:
比如过拦截掉我们不需要的接口请求
修改请求(request)和响应(response)内容
完成CORS跨域请求等等
demo1:
<filter>
<description>字符集过滤器</description>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<description>字符集编码</description>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
demo2
现在我们来实现一个简单的过滤器:
可以新建一个filter包,随着项目的扩大过滤器会越来越多
在这里我新建了一个TestFilter类,实现Filter接口
@Component
@WebFilter(urlPatterns = "/Blogs",filterName = "blosTest")
public class TestFilter implements Filter{}
我们一步步来
[email protected]就是把这个类注入到IOC容器中
[email protected](urlPatterns = “/Blogs”,filterName = “blosTest”)说明这是一个web过滤器,它拦截的url为/Blogs,过滤器名字为blogsTest
下面贴出实现接口之后的三个重构方法:
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request= (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
System.out.printf("过滤器实现");
filterChain.doFilter(request,response);
}
@Override
public void destroy() {
}
初始化(init)和摧毁(destroy)方法一般不会用到,具体使用看下源码便知
doFilter()是过滤器的核心
注意:在实现接口方法之后,我们要转换request和response类型至HttpServlet,否则接下去的操作可能会报错。
如果过滤通过,执行filterChain.doFilter(request,response);
说明这个url已经经过了我们的Filter
可以看到,只需要一个类我们就实现了一个简单的过滤器
当然可以不用注解的方式,配置启动类
//过滤器
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
List<String> urlPatterns = new ArrayList<String>();
TestFilter testFilter = new TestFilter(); //new过滤器
urlPatterns.add("/Blogs"); //指定需要过滤的url
filterRegistrationBean.setFilter(testFilter); //set
filterRegistrationBean.setUrlPatterns(urlPatterns); //set
return filterRegistrationBean;
}
3.拦截器(Interceptor)
拦截器是在面向切面编程中应用的,就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法。是基于JAVA的反射机制。是普通的java类,在本地就可运行
拦截是AOP的一种实现策略
拦截器将Action共用的行为独立出来,在Action执行前后执行。这也就是我们所说的AOP,它是分散关注的编程方法,它将通用需求功能从不相关类之中分离出来;同时,能够共享一个行为,一旦行为发生变化,不必修改很多类,只要修改这个行为就可以。
当你提交对Action(默认是.action结尾的url)的请求时,ServletDispatcher会根据你的请求,去调度并执行相应的Action。在Action执行之前,调用被Interceptor截取,Interceptor在Action执行前后执行。
SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式,第一种方式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口,或者是这个类继承实现了HandlerInterceptor 接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter ;第二种方式是实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类。
4.拦截器(Interceptor)使用
interceptor 的执行顺序大致为:
1.请求到达 DispatcherServlet
2.DispatcherServlet 发送至 Interceptor ,执行 preHandle
3.请求达到 Controller
4.请求结束后,postHandle 执行
Spring 中主要通过 HandlerInterceptor 接口来实现请求的拦截,实现 HandlerInterceptor 接口需要实现下面三个方法:
- preHandle() – 在handler执行之前,返回 boolean 值,true 表示继续执行,false 为停止执行并返回。
- postHandle() – 在handler执行之后, 可以在返回之前对返回的结果进行修改
- afterCompletion() – 在请求完全结束后调用,可以用来统计请求耗时等等
我们同样可以新建一个interceptor包
在里面新建一个名为MyInterceptor的类
public class MyInterceptor implements HandlerInterceptor {}
这个类实现了HandleInterceptor接口
直接贴类代码,我会在代码中注释功能
public class MyInterceptor implements HandlerInterceptor {
//在请求处理之前进行调用(Controller方法调用之前
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.printf("preHandle被调用");
return true; //如果false,停止流程,api被拦截
}
//请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle被调用");
}
//在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion被调用");
}
}
它依次实现了三个方法
相比过滤器,拦截器还需要在springmvc中注入
所以我们打开启动类,写入以下代码
public class WarApplication {
public static void main(String[] args) {
SpringApplication.run(WarApplication.class, args);
}
//mvc控制器
//@Configuration
static class WebMvcConfigurer extends WebMvcConfigurerAdapter{
//增加拦截器
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new MyInterceptor()) //指定拦截器类
.addPathPatterns("/Handles"); //指定该类拦截的url
}
}
}
4.区别:
过滤器和拦截器非常相似,但是它们有很大的区别
- Filter 接口定义在 javax.servlet 包中 接口 HandlerInterceptor 定义在org.springframework.web.servlet 包中
- Filter 是在 Servlet 规范中定义的,是 Servlet 容器支持的。 而拦截器是在 Spring容器内的,是Spring框架支持的。过滤器需要在servlet容器中实现,拦截器可以适用于javaEE,javaSE等各种环境
- 过滤器可以修改request,而拦截器不能
- 拦截器可以调用IOC容器中的各种依赖,而过滤器不能
- 过滤器只能在请求的前后使用,而拦截器可以详细到每个方法
- Filter 是被 Server(like Tomcat) 调用 Interceptor 是被 Spring 调用 , 因此Filter总比Inteceptor先执行
5.拦截器(Interceptor)和过滤器(Filter)的执行顺序
过滤前-拦截前-Action处理-拦截后-过滤后
推荐阅读
-
过滤器(Filter)与拦截器(Interceptor )区别
-
拦截器与过滤器的区别
-
Angular.Js中过滤器filter与自定义过滤器filter实例详解
-
Java web Filter, Strurs2 Interceptor 和 SpringMVC Interceptor 三者之间的联系与区别
-
Struts2拦截器Interceptor的原理与配置实例详解
-
浅谈SpringMVC中Interceptor和Filter区别
-
Falsk 与 Django 过滤器的使用与区别详解
-
Falsk 与 Django 过滤器的使用与区别详解
-
Spring Boot项目实战之拦截器与过滤器
-
浅析JAVA中过滤器、监听器、拦截器的区别