# filter
**Repository Path**: gzcltech/filter
## Basic Information
- **Project Name**: filter
- **Description**: No description available
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-07-17
- **Last Updated**: 2026-10-03
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# filter
从 Spring Framework / Spring Security 中抽取的过滤器链骨架(Servlet + WebFlux),类名与官方刻意区分,可独立引入、不依赖完整 `spring-security-*` 栈。
**参考版本(源码对照移植):**
| 项目 | 版本 |
|---|---|
| Spring Security | **7.0.5**(`spring-security-web` 等) |
| Spring Framework | **7.0.8** |
| Spring Boot | **4.0.7**(starter / 示例) |
上述版本与父 POM 属性 `spring-security.version` / `spring.version` / `spring-boot.version` 一致。
## 模块
| 模块 | 说明 |
|---|---|
| `filter-context` | `FilterContext` / `FilterContextHolder`(无 Reactor 依赖;Servlet / WebFlux 共享) |
| `filter-servlet` | Servlet 核心实现(含 `RequestIdFilter`、`HttpLoggingFilter`、`TraceIdFilter`、`FilterContextHolderFilter` 等),依赖 `jakarta.servlet-api`(provided) |
| `filter-servlet-tracing-slf4j` | `Slf4jTraceIdFilter`:将 Trace/Span 绑定到 SLF4J MDC(可选依赖) |
| `filter-servlet-tracing-log4j2` | `Log4j2TraceIdFilter`:将 Trace/Span 绑定到 Log4j2 ThreadContext(可选依赖) |
| `filter-spring` | Spring 桥接 + `HttpFilterChainBuilder` DSL(类比 `HttpSecurity`);含 `HttpLoggingFilterFactory` |
| `filter-spring-boot-starter` | Servlet 自动配置:prototype builder、收集 `MatchedFilterChain`、组装 `FilterChainRouter`、注册 `DelegateFilterProxy`;绑定 Properties 并注册 `HttpLoggingFilterFactory` bean |
| `filter-webflux` | WebFlux 核心(含 `RequestIdWebFilter`、`HttpLoggingWebFilter`、`TraceIdWebFilter`、`HttpLoggingWebFilterFactory`)+ `ServerHttpFilterChainBuilder` DSL(类比 `ServerHttpSecurity`) |
| `filter-webflux-tracing-slf4j` | `Slf4jTraceIdWebFilter`:将 Trace/Span 绑定到 SLF4J MDC(可选依赖;WebFlux 下为尽力而为) |
| `filter-webflux-tracing-log4j2` | `Log4j2TraceIdWebFilter`:将 Trace/Span 绑定到 Log4j2 ThreadContext(可选依赖;WebFlux 下为尽力而为) |
| `filter-webflux-spring-boot-starter` | Reactive 自动配置:prototype builder、收集 `MatchedWebFilterChain`、注册 `WebFilterChainRouter`;绑定 Properties 并注册 `HttpLoggingWebFilterFactory` bean |
| `example-filter` | Spring Boot Servlet 完整示例(不发布到 Maven Central) |
| `example-reactive-filter` | Spring Boot WebFlux 完整示例(不发布到 Maven Central) |
### Spring Boot 用法
```xml
io.gitee.gzcltech.filter
filter-spring-boot-starter
${filter.version}
```
注入 prototype `HttpFilterChainBuilder`(类比 `HttpSecurity`)声明链,starter 自动挂到容器:
```java
import io.gitee.gzcltech.filter.web.logging.HttpLoggingFilterFactory;
@Bean
@Order(1)
MatchedFilterChain apiChain(HttpFilterChainBuilder http, HttpLoggingFilterFactory loggingFilterFactory) {
return http
.securityMatcher("/api/**")
.addFilter(new RequestIdFilter())
.addFilter(loggingFilterFactory.create()) // 或 addFilterAfter(loggingFilterFactory.create(), RequestIdFilter.class)
.build();
}
```
仍可直接返回 `DefaultMatchedFilterChain`。配置前缀:`gzcltech.filter.*`(`enabled` / `filter-name` / `url-patterns` / `order`)。请求日志另见 `gzcltech.filter.logging.*`(`include-patterns` / `exclude-patterns` / `body-include-patterns` / `body-exclude-patterns` / `max-body-bytes`);`HttpLoggingFilterFactory` 定义在 `filter-spring`,starter 注册 bean,由业务 `loggingFilterFactory.create()` 后手动挂链。
`HttpFilterChainBuilder.build()` 默认按 `FilterOrderRegistration` 自动加入 `FilterContextHolderFilter`(可用 `http.disableFilterContextHolder()` 关闭)。
可选显式加入(互斥于 Holder 的自动 save 语义):
```java
.addFilter(new TraceIdFilter()) // 仅传播 Trace/Span;order 120
// 需要日志上下文时改用(二选一):
// .addFilter(new Slf4jTraceIdFilter()) // filter-servlet-tracing-slf4j → SLF4J MDC
// .addFilter(new Log4j2TraceIdFilter()) // filter-servlet-tracing-log4j2 → Log4j2 ThreadContext
.addFilter(loggingFilterFactory.create()) // io.gitee.gzcltech.filter.web.HttpLoggingFilter;order 150
.addFilter(new FilterContextPersistenceFilter(repository)) // 请求结束自动 save+clear;勿与 Holder 同链
.addFilter(HeaderWriterFilter.defaults())
.addFilter(new io.gitee.gzcltech.filter.web.cors.CorsFilter(corsConfigurationSource)) // filter-spring
```
默认 order:`RequestId(100)` → `TraceId(120)` → `AbstractTracingFilter`/`AbstractTracingMdcFilter`(130/140) → `HttpLoggingFilter(150)` → `FilterContextHolder`/`FilterContextPersistence(200)` → `HeaderWriter(300)` → `Cors(400)`。130/140 槽供自定义 tracing 扩展(继承 `AbstractTracing*`)使用。
详见 [`example-filter/README.md`](example-filter/README.md):
```bash
mvn -pl example-filter -am spring-boot:run
```
### Spring Boot WebFlux 用法
```xml
io.gitee.gzcltech.filter
filter-webflux-spring-boot-starter
${filter.version}
```
注入 prototype `ServerHttpFilterChainBuilder`(类比 `ServerHttpSecurity`):
```java
import io.gitee.gzcltech.filter.webflux.logging.HttpLoggingWebFilterFactory;
@Bean
@Order(1)
MatchedWebFilterChain apiChain(ServerHttpFilterChainBuilder http,
HttpLoggingWebFilterFactory loggingWebFilterFactory) {
return http
.securityMatcher("/api/**")
.addFilterAt(new RequestIdWebFilter(), SecurityWebFiltersOrder.REQUEST_ID)
.addFilterAt(loggingWebFilterFactory.create(), SecurityWebFiltersOrder.LOGGING)
.build();
}
```
配置前缀:`gzcltech.filter.webflux.*`(`enabled` / `order`)。请求日志另见 `gzcltech.filter.webflux.logging.*`(字段与 Servlet 侧对称);`HttpLoggingWebFilterFactory` 定义在 `filter-webflux`,starter 注册 bean,由业务 `loggingWebFilterFactory.create()` 后手动挂链。
`ServerHttpFilterChainBuilder.build()` 默认在 `REACTOR_CONTEXT` 槽位自动加入 `FilterContextReactorWebFilter`(可用 `http.disableFilterContextReactor()` 关闭)。
可选显式加入:
```java
.addFilterAt(new TraceIdWebFilter(), SecurityWebFiltersOrder.TRACE_ID)
// 需要日志上下文时改用(二选一):
// .addFilterAt(new Slf4jTraceIdWebFilter(), SecurityWebFiltersOrder.TRACE_ID) // filter-webflux-tracing-slf4j
// .addFilterAt(new Log4j2TraceIdWebFilter(), SecurityWebFiltersOrder.TRACE_ID) // filter-webflux-tracing-log4j2
.addFilterAt(loggingWebFilterFactory.create(), SecurityWebFiltersOrder.LOGGING) // io.gitee.gzcltech.filter.webflux.HttpLoggingWebFilter
.addFilterAt(new FilterContextPersistenceWebFilter(repo), SecurityWebFiltersOrder.REACTOR_CONTEXT) // 勿与 Reactor 同链
.addFilterAt(HttpHeaderWriterWebFilter.defaults(), SecurityWebFiltersOrder.HTTP_HEADERS_WRITER)
.addFilterAt(new CorsWebFilter(corsSource), SecurityWebFiltersOrder.CORS)
```
详见 [`example-reactive-filter/README.md`](example-reactive-filter/README.md):
```bash
mvn -pl example-reactive-filter -am spring-boot:run
```
## Maven 坐标
```xml
io.gitee.gzcltech.filter
filter-servlet
${filter.version}
io.gitee.gzcltech.filter
filter-spring
${filter.version}
io.gitee.gzcltech.filter
filter-webflux
${filter.version}
```
## 与 Spring 官方命名对照
| Spring / Spring Security | 本库 |
|---|---|
| `SecurityFilterChain` | `MatchedFilterChain` |
| `DefaultSecurityFilterChain` | `DefaultMatchedFilterChain` |
| `FilterChainProxy` | `FilterChainRouter` |
| `DelegatingFilterProxy` | `DelegateFilterProxy` |
| `GenericFilterBean` | `ConfigurableFilter` |
| `FilterOrderRegistration` | `FilterOrderRegistration`(公开 API;默认仅注册本库 Filter) |
| `HttpSecurity` | `HttpFilterChainBuilder` |
| `SecurityWebFiltersOrder` | `SecurityWebFiltersOrder`(`FIRST` / `REQUEST_ID` / `TRACE_ID` / `TRACING` / `TRACING_MDC` / `LOGGING` / `REACTOR_CONTEXT` / `HTTP_HEADERS_WRITER` / `CORS` / `LAST`) |
| `ServerHttpSecurity` | `ServerHttpFilterChainBuilder` |
| `SecurityWebFilterChain` | `MatchedWebFilterChain` |
| `MatcherSecurityWebFilterChain` | `DefaultMatchedWebFilterChain` |
| `WebFilterChainProxy` | `WebFilterChainRouter` |
| `SecurityContext` / `SecurityContextHolder` | `FilterContext` / `FilterContextHolder`(`filter-context`;支持 `MODE_THREADLOCAL` / `MODE_INHERITABLETHREADLOCAL`) |
| `DelegatingSecurityContextRunnable` / `Executor` | `DelegatingFilterContextRunnable` / `DelegatingFilterContextExecutor` |
| `ReactiveSecurityContextHolder` | `ReactiveFilterContextHolder`(`filter-webflux`) |
| `SecurityContextHolderFilter` | `FilterContextHolderFilter` |
| `SecurityContextPersistenceFilter` | `FilterContextPersistenceFilter`(行为壳;复用 `FilterContextRepository`) |
| `HeaderWriterFilter` / `HeaderWriter` | `HeaderWriterFilter` / `HeaderWriter`(含常用 Writer + `defaults()`) |
| `org.springframework.web.filter.CorsFilter` | `io.gitee.gzcltech.filter.web.cors.CorsFilter`(`filter-spring`,委托官方实现) |
| `HttpHeaderWriterWebFilter` / `ServerHttpHeadersWriter` | `HttpHeaderWriterWebFilter` / `ServerHttpHeadersWriter`(`filter-webflux`,含 `defaults()`) |
| WebFlux Persistence 行为壳 | `FilterContextPersistenceWebFilter`(复用 `ServerFilterContextRepository`;与 `FilterContextReactorWebFilter` 互斥) |
| `org.springframework.web.cors.reactive.CorsWebFilter` | `io.gitee.gzcltech.filter.webflux.cors.CorsWebFilter` |
| `ReactorContextWebFilter` | `FilterContextReactorWebFilter` |
| `SecurityContextServerWebExchangeWebFilter` | `FilterContextServerWebExchangeWebFilter` |
| `ServerWebExchangeMatcher` 族 | `ServerWebExchangeMatcher` 族(保留) |
| `ServerWebExchangeFirewall` / `StrictServerWebExchangeFirewall` | 同名保留(`firewall` 包) |
**注意:** 包名为 `io.gitee.gzcltech.filter.*`,与官方 `org.springframework.*` 不同。请勿与官方 Spring / Spring Security jar 混用同名 import,避免类冲突与行为混淆。
## 最小用法(Servlet)
组装过滤器链,放入 `ServletContext`,再通过 `DelegateFilterProxy` 挂到容器:
```java
import io.gitee.gzcltech.filter.web.DefaultMatchedFilterChain;
import io.gitee.gzcltech.filter.web.FilterChainRouter;
import io.gitee.gzcltech.filter.web.util.matcher.AntPathRequestMatcher;
import jakarta.servlet.Filter;
FilterChainRouter router = new FilterChainRouter(List.of(
new DefaultMatchedFilterChain(
new AntPathRequestMatcher("/**"),
List.of(myFilter))));
servletContext.setAttribute("gzcltechMatchedFilterChain", router);
// web.xml 或 ServletRegistration 注册 DelegateFilterProxy,filter-name=gzcltechMatchedFilterChain
```
`DelegateFilterProxy` 默认通过 `ServletContextFilterDelegateFactory` 按 filter-name 从 `ServletContext` attribute 解析委托 Filter。Spring 环境可引入 `filter-spring`,使用 `WebApplicationContextFilterDelegateFactory` 按 bean name 解析。
## 许可
Apache License 2.0。部分代码改编自 **Spring Security 7.0.5** / Spring Framework 7.0.8;来源说明见各源文件顶部版权声明及 `resources/META-INF/NOTICE.txt`。