Filter过滤器和Interceptor拦截器的使用和区别

Filter介绍

什么是Filter?

  • Filter表示过滤器,是 JavaWeb三大组件(Servlet、Filter、Listener)之一。

  • 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能

    • 使用了过滤器之后,要想访问web服务器上的资源,必须先经过滤器,过滤器处理完毕之后,才可以访问对应的资源。
  • 过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等。

下面我们通过Filter快速入门程序掌握过滤器的基本使用操作:

  • 第1步,定义过滤器 :1.定义一个类,实现 Filter 接口,并重写其所有方法。
  • 第2步,配置过滤器:Filter类上加 @WebFilter 注解,配置拦截资源的路径。引导类上加 @ServletComponentScan 开启Servlet组件支持。
  • 直接演示过滤器结合Jwt令牌校验在实际登录过程中的应用
java 复制代码
@Slf4j
@WebFilter(urlPatterns = "/*")
public class TokenFilter implements Filter {
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
      HttpServletRequest request = (HttpServletRequest) servletRequest;
      HttpServletResponse response = (HttpServletResponse) servletResponse;
      // 1. 获取请求url
      String uri = request.getRequestURI();
//        2. 判断请求url中是否包含login,如果包含,说明是登录操作,放行
      if (uri.contains("/login")) {
          log.info("登录请求,直接放行");
          chain.doFilter(request, response);
          return;
      }

//        3. 获取请求头中的令牌(token)
      String token = request.getHeader("token");
//        4. 判断令牌是否存在,如果不存在,响应 401
      if (StrUtil.isBlank(token)) {
          response.setStatus(HttpStatus.HTTP_UNAUTHORIZED);
          return;
      }
//        5. 解析token,如果解析失败,响应 401
      try {
          JwtUtils.parseJWT(token);
          //        6. 放行
          chain.doFilter(request, response);
      } catch (Exception e) {
          response.setStatus(HttpStatus.HTTP_UNAUTHORIZED);
          return;
      }



  }
}

当我们在Filter类上面加了@WebFilter注解之后,接下来我们还需要在启动类上面加上一个注解@ServletComponentScan,通过这个@ServletComponentScan注解来开启SpringBoot项目对于Servlet组件的支持。

less 复制代码
@ServletComponentScan //开启对Servlet组件的支持
@SpringBootApplication
public class TliasManagementApplication {
    public static void main(String[] args) {
        SpringApplication.run(TliasManagementApplication.class, args);
    }
}

注意事项: 在过滤器Filter中,如果不执行放行操作,将无法访问后面的资源。 放行操作:chain.doFilter(request, response);

2、Interceptor拦截器

Interceptor

什么是拦截器?

  • 是一种动态拦截方法调用的机制,类似于过滤器。
  • 拦截器是Spring框架中提供的,用来动态拦截控制器方法的执行。
  • 拦截器的作用:拦截请求,在指定方法调用前后,根据业务需要执行预先设定的代码。

在拦截器当中,我们通常也是做一些通用性的操作,比如:我们可以通过拦截器来拦截前端发起的请求,将登录校验的逻辑全部编写在拦截器当中。在校验的过程当中,如发现用户登录了(携带JWT令牌且是合法令牌),就可以直接放行,去访问spring当中的资源。如果校验时发现并没有登录或是非法令牌,就可以直接给前端响应未登录的错误信息。 拦截器的使用步骤和过滤器类似,也分为两步:

  1. 定义拦截器
  2. 注册配置拦截器

1). 自定义拦截器

实现HandlerInterceptor接口,并重写其所有方法

java 复制代码
//自定义拦截器
@Component
public class DemoInterceptor implements HandlerInterceptor {
    //目标资源方法执行前执行。 返回true:放行    返回false:不放行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle .... ");
        
        return true; //true表示放行
    }

    //目标资源方法执行后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle ... ");
    }

    //视图渲染完毕后执行,最后执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion .... ");
    }
}

注意:

  • preHandle方法:目标资源方法执行前执行。 返回true:放行 返回false:不放行

  • postHandle方法:目标资源方法执行后执行

  • afterCompletion方法:视图渲染完毕后执行,最后执行

2). 注册配置拦截器

com.itheima下创建一个包,然后创建一个配置类 WebConfig, 实现 WebMvcConfigurer 接口,并重写 addInterceptors 方法

typescript 复制代码
@Configuration  
public class WebConfig implements WebMvcConfigurer {

    //自定义的拦截器对象
    @Autowired
    private DemoInterceptor demoInterceptor;

    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       //注册自定义拦截器对象
        registry.addInterceptor(demoInterceptor).addPathPatterns("/**");//设置拦截器拦截的请求路径( /** 表示拦截所有请求)
    }
}
  1. 令牌校验Interceptor

讲解完了拦截器的基本操作之后,接下来我们需要完成最后一步操作:通过拦截器来完成案例当中的登录校验功能。

