过滤器 与 拦截器
一、过滤器(Filter)
1、特点
过滤器是基于Java Servlet规范的一部分,用于在哀求 到达Servlet之前 或 响应离开Servlet之后 对哀求和响应进行处理。
- 过滤器可以对全部哀求进行处理,不仅限于特定的Servlet或Spring MVC控制器。
- 过滤器在Servlet容器层面工作,而不是Spring层面。
- 得当用于日志记载、身份验证、权限查抄等通用功能。
2、生命周期
- public interface Filter {
- // 初始化方法
- default void init(FilterConfig filterConfig) throws ServletException {
- }
- // 执行拦截方法
- void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
- // 销毁方法
- default void destroy() {
- }
- }
复制代码- # 创建【init方法】
- 1. 特点:
- 服务器启动,项目加载,创建filter对象,执行【init方法】(只执行一次)
- 2. 对比Servlet:
- 先于Servlet的init方法执行
- # 拦截【doFilter方法】
- 1. 特点:
- 用户访问被拦截的目标资源时,执行【doFilter方法】(浏览器每访问一次,就会执行一次)
- 2. 对比Servlet:
- 先于Servlet的service方法执行
- # 销毁【destroy方法】
- 1. 特点:
- 服务器关闭,项目关闭,销毁filter对象,执行【destroy方法】(只执行一次)
- 2. 对比Servlet:
- 后于Servlet的destroy方法执行
复制代码 3、实现
定义拦截器只要实现Filter接口,重写doFilter方法即可
- public class MyFilter implements Filter {
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- // 前置处理...
- System.out.println("Filter doFilter before");
- // 处理请求
- chain.doFilter(request, response);
- // 后置处理...
- System.out.println("Filter doFilter after");
- }
- }
复制代码 注册拦截器(SpringBoot示例)
- @Configuration
- public class FilterConfig {
- @Bean
- public FilterRegistrationBean<MyFilter> myFilter() {
- FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
- registrationBean.setFilter(new MyFilter());
- // 过滤路径(/*表示所有)
- registrationBean.addUrlPatterns("/*");
- // 过滤顺序(多个Filter按Order从小到大顺序执行)
- registrationBean.setOrder(1);
- return registrationBean;
- }
- }
复制代码 4、过滤器链
1)配置 order
多个 Filter 按 Order的巨细 从小到大 执行(如果没有配置Order,按 Bean声明的次序 从上到下 执行)
- @Configuration
- public class FilterConfig {
- @Bean
- public FilterRegistrationBean<MyFilter> myFilter1() {
- FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
- registrationBean.setFilter(new MyFilter1());
- registrationBean.addUrlPatterns("/*");
- registrationBean.setOrder(1);
- return registrationBean;
- }
- @Bean
- public FilterRegistrationBean<MyFilter> myFilter2() {
- FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
- registrationBean.setFilter(new MyFilter2());
- registrationBean.addUrlPatterns("/*");
- registrationBean.setOrder(2);
- return registrationBean;
- }
- @Bean
- public FilterRegistrationBean<MyFilter> myFilter3() {
- FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
- registrationBean.setFilter(new MyFilter3());
- registrationBean.addUrlPatterns("/*");
- registrationBean.setOrder(3);
- return registrationBean;
- }
- }
复制代码 2)执行次序
- Filter1 doFilter before
- Filter2 doFilter before
- Filter3 doFilter before
- Servlet service
- // 如果发生异常,就不会执行 doFilter after 了
- Filter3 doFilter after
- Filter2 doFilter after
- Filter1 doFilter after
复制代码 二、拦截器 Inteceptor
1、特点
拦截器是Spring MVC提供的功能,用于在哀求到达控制器之前和响应离开控制器之后进行处理。
- 拦截器主要用于Spring MVC层面,处理的是控制器层的哀求和响应。
- 得当用于权限查抄、日志记载、哀求计时等与业务逻辑密切相关的操作。
2、生命周期
- public interface HandlerInterceptor {
- // Controller执行之前调用
- default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- return true;
- }
- // Controller执行之后调用(发生异常 或 preHandle=false 不会调用)
- default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
- }
- // Controller执行之后调用(发生异常也会调用,preHandle=false不会调用)
- default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
- }
- }
复制代码 3、实现
自定义拦截器只要实现HandlerInterceptor接口,按需重写指定即可。
- public class MyInterceptor implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("Pre Handle method is Called");
- return true; // 继续处理请求
- }
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("Post Handle method is Called");
- }
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("Request and Response is completed");
- }
- }
复制代码 注册拦截器
- 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 MyInterceptor())
- // 配置拦截路径
- .addPathPatterns("/**")
- // 配置放过路径
- .excludePathPatterns();
- }
- }
复制代码 4、拦截器链
1)配置 order
多个 Interceptor 按 Order的巨细 从小到大 执行(如果没有配置Order,按 添加的次序 从上到下 执行)
- @Configuration
- public class MyAdapter implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").order(1);
- registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**").order(2);
- registry.addInterceptor(new MyInterceptor3()).addPathPatterns("/**").order(3);
- }
- }
复制代码 2)执行次序(没有异常)
- Interceptor1 preHandle // true
- Interceptor2 preHandle // true
- Interceptor3 preHandle // true
-
- Servlet service
- Interceptor3 postHandle
- Interceptor2 postHandle
- Interceptor1 postHandle
- Interceptor3 afterCompletion
- Interceptor2 afterCompletion
- Interceptor1 afterCompletion
复制代码 3)某拦截器 preHandle 返回false
这里我们假设中间的 Interceptor2 的 preHandle 返回 false
- Interceptor1 preHandle // true
- Interceptor2 preHandle // false
- Interceptor1 afterCompletion
复制代码- 之前的拦截器(即 Interceptor1): 执行了 preHandle 和 afterCompletion
- 阻隔的拦截器(即 Interceptor2): 执行了 preHandle
- 之后的拦截器(即 Interceptor3): 全部不执行
复制代码 4)执行次序(有异常)
- Interceptor1 preHandle // true
- Interceptor2 preHandle // true
- Interceptor3 preHandle // true
- // 发生异常之前
- Servlet service
- // 这个竟然是在 异常的堆栈信息 之前执行的
- Interceptor3 afterCompletion
- Interceptor2 afterCompletion
- Interceptor1 afterCompletion
- 异常的堆栈信息
- // 发生异常之后,又整体执行了一遍....
- Interceptor1 preHandle
- Interceptor2 preHandle
- Interceptor3 preHandle
- Interceptor3 postHandle
- Interceptor2 postHandle
- Interceptor1 postHandle
- Interceptor3 afterCompletion
- Interceptor2 afterCompletion
- Interceptor1 afterCompletion
复制代码 5)小结
团体次序:全部 preHandle -> Controller -> 全部 postHandle -> 全部 afterCompletion
- # preHandle
- 1. 调用前提
- 无
- 2. 调用时机
- Controller方法处理之前
- 3. 调用链顺序
- 顺序执行:preHandle1 ==> preHandle2 ==> preHandle3
- # postHandle
- 1. 调用前提
- preHandle返回true 且 Controller没有发生异常
- 2. 调用时机
- Controller方法处理完之后,afterCompletion调用之前
- 3. 调用链顺序
- 倒序执行:postHandle3 ==> postHandle2 ==> postHandle1
- # afterCompletion
- 1. 调用前提
- preHandle返回true(Controller发生异常也会调用)
- 2. 调用时机
- Controller方法处理完之后
- 3. 调用链顺序
- 倒序执行:afterCompletion3 ==> afterCompletion2 ==> afterCompletion1
复制代码 三、执行次序
1、自定义 Servlet
- public class MyServlet extends HttpServlet {
- @Override
- public void destroy() {
- System.out.println("Servlet destroy");
- super.destroy();
- }
- @Override
- public void init(ServletConfig config) throws ServletException {
- System.out.println("Servlet init");
- super.init(config);
- }
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- System.out.println("Servlet service");
- resp.getWriter().write("Hello from MyServlet");
- }
- }
复制代码- @Configuration
- public class ServletConfig {
- @Bean
- public ServletRegistrationBean<MyServlet> myServlet() {
- return new ServletRegistrationBean<>(new MyServlet(), "/myServlet");
- }
- }
复制代码 2、自定义 Filter
- public class MyFilter implements Filter {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- System.out.println("Filter init");
- Filter.super.init(filterConfig);
- }
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- // 前置处理...
- System.out.println("Filter doFilter before");
- // 处理请求
- chain.doFilter(request, response);
- // 后置处理...
- System.out.println("Filter doFilter after");
- }
- @Override
- public void destroy() {
- System.out.println("Filter destroy");
- Filter.super.destroy();
- }
- }
复制代码- @Configuration
- public class FilterConfig {
- @Bean
- public FilterRegistrationBean<MyFilter> myFilter() {
- FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
- registrationBean.setFilter(new MyFilter());
- registrationBean.addUrlPatterns("/*");
- registrationBean.setOrder(1);
- return registrationBean;
- }
- }
复制代码 3、自定义 Inteceptor
- public class MyInterceptor implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("Interceptor preHandle");
- return true; // 继续处理请求
- }
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("Interceptor postHandle");
- }
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("Interceptor afterCompletion");
- }
- }
复制代码- @Configuration
- public class WebConfig implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new MyInterceptor())
- .addPathPatterns("/**")
- .excludePathPatterns();
- }
- }
复制代码 4、对比:Servlet 与 Filter
- // 项目启动
- Filter init
-
- // 访问 http://localhost:8080/myServlet
- Servlet init
- Filter doFilter before
- Servlet service
- Filter doFilter after
- // 项目关闭
- Servlet destroy
- Filter destroy
复制代码 5、对比:Filter 与 Inteceptor
- @RestController
- public class TestController {
- @GetMapping("/interceptor")
- public ResponseEntity<String> interceptor() {
- System.out.println("Servlet service");
- return ResponseEntity.ok("SUCCESS");
- }
- }
复制代码- // 项目启动
- Filter init
- // 访问 http://localhost:8080/interceptor
- Filter doFilter before
- Interceptor preHandle
- Servlet service
- Interceptor postHandle
- Interceptor afterCompletion
- Filter doFilter after
- // 项目关闭
- Filter destroy
复制代码 6、小结
- // 项目启动
- Filter init
- // 访问接口
- Servlet init
- Filter doFilter before
- Interceptor preHandle
- Servlet service
- Interceptor postHandle
- Interceptor afterCompletion
- Filter doFilter after
- // 项目关闭
- Servlet destroy
- Filter destroy
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |