过滤器 与 拦截器

打印 上一主题 下一主题

主题 894|帖子 894|积分 2682

过滤器 与 拦截器

一、过滤器(Filter)

1、特点

过滤器是基于Java Servlet规范的一部分,用于在哀求 到达Servlet之前 或 响应离开Servlet之后 对哀求和响应进行处理。


  • 过滤器可以对全部哀求进行处理,不仅限于特定的Servlet或Spring MVC控制器。
  • 过滤器在Servlet容器层面工作,而不是Spring层面。
  • 得当用于日志记载、身份验证、权限查抄等通用功能。
2、生命周期

  1. public interface Filter {
  2.     // 初始化方法
  3.     default void init(FilterConfig filterConfig) throws ServletException {
  4.     }
  5.     // 执行拦截方法
  6.     void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
  7.     // 销毁方法
  8.     default void destroy() {
  9.     }
  10. }
复制代码
  1. # 创建【init方法】
  2. 1. 特点:
  3.                 服务器启动,项目加载,创建filter对象,执行【init方法】(只执行一次)
  4. 2. 对比Servlet:
  5.                 先于Servlet的init方法执行
  6. # 拦截【doFilter方法】
  7. 1. 特点:
  8.                 用户访问被拦截的目标资源时,执行【doFilter方法】(浏览器每访问一次,就会执行一次)
  9. 2. 对比Servlet:
  10.                 先于Servlet的service方法执行
  11. # 销毁【destroy方法】
  12. 1. 特点:
  13.                 服务器关闭,项目关闭,销毁filter对象,执行【destroy方法】(只执行一次)
  14. 2. 对比Servlet:
  15.                 后于Servlet的destroy方法执行
复制代码
3、实现

定义拦截器只要实现Filter接口,重写doFilter方法即可
  1. public class MyFilter implements Filter {
  2.     @Override
  3.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  4.         // 前置处理...
  5.         System.out.println("Filter doFilter before");
  6.         // 处理请求
  7.         chain.doFilter(request, response);
  8.         // 后置处理...
  9.         System.out.println("Filter doFilter after");
  10.     }
  11. }
复制代码
注册拦截器(SpringBoot示例)
  1. @Configuration
  2. public class FilterConfig {
  3.     @Bean
  4.     public FilterRegistrationBean<MyFilter> myFilter() {
  5.         FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
  6.         registrationBean.setFilter(new MyFilter());
  7.         // 过滤路径(/*表示所有)
  8.         registrationBean.addUrlPatterns("/*");
  9.         // 过滤顺序(多个Filter按Order从小到大顺序执行)
  10.         registrationBean.setOrder(1);
  11.         return registrationBean;
  12.     }
  13. }
复制代码
4、过滤器链

1)配置 order

多个 Filter 按 Order的巨细 从小到大 执行(如果没有配置Order,按 Bean声明的次序 从上到下 执行)
  1. @Configuration
  2. public class FilterConfig {
  3.     @Bean
  4.     public FilterRegistrationBean<MyFilter> myFilter1() {
  5.         FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
  6.         registrationBean.setFilter(new MyFilter1());
  7.         registrationBean.addUrlPatterns("/*");
  8.         registrationBean.setOrder(1);
  9.         return registrationBean;
  10.     }
  11.     @Bean
  12.     public FilterRegistrationBean<MyFilter> myFilter2() {
  13.         FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
  14.         registrationBean.setFilter(new MyFilter2());
  15.         registrationBean.addUrlPatterns("/*");
  16.         registrationBean.setOrder(2);
  17.         return registrationBean;
  18.     }
  19.     @Bean
  20.     public FilterRegistrationBean<MyFilter> myFilter3() {
  21.         FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
  22.         registrationBean.setFilter(new MyFilter3());
  23.         registrationBean.addUrlPatterns("/*");
  24.         registrationBean.setOrder(3);
  25.         return registrationBean;
  26.     }
  27. }
复制代码
2)执行次序

  1. Filter1 doFilter before
  2. Filter2 doFilter before
  3. Filter3 doFilter before
  4. Servlet service
  5. // 如果发生异常,就不会执行 doFilter after 了
  6. Filter3 doFilter after
  7. Filter2 doFilter after
  8. Filter1 doFilter after
复制代码
二、拦截器 Inteceptor

1、特点

拦截器是Spring MVC提供的功能,用于在哀求到达控制器之前和响应离开控制器之后进行处理。


  • 拦截器主要用于Spring MVC层面,处理的是控制器层的哀求和响应。
  • 得当用于权限查抄、日志记载、哀求计时等与业务逻辑密切相关的操作。