登录校验的业务逻辑以及操作步骤我们前面已经分析过了,和登录校验Filter过滤器当中的逻辑是完全一致的。现在我们只需要把这个技术方案由原来的过滤器换成拦截器interceptor就可以了。

1). Token和Interceptor

java 复制代码
@Slf4j
@Component
public class TokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1. 获取请求url。
        String uri = request.getRequestURI().toString();

        //2. 判断请求url中是否包含login,如果包含,说明是登录操作,放行。
        if(uri.contains("login")){ //登录请求
            log.info("登录请求 , 直接放行");
            return true;
        }

        //3. 获取请求头中的令牌(token)。
        String jwt = request.getHeader("token");

        //4. 判断令牌是否存在,如果不存在,返回错误结果(未登录)。
        if(StringUtils.isBlank(jwt)){ //jwt为空
            log.info("获取到jwt令牌为空, 返回错误结果");
            response.setStatus(HttpStatus.SC_UNAUTHORIZED);
            return false;
        }

        //5. 解析token,如果解析失败,返回错误结果(未登录)。
        try {
            JwtUtils.parseJWT(jwt);
            //6. 放行。
        log.info("令牌合法, 放行");
        return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.info("解析令牌失败, 返回错误结果");
            response.setStatus(HttpStatus.SC_UNAUTHORIZED);
            return false;
        }

   
    }

}

2). 配置拦截器

typescript 复制代码
@Configuration  
public class WebConfig implements WebMvcConfigurer {
    //拦截器对象
    @Autowired
    private TokenInterceptor tokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       //注册自定义拦截器对象
        registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
    }
}
  1. 拦截路径

首先我们先来看拦截器的拦截路径的配置,在注册配置拦截器的时候,我们要指定拦截器的拦截路径,通过addPathPatterns("要拦截路径")方法,就可以指定要拦截哪些资源。

在入门程序中我们配置的是/**,表示拦截所有资源,而在配置拦截器时,不仅可以指定要拦截哪些资源,还可以指定不拦截哪些资源,只需要调用excludePathPatterns("不拦截路径")方法,指定哪些资源不需要拦截。

typescript 复制代码
@Configuration  
public class WebConfig implements WebMvcConfigurer {

    //拦截器对象
    @Autowired
    private DemoInterceptor demoInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册自定义拦截器对象
        registry.addInterceptor(demoInterceptor)
                .addPathPatterns("/**")//设置拦截器拦截的请求路径( /** 表示拦截所有请求)
                .excludePathPatterns("/login");//设置不拦截的请求路径
    }
}

3过滤器和拦截器的区别

在Java Web开发中,过滤器(Filter)和拦截器(Interceptor)都是常见的用于在请求和响应之间进行处理的组件。它们的主要区别如下:,

1、他们依赖的框架不同:过滤器是web的三大规范之一,不依赖任何框架,三大规范分别是Servlet、Filter和Listener。而拦截器是依赖于特定的框架而实现的,例如本文讲的基于spring框架实现的

2、功能不同:过滤器主要用于对请求进行预处理和过滤,例如设置字符集、登录验证、日志记录等操作;而拦截器则主要用于对请求进行流程控制,例如权限验证、参数注入、异常处理等操作。他们的拦截路径也有所区别,比如Filter中的/表示拦截全部的请求路径,Interceptor中的/ * 才表示拦截全部的请求路径。

3、触发时机也不同:请求的执行顺序是:请求进入容器 > 进入过滤器 > 进入 Servlet > 进入拦截器 > 执行控制器,所以过滤器和拦截器的执行时机也是不同的,过滤器会先执行,然后才会执行拦截器,最后才会进入真正的要调用的方法。过滤器通常是用来进行全局过滤的,而拦截器是用来实现某项业务拦截的。

图片来源:(juejin.cn/post/715506...)

相关推荐
sniper_fandc29 分钟前
Spring Cloud系列—LoadBalance负载均衡
后端·spring·spring cloud
右手嘚温暖7 小时前
分布式事务Seata、LCN的原理深度剖析
spring boot·分布式·后端·spring·spring cloud·中间件·架构
麦兜*9 小时前
Spring Boot集成方案 + Elasticsearch向量检索,语义搜索核弹
java·spring boot·python·spring·elasticsearch·spring cloud·系统架构
yh云想11 小时前
《RedisTemplate 核心操作全解析》
redis·spring·redistemplate
一枚小小程序员哈11 小时前
基于springboot的宠物商城设计与实现
java·spring boot·spring·eclipse·tomcat·maven·宠物
一个儒雅随和的男子16 小时前
Spring Security 框架深度集成与开发指南
java·后端·spring
写代码的比利17 小时前
Spring 调试终于不再痛苦了
spring boot·spring·intellij idea
丶小鱼丶17 小时前
Spring之【初识AOP】
java·spring
探索java18 小时前
Spring MVC框架中全局异常处理机制详解
java·spring·mvc
Java水解19 小时前
Spring AI+Redis会话记忆持久化存储实现
后端·spring