首页 > 其他分享 >过滤器与拦截器对比

过滤器与拦截器对比

时间:2024-08-29 12:53:34浏览次数:11  
标签:拦截器 请求 public 过滤器 import Servlet 对比

在Java Web开发中,过滤器(Filter)和拦截器(Interceptor)都是用于处理请求和响应的机制,但它们在使用场景、实现方式和功能上有一些重要的区别。 

过滤器(Filter)

特点:
  1. 工作原理

    • 过滤器是在请求到达Servlet之前或响应离开Servlet之后进行处理的。
    • 过滤器可以对请求和响应进行修改。
  2. 配置方式

    • 通过web.xml文件进行配置,或使用注解(如@WebFilter)进行声明。
  3. 适用范围

    • 主要用于对请求进行预处理(如日志记录、权限检查、请求编码等)或对响应进行后处理。
示例代码:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter("/*") // 过滤所有请求
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化代码
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 记录请求信息
        System.out.println("Request URL: " + httpRequest.getRequestURL());

        // 继续执行后续的请求处理
        chain.doFilter(request, response);

        // 记录响应信息
        System.out.println("Response Status: " + httpResponse.getStatus());
    }

    @Override
    public void destroy() {
        // 清理资源
    }
}

过滤器的触发过程

  1. 请求到达Servlet容器: 当用户发送一个HTTP请求时,请求首先到达Servlet容器(例如Apache Tomcat)。

  2. 过滤器链的构建: Servlet容器根据配置(如web.xml文件或@WebFilter注解)构建一个过滤器链。这个链条中包含了所有需要处理该请求的过滤器。

  3. 过滤器的调用顺序: 过滤器的调用顺序是根据它们在配置中的排列顺序来决定的。首先执行第一个过滤器的doFilter方法。

  4. 执行doFilter方法: 在每个过滤器的doFilter方法中,开发者可以实现对请求和响应的处理逻辑,比如:

    • 记录请求信息
    • 进行权限检查
    • 修改请求或响应的内容

    代码示例:

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
    
        // 记录请求信息
        System.out.println("Request URL: " + httpRequest.getRequestURL());
    
        // 继续执行后续的请求处理
        chain.doFilter(request, response); // 继续调用下一个过滤器或目标Servlet
    
        // 记录响应信息
        System.out.println("Response Status: " + httpResponse.getStatus());
    }
  5. 继续执行后续过滤器或目标Servlet: 在doFilter方法中调用chain.doFilter(request, response)后,请求将继续传递到下一个过滤器(如果存在)或最终的目标Servlet。

  6. 响应返回: 一旦目标Servlet处理完请求并生成响应,响应将返回到过滤器。每个过滤器的doFilter方法可以在此时对响应进行后处理。

  7. 过滤器的销毁: 当应用程序被关闭或过滤器被卸载时,Servlet容器会调用过滤器的destroy方法,进行资源清理。

总结

  • 过滤器的触发是由Servlet容器在请求到达Servlet之前和响应离开Servlet之后自动管理的。
  • 过滤器可以对请求和响应进行处理,并通过chain.doFilter方法控制请求的流向。
  • 过滤器的配置可以通过web.xml文件或使用注解(如@WebFilter)进行声明。

1. 过滤器的顺序由配置决定

无论是通过web.xml配置还是使用注解(如@WebFilter),过滤器的执行顺序都是根据它们在配置中的排列顺序决定的。

1.1 通过 web.xml 指定顺序

web.xml中,过滤器的顺序是由它们的定义顺序决定的。例如:

xml

<filter>
    <filter-name>FirstFilter</filter-name>
    <filter-class>com.example.FirstFilter</filter-class>
</filter>
<filter>
    <filter-name>SecondFilter</filter-name>
    <filter-class>com.example.SecondFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>FirstFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>SecondFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

在这个配置中,FirstFilter会在SecondFilter之前被调用。

拦截器(Interceptor)

特点:
  1. 工作原理

    • 拦截器是在请求到达Controller之前或响应离开Controller之后进行处理的。
    • 拦截器通常用于Spring MVC等框架中。
  2. 配置方式

    • 通过Spring配置文件或使用注解(如@Component)进行声明。
  3. 适用范围

    • 主要用于对请求进行预处理(如权限验证、日志记录)或对响应进行后处理。
 

1. 拦截器的触发

拦截器的触发通常与Spring MVC的请求处理过程密切相关。当用户发送HTTP请求时,Spring MVC会根据请求的URL映射到相应的Controller方法。在请求到达Controller之前,拦截器的preHandle方法会被调用。

2. 示例代码

 记录请求的时间、验证用户的角色、限制访问频率等。

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Component
public class MyInterceptor implements HandlerInterceptor {

