当前位置: 首页 > article >正文

设计模式——拦截过滤器模式

定义与概念

拦截过滤器模式(Intercepting Filter Pattern)是一种软件设计模式,主要用于在处理请求的过程中,对请求进行一系列预处理和后处理操作。这些操作通过一系列的过滤器来实现,过滤器可以在请求到达目标处理程序之前对请求进行检查、修改或记录等操作,也可以在目标处理程序生成响应之后对响应进行类似的操作。

结构组成

  • 过滤器(Filter):
    这是模式的核心组件,它定义了对请求和响应进行操作的接口。过滤器可以有多个,每个过滤器都有自己特定的功能,如身份验证过滤器、日志记录过滤器、数据压缩过滤器等。过滤器通常会实现一个doFilter()方法,这个方法接收请求和响应对象,并在其中执行对请求或响应的操作,还会决定是否将请求传递给下一个过滤器或者目标处理程序。例如,身份验证过滤器会在doFilter()方法中检查请求中的用户凭据,只有验证通过的请求才会被继续传递。
  • 目标处理程序(Target Handler):
    目标处理程序是最终处理请求并生成响应的组件。它接收经过一系列过滤器处理后的请求,执行具体的业务逻辑,如查询数据库、生成 HTML 页面等操作,然后返回响应。例如,在一个 Web 应用中,目标处理程序可能是一个 Servlet,它根据请求中的参数从数据库中获取数据,然后生成包含数据的 HTML 页面作为响应。
  • 过滤器链(Filter Chain):
    过滤器链用于管理和组织多个过滤器,它决定了过滤器的执行顺序。当一个请求进入系统时,它会按照过滤器链中定义的顺序依次通过各个过滤器,每个过滤器都可以对请求进行操作,然后再传递给下一个过滤器或者目标处理程序。过滤器链可以是一个简单的线性结构,也可以根据不同的请求类型或者其他条件动态地调整过滤器的顺序。
  • 客户端(Client):
    客户端是发起请求的实体,它可以是一个浏览器、一个移动应用或者其他软件系统。客户端发送请求到过滤器链的第一个过滤器,然后等待接收经过处理后的响应。

工作原理

客户端发起请求,请求首先到达过滤器链中的第一个过滤器。第一个过滤器对请求进行预处理,例如检查请求的合法性、记录请求日志等操作。如果请求满足该过滤器的要求,过滤器会调用过滤器链的doFilter()方法,将请求传递给下一个过滤器(如果有)。这个过程会在过滤器链中依次进行,每个过滤器都可以对请求进行检查、修改或者添加信息等操作。当请求通过所有的过滤器后,它会到达目标处理程序。目标处理程序执行具体的业务逻辑,生成响应。响应会沿着相反的方向通过过滤器链,每个过滤器可以对响应进行后处理,如数据压缩、添加响应头信息等操作。最后,经过处理后的响应返回给客户端。

代码示例(简单的控制台应用模拟)

  • 请求和响应结构体
#include <iostream>
#include <string>
#include <vector>

// 表示请求的结构体
struct Request {
    std::string url;
    std::vector<std::string> parameters;
};

// 表示响应的结构体
struct Response {
    int statusCode;
    std::string body;
};
  • 过滤器接口(Filter)
class Filter {
public:
    virtual void doFilter(Request& request, Response& response, Filter* next) = 0;
};
  • 具体过滤器 - 日志记录过滤器(LoggingFilter)
class LoggingFilter : public Filter {
public:
    void doFilter(Request& request, Response& response, Filter* next) override {
        std::cout << "记录请求日志: " << request.url << std::endl;
        if (next!= nullptr) {
            next->doFilter(request, response, nullptr);
        }
    }
};
  • 具体过滤器 - 身份验证过滤器(AuthenticationFilter)
class AuthenticationFilter : public Filter {
public:
    void doFilter(Request& request, Response& response, Filter* next) override {
        // 简单模拟身份验证,这里假设URL包含"auth"表示已认证
        if (request.url.find("auth")!= std::string::npos) {
            if (next!= nullptr) {
                next->doFilter(request, response, nullptr);
            }
        } else {
            response.statusCode = 401;
            response.body = "未授权访问。";
        }
    }
};
  • 目标处理程序(TargetHandler)
class TargetHandler {
public:
    Response handleRequest(Request& request) {
        Response response;
        response.statusCode = 200;
        response.body = "已处理请求: " + request.url;
        return response;
    }
};
  • 过滤器链(FilterChain)