2、生命周期


  1. public interface HandlerInterceptor {
  2.     // Controller执行之前调用
  3.         default boolean preHandle(HttpServletRequest request,  HttpServletResponse response, Object handler) throws Exception {
  4.                 return true;
  5.         }
  6.     // Controller执行之后调用(发生异常 或 preHandle=false 不会调用)
  7.         default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
  8.         }
  9.     // Controller执行之后调用(发生异常也会调用,preHandle=false不会调用)
  10.         default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
  11.         }
  12. }
复制代码
3、实现

自定义拦截器只要实现HandlerInterceptor接口,按需重写指定即可。
  1. public class MyInterceptor implements HandlerInterceptor {
  2.     @Override
  3.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4.         System.out.println("Pre Handle method is Called");
  5.         return true; // 继续处理请求
  6.     }
  7.     @Override
  8.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  9.         System.out.println("Post Handle method is Called");
  10.     }
  11.     @Override
  12.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  13.         System.out.println("Request and Response is completed");
  14.     }
  15. }
复制代码
注册拦截器
  1. import org.springframework.context.annotation.Configuration;
  2. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  3. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  4. @Configuration
  5. public class WebConfig implements WebMvcConfigurer {
  6.     @Override
  7.     public void addInterceptors(InterceptorRegistry registry) {
  8.         // 添加自定义拦截器
  9.         registry.addInterceptor(new MyInterceptor())
  10.                     // 配置拦截路径
  11.                 .addPathPatterns("/**")
  12.                     // 配置放过路径
  13.                 .excludePathPatterns();
  14.     }
  15. }
复制代码
4、拦截器链

1)配置 order

多个 Interceptor 按 Order的巨细 从小到大 执行(如果没有配置Order,按 添加的次序 从上到下 执行)
  1. @Configuration
  2. public class MyAdapter implements WebMvcConfigurer {
  3.         @Override
  4.         public void addInterceptors(InterceptorRegistry registry) {
  5.                 registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").order(1);
  6.         registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**").order(2);
  7.         registry.addInterceptor(new MyInterceptor3()).addPathPatterns("/**").order(3);
  8.         }
  9. }
复制代码
2)执行次序(没有异常)

  1. Interceptor1 preHandle        // true
  2. Interceptor2 preHandle        // true
  3. Interceptor3 preHandle        // true
  4.    
  5. Servlet service
  6. Interceptor3 postHandle
  7. Interceptor2 postHandle
  8. Interceptor1 postHandle  
  9. Interceptor3 afterCompletion
  10. Interceptor2 afterCompletion
  11. Interceptor1 afterCompletion
复制代码
3)某拦截器 preHandle 返回false

这里我们假设中间的 Interceptor2 的 preHandle 返回 false
  1. Interceptor1 preHandle        // true
  2. Interceptor2 preHandle        // false
  3. Interceptor1 afterCompletion
复制代码
  1. 之前的拦截器(即 Interceptor1): 执行了 preHandle 和 afterCompletion
  2. 阻隔的拦截器(即 Interceptor2): 执行了 preHandle
  3. 之后的拦截器(即 Interceptor3): 全部不执行
复制代码
4)执行次序(有异常)

  1. Interceptor1 preHandle        // true
  2. Interceptor2 preHandle        // true
  3. Interceptor3 preHandle        // true
  4. // 发生异常之前
  5. Servlet service
  6. // 这个竟然是在 异常的堆栈信息 之前执行的
  7. Interceptor3 afterCompletion
  8. Interceptor2 afterCompletion
  9. Interceptor1 afterCompletion
  10. 异常的堆栈信息
  11. // 发生异常之后,又整体执行了一遍....
  12. Interceptor1 preHandle
  13. Interceptor2 preHandle
  14. Interceptor3 preHandle
  15. Interceptor3 postHandle
  16. Interceptor2 postHandle
  17. Interceptor1 postHandle
  18. Interceptor3 afterCompletion
  19. Interceptor2 afterCompletion
  20. Interceptor1 afterCompletion
复制代码
5)小结

团体次序:全部 preHandle -> Controller -> 全部 postHandle -> 全部 afterCompletion
  1. # preHandle
  2. 1. 调用前提
  3.                 无
  4. 2. 调用时机
  5.                 Controller方法处理之前
  6. 3. 调用链顺序
  7.                 顺序执行:preHandle1 ==> preHandle2 ==> preHandle3
  8. # postHandle
  9. 1. 调用前提
  10.                 preHandle返回true 且 Controller没有发生异常
  11. 2. 调用时机
  12.                 Controller方法处理完之后,afterCompletion调用之前
  13. 3. 调用链顺序
  14.                 倒序执行:postHandle3 ==> postHandle2 ==> postHandle1
  15. # afterCompletion
  16. 1. 调用前提
  17.                 preHandle返回true(Controller发生异常也会调用)
  18. 2. 调用时机
  19.                 Controller方法处理完之后
  20. 3. 调用链顺序
  21.                 倒序执行:afterCompletion3 ==> afterCompletion2 ==> afterCompletion1
