Hướng dẫn Java Design Pattern – Intercepting Filter

1. Intercepting Filter Pattern là gì?

Intercepting filter pattern là một Java EE pattern, được sử dụng khi muốn thực hiện một vài xử lý trước (pre-processing) khi request được ứng dụng đích (target) xử lý hoặc sau (post-processing) khi response được trả về từ target.

Các Filter được định nghĩa và áp dụng trên yêu cầu (request) khi chuyển request đến ứng dụng đích thực tế (target). Các Filter có thể thực hiện xác thực (authentication), ủy quyền (authorization), nén dữ liệu (compressing), ghi nhật ký (logging) hoặc theo dõi yêu cầu (tracking) và sau đó chuyển yêu cầu đến các trình xử lý tương ứng.

Các Filter được thực thi một cách trong suốt, phía client và target không hề biết sự tồn tại của nó.

2. Cài đặt Intercepting Filter Pattern như thế nào?

Các thành phần tham gia mẫu Intercepting filter pattern:

  • Filter : chịu trách nhiệm thực hiện một vài xử lý trước khi request được target xử lý hoặc sau khi response được trả về từ target.
  • Target : là một đối tượng xử lý lý chính, một trình xử lý yêu cầu.
  • Filter chain : chứa một chuỗi các Filter sẽ được thực hiện trên target theo thứ tự được xác định.
  • Filter manager : quản lý các Filter và Filter Chain.
  • Client : đối tượng gửi request đến target hoặc nhận response từ target.

2.1. Ví dụ sử dụng Intercepting Filter Pattern

Giả sử chúng ta có một ứng dụng cần ghi log, xác thực tất cả request đến hệ thống trước khi target xử lý. Chương trình của chúng ta như sau:

HttpRequest.java

package com.maixuanviet.patterns.other.filter;
 
import lombok.Data;
 
@Data
public class HttpRequest {
 
    private String clientIp;
    private String targetUrl;
}

Filter.java

package com.maixuanviet.patterns.other.filter;
 
public interface Filter {
    void doFilter(HttpRequest request);
}

TrackingFilter.java

package com.maixuanviet.patterns.other.filter;
 
public class TrackingFilter implements Filter {
 
    @Override
    public void doFilter(HttpRequest request) {
        System.out.println("Tracking request: " + request);
    }
}

AuthenticationFilter.java

package com.maixuanviet.patterns.other.filter;
 
public class AuthenticationFilter implements Filter {
 
    @Override
    public void doFilter(HttpRequest request) {
        System.out.println("Authenticating request: " + request);
    }
}

Target.java

package com.maixuanviet.patterns.other.filter;
 
public class Target {
 
    public void execute(HttpRequest request) {
        System.out.println("Executing request: " + request);
    }
}

FilterChain.java

package com.maixuanviet.patterns.other.filter;
 
import java.util.ArrayList;
import java.util.List;
 
public class FilterChain {
 
    private List<Filter> filters = new ArrayList<>();
 
    private Target target;
 
    public void addFilter(Filter filter) {
        filters.add(filter);
    }
 
    public void doFilter(HttpRequest request) {
        // Do some pre-processing
        for (Filter filter : filters) {
            filter.doFilter(request);
        }
 
        // Execute actual processing by target
        target.execute(request);
 
        // Do some pos-processing
    }
 
    public void setTarget(Target target) {
        this.target = target;
    }
}

FilterManager.java

package com.maixuanviet.patterns.other.filter;
 
public class FilterManager {
 
    private FilterChain filterChain;
 
    public FilterManager(Target target) {
        filterChain = new FilterChain();
        filterChain.setTarget(target);
    }
 
    public void addFilter(Filter filter) {
        filterChain.addFilter(filter);
    }
 
    public void filterRequest(HttpRequest request) {
        filterChain.doFilter(request);
    }
}

Client.java

package com.maixuanviet.patterns.other.filter;
 
public class Client {
 
    private FilterManager filterManager;
 
    public Client(FilterManager filterManager) {
        this.filterManager = filterManager;
    }
 
    public void sendRequest(HttpRequest request) {
        filterManager.filterRequest(request);
    }
}

InterceptingFilterPatternExample.java

package com.maixuanviet.patterns.other.filter;
 
public class InterceptingFilterPatternExample {
 
    public static void main(String[] args) {
        FilterManager filterManager = new FilterManager(new Target());
        filterManager.addFilter(new TrackingFilter());
        filterManager.addFilter(new AuthenticationFilter());
 
        HttpRequest request = new HttpRequest();
        request.setClientIp("127.0.0.1");
        request.setTargetUrl("/home");
 
        Client client = new Client(filterManager);
        client.sendRequest(request);
    }
}

Output của chương trình:

Tracking request: HttpRequest(clientIp=127.0.0.1, targetUrl=/home)
Authenticating request: HttpRequest(clientIp=127.0.0.1, targetUrl=/home)
Executing request: HttpRequest(clientIp=127.0.0.1, targetUrl=/home)

3. Lợi ích của Intercepting Filter Pattern là gì?

  • Có thể thêm một vài xử lý trước hoặc sau khi request, response được target xử lý thực sự.
  • Giảm kết dính giữa các thành phần trong ứng dụng, mỗi filter chịu trách nhiệm một phần riêng.
  • Tăng khả năng tái sử dụng lại.
  • Dễ dàng thêm/ bớt filter mà không ảnh hưởng đến Business Logic.

Related posts:

Check If a File or Directory Exists in Java
Spring Boot - Zuul Proxy Server and Routing
Thực thi nhiều tác vụ cùng lúc như thế nào trong Java?
String Operations with Java Streams
A Quick Guide to Spring Cloud Consul
New Features in Java 15
Spring Security Login Page with React
Cài đặt và sử dụng Swagger UI
Inheritance with Jackson
Quick Guide on Loading Initial Data with Spring Boot
Java Program to Implement LinkedHashSet API
Java Program to Repeatedly Search the Same Text (such as Bible by building a Data Structure)
Java Streams vs Vavr Streams
Java Program to find the maximum subarray sum O(n^2) time(naive method)
Java Program to Test Using DFS Whether a Directed Graph is Weakly Connected or Not
Server-Sent Events in Spring
Quick Guide to @RestClientTest in Spring Boot
Error Handling for REST with Spring
Java Web Services – Jersey JAX-RS – REST và sử dụng REST API testing tools với Postman
Java Program to Check if any Graph is Possible to be Constructed for a Given Degree Sequence
Tính kế thừa (Inheritance) trong java
Spring Boot Gradle Plugin
Spring Boot with Multiple SQL Import Files
Convert Character Array to String in Java
Guide to UUID in Java
Java NIO2 Path API
Java Program to Find Nearest Neighbor for Dynamic Data Set
Hướng dẫn Java Design Pattern – Iterator
Java Program to Generate a Graph for a Given Fixed Degree Sequence
Hướng dẫn sử dụng luồng vào ra nhị phân trong Java
Java Program to Implement Strassen Algorithm
Java Program to Decode a Message Encoded Using Playfair Cipher