详解过滤器Filter和拦截器Interceptor的区别和联系

目录

前言

区别

联系


前言

  • 过滤器(Filter)和拦截器(Interceptor)都是用于在Web应用程序中处理请求和响应的组件,但它们在实现方式和功能上有一些区别。

区别

    1. 实现方式:
  • 过滤器是基于Servlet规范的组件,通过实现javax.servlet.Filter接口 来定义。过滤器可以在请求被处理之前和响应被发送到客户端之前进行操作。

  • 拦截器是基于Java的反射机制,通过实现HandlerInterceptor接口来定义。拦截器可以在请求被处理之前、处理过程中和响应被发送到客户端之前进行操作。

    1. 执行顺序:
  • 过滤器在Servlet容器中的执行顺序是由部署描述符(web.xml)中的配置顺序决定的,它们按照配置的顺序依次执行。

  • 拦截器在Spring MVC框架中的执行顺序是由配置文件中的拦截器顺序决定的,它们按照配置的顺序依次执行。

具体参照文章:登录校验-Interceptor-详解_熵240的博客-CSDN博客

    1. 功能:
  • 过滤器可以对请求进行预处理和后处理,例如修改请求参数、编码转换、请求拦截等。过滤器可以对所有的请求进行统一的处理。

  • 拦截器可以对请求进行更加细粒度的控制和处理,例如权限验证、日志记录、性能监控等。拦截器可以根据具体的请求路径、请求方法、请求参数等进行处理。

    1. 作用范围:
  • 过滤器是在Servlet容器中工作的 ,可以对所有的请求进行过滤处理,包括静态资源请求和动态请求。

  • 拦截器是在Spring MVC框架中工作的只能对控制器(Controller)处理的请求进行拦截处理。

    1. 放行条件不一样

-过滤器(Filter)放行方式是执行doFilter()方法实现的

java 复制代码
package com.example.tlias.Filter;

import com.alibaba.fastjson.JSONObject;
import com.example.tlias.pojo.Result;
import com.example.tlias.utils.JwtUtils;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.io.IOException;

@Slf4j
//@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 1.获取请求URL地址
        String url = request.getRequestURI().toString();
        log.info("获取到的URL地址为:{}", url);

        // 2.判断URL是否含有login路径,如果含有,则为登陆操作,放行
        if (url.contains("login")) {
            log.info("此请求为登陆操作,放行.......");
            filterChain.doFilter(request, response);
            return; //  todo 跳出过滤器
        }
        // todo 以下是对于不是登录操作的过滤
        // 3.获取请求头中的令牌(token)
        String token = request.getHeader("token");

        // 4.判断是否存在,如果不存在,返回错误结果(未登录)
        if (!StringUtils.hasLength(token)) {
            log.info("请求头token为空,返回为登录的信息");
            Result error = Result.error("NOT_LOGIN"); // 返回的错误信息通过接口文档与前端统一
            // todo 手动转换 将对象-->json格式数据===》可以使用阿里巴巴fastJson的工具包,在pom.xml配置文件中添加相关依赖
            // todo 控制类返回的对象会自动转换为JSON格式的字符串数据
            String noLogin = JSONObject.toJSONString(error);
            // 将数据写入响应对象
            response.getWriter().write(noLogin);
            return; // todo 跳出过滤器
        }

        // 5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(token);  // todo 如果解析失败方法就会报错
        } catch (Exception e) {  // token解析失败
            e.printStackTrace();
            log.info("解析令牌失败,返回未登录的错误信息");
            Result error = Result.error("NOT_LOGIN");
            String noLogin = JSONObject.toJSONString(error);
            response.getWriter().write(noLogin);
            return;
        }
        // 6.放行
        log.info("令牌合法,放行");
        filterChain.doFilter(request, response);
    }
}

-拦截器(Interceptor)放行的方法是在preHandle()种返回true值

java 复制代码
package com.example.tlias.Interceptor;