    // 用于限制访问频率的简单计数器
    private Map<String, Long> requestCounts = new HashMap<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 记录请求信息
        System.out.println("Request URL: " + request.getRequestURL());
        System.out.println("Request Time: " + System.currentTimeMillis());

        // 权限验证示例
        String userRole = (String) request.getSession().getAttribute("userRole");
        if (userRole == null || !userRole.equals("ADMIN")) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN); // 无权限
            return false; // 终止请求
        }

        // 限制访问频率示例
        String clientIp = request.getRemoteAddr();
        Long lastRequestTime = requestCounts.get(clientIp);
        if (lastRequestTime != null && System.currentTimeMillis() - lastRequestTime < 1000) {
            response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS); // 频率限制
            return false; // 终止请求
        }
        requestCounts.put(clientIp, System.currentTimeMillis());

        return true; // 继续处理请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) {
        // 记录响应信息
        System.out.println("Response Status: " + response.getStatus());
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 清理资源
        System.out.println("Request completed.");
    }
}

3. 业务逻辑说明

  • 请求记录:记录请求的URL和时间,方便后续的调试和分析。
  • 权限验证:检查用户的角色是否为"ADMIN"。如果不是,则返回403 Forbidden状态,终止请求。
  • 访问频率限制:使用一个简单的HashMap来记录每个客户端IP的最后请求时间。若同一IP在1秒内发起多次请求,则返回429 Too Many Requests状态,限制其访问频率。

4. 如何触发拦截器

要触发这个拦截器,设置一个Controller,并确保请求的URL与该Controller的映射相匹配。例如:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @GetMapping("/admin")
    public String adminEndpoint() {
        return "Welcome to the admin page!";
    }
}

5. 配置拦截器

在Spring Boot应用中,在配置类中注册拦截器,并指定拦截的URL模式。如下所示:

import org.springframework.context.annotation.Bean;
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 {

    // 注册拦截器
    @Bean
    public MyInterceptor myInterceptor() {
        return new MyInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 配置拦截器的拦截条件
        registry.addInterceptor(myInterceptor())
                .addPathPatterns("/admin/**") // 拦截所有以/admin/开头的请求
                .excludePathPatterns("/public/**"); // 排除以/public/开头的请求
    }
}

6. 测试拦截器

  • 启动应用:运行Spring Boot应用程序。
  • 访问URL:在浏览器或Postman中访问http://localhost:8080/admin
  • 观察输出:查看控制台输出,确保拦截器的preHandlepostHandle方法被调用。

7. 不同测试场景

  • 未登录用户:在Session中不设置userRole,访问/admin,应该返回403状态。
  • 频率限制:在1秒内多次访问/admin,应该返回429状态。

8.配置拦截器链

在Spring配置中,可以通过WebMvcConfigurer接口来注册拦截器:

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 FirstInterceptor()).addPathPatterns("/**"); // 注册第一个拦截器
        registry.addInterceptor(new SecondInterceptor()).addPathPatterns("/**"); // 注册第二个拦截器
    }
}

9. 拦截器链的执行顺序

拦截器的执行顺序也是根据它们在addInterceptors方法中注册的顺序来决定的。以上述配置为例:

  1. FirstInterceptorpreHandle方法会在请求处理之前被调用。
  2. 然后调用SecondInterceptorpreHandle方法。
  3. 如果所有的preHandle方法返回true,请求会继续处理,最终调用目标Controller的方法。
  4. 请求处理完成后,控制权会返回到拦截器,依次调用postHandleafterCompletion方法。

关键区别

  • 过滤器:主要处理HTTP请求和响应的通用功能,适用于所有请求。它们在请求到达Servlet之前或响应离开Servlet之后执行。
  • 拦截器:主要处理特定业务逻辑的功能,适用于特定的业务方法调用。它们在特定方法调用之前和之后执行。

对比总结

特性过滤器(Filter)拦截器(Interceptor)
适用框架Java EE(Servlet)Spring MVC
处理时机请求到达Servlet之前和响应离开Servlet之后请求到达Controller之前和响应离开Controller之后
配置方式web.xml或注解Spring配置文件或注解
功能主要用于请求和响应的预处理和后处理主要用于请求的预处理和响应的后处理

具体使用场景

1. 请求日志记录
  • 场景描述:需要记录每个请求的详细信息(如请求 URL、请求时间等)。
  • 选择:使用过滤器
    • 原因:过滤器可以拦截所有请求,适合在请求到达Servlet之前进行日志记录。
2. 权限验证
  • 场景描述:在用户访问特定资源之前,需要验证用户的权限。
  • 选择:使用拦截器
    • 原因:拦截器可以在请求到达Controller之前进行处理,适合进行权限验证和拦截。
