spring-filter-intercepter-过滤器与拦截器
1. 过滤器 Filter
1.1 Filter 定义
Filter是sun公司中servlet2.3后增加的一个新功能,在javaEE中定义了一个接口 javax.servlet.Filter来描述过滤器。
Filter可以认为是Servlet的一种“加强版”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序.它依赖于servlet容器,在实现上,基于函数回调,它可以对几乎所有请求进行过滤。
1.2 Filter 工作原理
Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,其工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应(Request、Response)统一处理等。
使用Filter完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
- 当服务器启动,会创建Filter对象,并调用init方法,只调用一次。
- 当访问资源,路径与Filter的拦截路径匹配,会执行Filter中的doFilter方法,
- 当服务器关闭时,会调用Filter的destroy方法来进行销毁操作。
1.3 Filter 应用场景
在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符、敏感词过滤、响应信息压缩、控制权限、控制转向、做一些业务逻辑判断等。
1.4 Filter 实例
1.定义 Filter
package com.demo.filter; import org.springframework.stereotype.Component; import javax.servlet.*; import java.io.IOException; /** * @author gx */ @Component public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { System.out.println("这是 myFilter 过滤器!"); filterChain.doFilter(request, response); System.out.println("这是 myFilter 过滤器执行后!"); } @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("这是 myFilter 初始化"); } @Override public void destroy() { System.out.println("这是 myFilter 销毁"); } }
2. 配置过滤器
- 方式一:web.xml
<filter> <description>测试过滤器</description> <filter-name>TestFilter</filter-name> <filter-class>com.test.filtes.TestFilter</filter-class> </filter> <filter-mapping> <filter-name>TestFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
- 方式二:通过@WebFilter注解配置
@WebFilter(urlPatterns = "/*") @Component public class MyFilter2 implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { System.out.println("这是 myFilter2 过滤器!"); filterChain.doFilter(request, response); System.out.println("这是 myFilter2 过滤器执行后!"); } @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("这是 myFilter2 初始化"); } @Override public void destroy() { System.out.println("这是 myFilter2 销毁"); } }
启动类上可能需要这个注解:@ServletComponentScan
- 方式三:通过@Bean来配置
package com.demo.component; import com.demo.filter.MyFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author gx */ @Configuration public class MyConfig { @Autowired private MyFilter myFilter; //可以设置 order @Bean public FilterRegistrationBean registrationBean(){ FilterRegistrationBean filterRegister = new FilterRegistrationBean(myFilter); filterRegister.addUrlPatterns("/*"); //可以设置过滤器顺序 filterRegister.setOrder(0); return filterRegister; } }
2. 拦截器 Interceptor
2.1 Interceptor 定义
拦截器(Interceptor)和Servlet无关,它依赖于Web框架,在SpringMVC中就依赖于SpringMVC框架,由SpringMVC框架实现。在Struts2中同理,它是一种可以让你在Action执行之前和Result执行之后进行一些功能处理的机制。
在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用。可以用于在某个方法或者字段被访问之前,进行拦截,然后在之前或者之后加入某些统一的处理方法。就是在action的前、后、甚至抛出异常时进行处理,比如动态代理就是拦截器的简单实现。
拦截器将很多service或者Controller中共有的行为提炼出来,在某些方法执行的前后执行,提炼为通用的处理方式,让被拦截的方法都能享受这一共有的功能,让代码更加简洁,同时,当共有的功能需要发生调整、变动的时候,不必修改很多的类或者方法,只要修改这个拦截器就可以了,可复用性很强。
SpringMVC的拦截器基于HandlerInterceptor接口来实现,所以只要实现HandlerInterceptor接口或者继承它的实现类。
2.2 Interceptor 工作原理
-
preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) 方法在请求处理之前被调用。如果已经是最后一个 Interceptor 的时候就会调用当前请求的 Controller 方法。
-
postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 方法在当前请求处理完成之后,所以我们可以在这个方法中对 Controller 处理之后的 ModelAndView 对象进行操作。
-
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法需要在当前对应的 Interceptor 类的 preHandle 方法返回值为 true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行。此方法主要用来进行资源清理
2.3 Interceptor 应用场景
-
日志记录:记录请求操作日志(用户ip,访问时间等)
-
权限检查:判断用户是否有权限访问资源,如校验token 日志记录
-
性能监控:记录请求->响应时间,preHandle:记录开始时间,afterCompletion:记录结束时间,开始时间相减去结束时间
-
登录验证:判断用户是否登录
-
sign校验,封禁校验等
-
处理cookie,主题,国际化,本地化等
-
filter可以实现的功能intercepter基本上都能实现
2.4 Interceptor 实例
1. 定义拦截器
package com.demo.intercepter; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyIntercepter implements HandlerInterceptor { //进入 handler 之前:权限认证等 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("myIntercepter:preHandel 方法!"); return true; } //进入 handler 之后,返回 modelAndView 之前 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("myIntercepter:postHandle 方法!"); } //执行完 handler 之后 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("myIntercepter:afterCompletion 方法!"); } }
Object handler
这个 handler 指拦截器拦截的内容,比如方法(HanderMethod)
2. 配置拦截器
- 方式一:web.xml
<mvc:interceptors> <!-- 如果直接配置bean,代表对所有请求都拦截 --> <bean name="myIntercepter" class="com.demo.intercepter.MyIntercepter" /> <mvc:interceptor> <!-- /**:拦截所有,/*拦截一层目录结构请求 --> <mvc:mapping path="/**"/> <!-- 不拦截的请求 --> <mvc:exclude-mapping path="/testRequestEntity"/> <!-- 自定义的拦截器引用 --> <ref bean="myIntercepter"></ref> </mvc:interceptor> <mvc:interceptors/>
- 方式二:WebConfig将拦截器注册添加到拦截器链
package com.demo.component; import com.demo.intercepter.MyIntercepter; import com.demo.intercepter.MyIntercepter1; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyIntercepter()) .addPathPatterns("/**") .order(1); } }
spring 环境下这么玩
3. Filter 和 Interceptor 执行顺序
4. Filter 和 Interceptor 区别
过滤器(Filter)和拦截器(Interceptor)区别 | |||
过滤器(Filter) | 拦截器(Interceptor) | 总结 | |
定义位置 | Filter定义在java.servlet包下 | 接口HandlerInterceptor定义在org.springframework.web.servlet包下 | |
配置位置 | 配置在web.xml中 | 配置在springmvc.xml中 | |
作用位置 | Filter在只在 Servlet 前后起作用,Filter 通常不考虑servlet 的实现 | 拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。允许用户介入(hook into)请求的生命周期 | 在Spring构架的程序中,要优先使用拦截器。几乎所有 Filter 能够做的事情, interceptor 都能够轻松的实现 |
使用范围 | Filter 是 Servlet 规范规定的 | 而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。 | |
遵循规范 | Filter 是遵循 Servlet 规范 | 而拦截器是在 Spring容器内的,是Spring框架支持的。 | |
与spring关系 | Filter 不能够使用 Spring 容器资源 | Interceptor 是被 Spring 调用 | Spring 中使用 interceptor 更容易 |
调用方 | Filter 是被 Server(like Tomcat) 调用 | Interceptor 是被 Spring 调用 | 因此 Filter 总是优先于 Interceptor 执行 |
实现方式 | Filter 基于函数回掉 | Interceptor基于java反射 |
demo 示例
https://gitee.com/zangsan/apz/tree/master/demo-boot/demo-filter/src/main/java/com/demo
参考文献
本文作者:Hi.PrimaryC
本文链接:https://www.cnblogs.com/cnff/p/18023433
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2021-02-20 Git基本操作