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...)

相关推荐
livemetee2 小时前
springboot 整合spring-kafka客户端:SASL_SSL+PLAINTEXT方式
spring boot·spring·kafka
要开心吖ZSH2 小时前
Spring Cloud LoadBalancer 详解
后端·spring·spring cloud
丶小鱼丶6 小时前
Spring之【BeanDefinition】
java·spring
武子康6 小时前
Java-75 深入浅出 RPC Dubbo Java SPI机制详解:从JDK到Dubbo的插件式扩展
java·分布式·后端·spring·微服务·rpc·dubbo
NE_STOP7 小时前
SpringBoot--自动配置的替换和关闭
java·spring
Honesty8610248 小时前
深入排查:@Scope(“prototype“)与@RequestScope字段篡改问题全链路分析
java·spring boot·spring·原型模式
Honesty8610248 小时前
Spring 作用域冲突深度解析:@Scope(“prototype“)与@RequestScope的冲突与解决方案
java·spring·原型模式
麦兜*11 小时前
SpringBoot 3.x集成阿里云OSS:文件上传 断点续传 权限控制
java·spring boot·后端·spring·spring cloud·阿里云·maven
老神在在00114 小时前
SpringMVC1
java·前端·学习·spring