3. 请求参数处理
  • 场景描述:需要对请求参数进行统一处理,比如参数的格式化或编码。
  • 选择:使用过滤器
    • 原因:过滤器可以在请求到达Servlet之前处理请求参数,适合进行全局的请求参数处理。
4. 会话管理
  • 场景描述:需要在请求中检查用户的会话状态,确保用户已登录。
  • 选择:使用拦截器
    • 原因:拦截器可以在Controller处理请求之前检查会话状态,适合进行会话管理和用户认证。
5. 响应压缩
  • 场景描述:需要对响应数据进行压缩,以减少网络带宽的使用。
  • 选择:使用过滤器
    • 原因:过滤器可以在响应离开Servlet之前对响应数据进行处理,适合进行响应压缩。
6. 跨域请求处理
  • 场景描述:需要处理跨域请求,添加相应的CORS头信息。
  • 选择:使用过滤器
    • 原因:过滤器可以在请求到达Servlet之前添加必要的CORS头信息,适合进行跨域请求处理。

标签:拦截器,请求,public,过滤器,import,Servlet,对比
From: https://blog.csdn.net/weixin_51052174/article/details/141673903

相关文章

  • Android经典实战之存储方案对比:SharedPreferences vs MMKV vs DataStore
    本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点在Android开发中,键值对存储(Key-ValueStorage)是一种经常用到的轻量级数据存储方案。它主要用于保存一些简单的配置数据或状态信息,例如用户设置、缓存数据等。常......
  • JavaScript 模块化开发:ES6 模块与 CommonJS 的对比与应用
    ​​您好,我是程序员小羊!前言随着前端项目规模的增长,代码组织和管理变得越来越复杂。模块化开发成为解决这一问题的有效手段,能够帮助开发者将代码进行分割、复用和维护。JavaScript在发展过程中出现了多种模块化规范,其中最为广泛使用的有ES6模块(也称为ESModules)......
  • BeyondCompare替代,推荐四款免费代码文件对比软件
     BeyondCompare是一套内容比较工具软件。除了可以作文件比较以外,还可以比对文件目录、FTP目录及压缩包案的内容等,但是由于要收费且比较贵,很多公司也在规避工作电脑使用非授权软件的风险,所以分享四款平替BeyondCompare的文件代码对比软件工具。1、WinMergeWinMerge是一款......
  • 【Unity】经典四叉树的实现以及和无空间划分加速下的效率对比分析
    背景假如场景中存在大量的对象,需要快速找到某个范围内的所有对象,如果通过传统的方式,就需要对所有的物体遍历,依次判断是否在范围中,这样非常耗时。所以通过空间划分的方法将其加速,本文中采用四叉树的方式,从实现思想和代码层面对效率进行分析。思想在空间划分算法中首先需要对所有......
  • Qt 事件传递流程-事件处理器|事件分发器|事件过滤器
    (总体传递流程图见文章末尾)自定义控件结构 自定义继承于QLabel的控件类 PropagateLabel.h 自定义窗口 PropagateWidget 在PropagateWidget中添加一个PropagateLabel标签1PropagateWidget::PropagateWidget(QWidget*parent):2QWidget(parent)3{4......
  • 在 Transformers 中使用对比搜索
    在Transformers中使用对比搜索生成可媲美人类水平的文本......
  • MVVM框架对比
    框架名称MvvmLigthCommunityToolkit.MvvmPrismCaliburn.Micro通知属性ObservableObjectObservableObjectBindableBasePropertyChangedBaseViewModel基类ViewModelBase无无Screen/Conductor命令对象RelayCommandRelayCommandDelegateComma......
  • Odoo17.0 送货运费对比
    运费对比前面讲了如何在odoo中使用各种承运商来完成运费查询和发货等操作,一个很自然的场景就出来了,当我们同时启用了多个物流方式的时候,我们自然希望在发货的时候能够选择性价比最高的那个进行发货。因此,我们需要有一个物流方式对比的功能。在我们的欧姆物流解决方案中,我们实现了......
  • 大模型RAG应用开发之PDF解析工具对比
    一汇总类型名称地址OCR提取表格内容保留文本顺序提取图片保存成md格式其他特性传统PDF解析库pymupdfhttps://github.com/pymupdf/PyMuPDF❌✔️✔️✔️❌●表格提取●自定义字体传统PDF解析库pdfminerhttps://github.com/pdfminer/pdfminer.six❌❌......
  • 【微前端】前端微服务框架对比和技术选型
    文章目录:目录文章目录:前言:具体内容:1.什么是微前端2.使用微服务的场景:iframe方案的缺点:3.主流微服务框架介绍2.1无界-腾讯官网github地址:无界的运行模式简单了解一下原理主要特性:优势:劣势:2.2 MicroApp-京东官网:github地址:主要特性:优势:劣势:2.3qiankun-......