import com.alibaba.fastjson.JSONObject;
import com.example.tlias.pojo.Result;
import com.example.tlias.utils.JwtUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component // 将该类标记为组件交给IOC容器管理
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override  // todo 在目标资源方法(控制类中的方法)执行之前执行,返回true:放行;返回false:不放行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 1.获取请求URL地址
        String url = request.getRequestURI().toString();
        log.info("获取到的URL地址为:{}", url);

        // 2.判断URL是否含有login路径,如果含有,则为登陆操作,放行
        if (url.contains("login")) {
            log.info("此请求为登陆操作,放行.......");
            return true; //  todo 跳出拦截器
        }
        // todo 以下是对于不是登录操作的过滤
        // 3.获取请求头中的令牌(token)
        String token = request.getHeader("token");

        // 4.判断是否存在,如果不存在,返回错误结果(未登录)
        if (!StringUtils.hasLength(token)) {
            log.info("请求头token为空,返回为登录的信息");
            Result error = Result.error("NOT_LOGIN"); // 返回的错误信息通过接口文档与前端统一
            // todo 手动转换 将对象-->json格式数据===》可以使用阿里巴巴fastJson的工具包,在pom.xml配置文件中添加相关依赖
            // todo 控制类返回的对象会自动转换为JSON格式的字符串数据
            String noLogin = JSONObject.toJSONString(error);
            // 将数据写入响应对象
            response.getWriter().write(noLogin);
            return false; // todo 跳出过滤器
        }

        // 5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(token);  // todo 如果解析失败方法就会报错
        } catch (Exception e) {  // token解析失败
            e.printStackTrace();
            log.info("解析令牌失败,返回未登录的错误信息");
            Result error = Result.error("NOT_LOGIN");
            String noLogin = JSONObject.toJSONString(error);
            response.getWriter().write(noLogin);
            return false;
        }
        // 6.放行
        log.info("令牌合法,放行");
        return true;
    }

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

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

联系

  • 过滤器和拦截器都可以用于对请求进行处理,但它们的实现方式和功能不同。
  • 过滤器是基于Servlet规范的组件,可以对所有的请求进行统一的处理;拦截器是基于Spring MVC框架的组件,只能对控制器处理的请求进行处理。
  • 过滤器和拦截器都可以用于对请求进行预处理和后处理,但拦截器可以提供更加细粒度的控制和处理。
  • 过滤器和拦截器都可以在请求被处理之前和响应被发送到客户端之前进行操作,但它们的执行顺序不同。
相关推荐
CoderJia程序员甲20 小时前
重学SpringBoot3-集成Redis(一)
java·redis·缓存·springboot
识途老码2 天前
Centos7安装Jenkins
运维·servlet·jenkins
奔跑吧邓邓子2 天前
Jenkins从入门到精通,构建高效自动化流程
servlet·自动化·jenkins
学习ing小白3 天前
JavaWeb - 8 - 请求响应 & 分层解耦
java·springboot·后端web开发
Hello Dam3 天前
【文件增量备份系统】MySQL百万量级数据量分页查询性能优化
java·mysql·性能优化·springboot·深分页优化
人生匆匆3 天前
bluefs _flush_range allocated: osd用空间但是显示ceph_bluefs_db_used_bytes is 100%
数据库·ceph·servlet
天下蒂一厨4 天前
jenkins微服务
linux·servlet·微服务·jenkins
大灰狼19135 天前
【怎样基于Okhttp3来实现各种各样的远程调用,表单、JSON、文件、文件流等待】
java·springboot·网络流·okhttp3·文件流传输
一 乐5 天前
高校体育场小程序|高校体育场管理系统系统|体育场管理系统小程序设计与实现(源码+数据库+文档)
数据库·小程序·vue·源码·springboot·体育馆小程序
爱跑步的程序员~6 天前
若依框架使用教程
vue.js·低代码·mybatis·springboot