复制代码
三、执行次序

1、自定义 Servlet

  1. public class MyServlet extends HttpServlet {
  2.     @Override
  3.     public void destroy() {
  4.         System.out.println("Servlet destroy");
  5.         super.destroy();
  6.     }
  7.     @Override
  8.     public void init(ServletConfig config) throws ServletException {
  9.         System.out.println("Servlet init");
  10.         super.init(config);
  11.     }
  12.     @Override
  13.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  14.         System.out.println("Servlet service");
  15.         resp.getWriter().write("Hello from MyServlet");
  16.     }
  17. }
复制代码
  1. @Configuration
  2. public class ServletConfig {
  3.     @Bean
  4.     public ServletRegistrationBean<MyServlet> myServlet() {
  5.         return new ServletRegistrationBean<>(new MyServlet(), "/myServlet");
  6.     }
  7. }
复制代码
2、自定义 Filter

  1. public class MyFilter implements Filter {
  2.     @Override
  3.     public void init(FilterConfig filterConfig) throws ServletException {
  4.         System.out.println("Filter init");
  5.         Filter.super.init(filterConfig);
  6.     }
  7.     @Override
  8.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  9.         // 前置处理...
  10.         System.out.println("Filter doFilter before");
  11.         // 处理请求
  12.         chain.doFilter(request, response);
  13.         // 后置处理...
  14.         System.out.println("Filter doFilter after");
  15.     }
  16.     @Override
  17.     public void destroy() {
  18.         System.out.println("Filter destroy");
  19.         Filter.super.destroy();
  20.     }
  21. }
复制代码
  1. @Configuration
  2. public class FilterConfig {
  3.     @Bean
  4.     public FilterRegistrationBean<MyFilter> myFilter() {
  5.         FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
  6.         registrationBean.setFilter(new MyFilter());
  7.         registrationBean.addUrlPatterns("/*");
  8.         registrationBean.setOrder(1);
  9.         return registrationBean;
  10.     }
  11. }
复制代码
3、自定义 Inteceptor

  1. public class MyInterceptor implements HandlerInterceptor {
  2.     @Override
  3.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4.         System.out.println("Interceptor preHandle");
  5.         return true; // 继续处理请求
  6.     }
  7.     @Override
  8.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  9.         System.out.println("Interceptor postHandle");
  10.     }
  11.     @Override
  12.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  13.         System.out.println("Interceptor afterCompletion");
  14.     }
  15. }
复制代码
  1. @Configuration
  2. public class WebConfig implements WebMvcConfigurer {
  3.     @Override
  4.     public void addInterceptors(InterceptorRegistry registry) {
  5.         registry.addInterceptor(new MyInterceptor())
  6.                 .addPathPatterns("/**")
  7.                 .excludePathPatterns();
  8.     }
  9. }
复制代码
4、对比:Servlet 与 Filter

  1. // 项目启动
  2. Filter init
  3.    
  4. // 访问 http://localhost:8080/myServlet
  5. Servlet init
  6. Filter doFilter before
  7. Servlet service
  8. Filter doFilter after
  9. // 项目关闭
  10. Servlet destroy
  11. Filter destroy
复制代码
5、对比:Filter 与 Inteceptor

  1. @RestController
  2. public class TestController {
  3.     @GetMapping("/interceptor")
  4.     public ResponseEntity<String> interceptor() {
  5.         System.out.println("Servlet service");
  6.         return ResponseEntity.ok("SUCCESS");
  7.     }
  8. }
复制代码
  1. // 项目启动
  2. Filter init
  3. // 访问 http://localhost:8080/interceptor
  4. Filter doFilter before
  5. Interceptor preHandle
  6. Servlet service
  7. Interceptor postHandle
  8. Interceptor afterCompletion
  9. Filter doFilter after
  10. // 项目关闭
  11. Filter destroy
复制代码
6、小结


  1. // 项目启动
  2. Filter init
  3. // 访问接口
  4. Servlet init
  5. Filter doFilter before
  6. Interceptor preHandle
  7. Servlet service
  8. Interceptor postHandle
  9. Interceptor afterCompletion
  10. Filter doFilter after
  11. // 项目关闭
  12. Servlet destroy
  13. Filter destroy
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王海鱼

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表