class FilterChain {
private:
    std::vector<Filter*> filters;
    int currentIndex = 0;
    TargetHandler targetHandler;

public:
    void addFilter(Filter* filter) {
        filters.push_back(filter);
    }

    void doFilter(Request& request, Response& response) {
        if (currentIndex < filters.size()) {
            Filter* currentFilter = filters[currentIndex];
            currentFilter->doFilter(request, response, this);
            currentIndex++;
        } else {
            response = targetHandler.handleRequest(request);
        }
    }
};
  • 客户端使用示例(模拟)
int main() {
    FilterChain chain;
    LoggingFilter loggingFilter;
    AuthenticationFilter authenticationFilter;

    chain.addFilter(&loggingFilter);
    chain.addFilter(&authenticationFilter);

    Request request;
    request.url = "auth/somepage";
    Response response;
    chain.doFilter(request, response);

    std::cout << "响应状态码: " << response.statusCode << std::endl;
    std::cout << "响应内容: " << response.body << std::endl;

    Request unauthorizedRequest;
    unauthorizedRequest.url = "somepage";
    Response unauthorizedResponse;
    chain.doFilter(unauthorizedRequest, unauthorizedResponse);

    std::cout << "未授权响应状态码: " << unauthorizedResponse.statusCode << std::endl;
    std::cout << "未授权响应内容: " << unauthorizedResponse.body << std::endl;

    return 0;
}

优点

  • 分离关注点:
    通过将不同的处理功能(如日志记录、身份验证等)封装到不同的过滤器中,使得每个功能模块的职责更加清晰,便于维护和扩展。例如,在一个大型的 Web 应用中,可以方便地添加、删除或者修改某个过滤器,而不会影响到其他功能模块。
  • 可复用性高:
    过滤器可以在不同的请求处理场景中复用。例如,日志记录过滤器可以用于所有的请求处理流程,只需要将其添加到过滤器链中即可。这提高了代码的复用性,减少了重复代码的编写。
  • 灵活性和可配置性:
    可以根据不同的应用需求灵活地配置过滤器链,包括过滤器的顺序、是否启用某个过滤器等。例如,在开发环境中,可以启用详细的日志记录过滤器,而在生产环境中可以禁用或者调整日志记录的级别。

缺点

  • 增加系统复杂度:
    引入多个过滤器和过滤器链会增加系统的层次结构和复杂度。对于简单的应用来说,可能会显得过于复杂,并且在理解和调试请求处理流程时会增加难度。例如,在一个小型的命令行工具中,使用拦截过滤器模式可能会使代码变得臃肿。
  • 性能开销:
    每个过滤器都需要对请求和响应进行处理,这可能会引入一定的性能开销,尤其是在高并发的应用场景下。如果过滤器的处理逻辑比较复杂或者过滤器数量较多,可能会导致响应时间延长。因此,在设计过滤器时,需要注意优化其性能,避免不必要的操作。

http://www.kler.cn/a/409182.html

相关文章:

  • 【大数据学习 | Spark-Core】Spark提交及运行流程
  • 用CAXA CAD电子图板导入图框、标题栏并导出pdf的方法
  • android-sdk 安装脚本
  • 调试器 gdb/cgdb 的使用
  • 三十一、构建完善微服务——API 网关
  • apache、iis屏蔽限制ip访问(适用虚拟主机)
  • ISAAC Gym 7. 使用箭头进行数据可视化
  • 伪数组和真数组
  • java Scanner
  • 【PHP】 环境以及插件的配置,自学笔记(一)
  • 【Ubuntu24.04】服务部署(虚拟机)
  • 微信万能门店小程序系统存在任意文件读取漏洞
  • 中标麒麟部署k8sV1.31版本详细步骤
  • 5.最长回文子串 python
  • Diffusion 和Stable Diffusion的数学和工作原理详细解释
  • 【君正T31开发记录】8.了解rtsp协议及设计模式
  • golang学习6-指针
  • 探索智能时代:从AI生成PPT到自动化未来
  • 【Elasticsearch入门到落地】2、正向索引和倒排索引
  • C++自动化测试:GTest 与 GitLab CI/CD 的完美融合
  • 如何做鸿蒙系统里的App开发需要哪些技术栈
  • Node.js 安装与环境配置详解:从入门到实战
  • 数据结构(顺序队列——c语言实现)
  • pytorch torch.sign() 方法介绍
  • CTF之密码学(培根密码)
  • SpringBoot集成多个rabbitmq