8 -- 深入使用Spring -- 1...4 重写占位符配置器

本文介绍如何使用Spring的PropertyOverrideConfigurer重写容器中的Bean属性。通过指定属性文件,可直接覆盖XML配置文件中的Bean属性值。

      8.1.5 重写占位符配置器 (PropertyOverrideConfigurer)

        PropertyOverrideConfigurer是Spring提供的另一个容器后处理器。PropertyOverrideConfigurer的属性文件指定的信息可以直接覆盖Spring配置文件中的元数据。 

        使用PropertyOverrideConfigurer的属性文件,每条属性应保持如下格式:beanId.property = value

        beanId 是属性占位符试图覆盖的Bean的id,Property是试图覆盖的属性名(对应于调用setter方法)。

        XML : 

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
        <property name="locations">
            <list>
                <value>dbconn.properties</value>
                <!-- 如果有多个属性文件,依次在下面列出来 -->
                <!-- <value>wawa.properties</value> -->
            </list>
        </property>
    </bean>
    
    <!-- 对于采用基于XML Schema的配置文件而言,如果导入了context:命名空间,则可采用如下方式来配置该属性占位符 -->
    <!-- <context:property-override location="classpath:wawa.properties"/> -->

    <!-- 定义数据源Bean,使用C3P0数据源实现 -->
    <!-- 配置该Bean时没有指定任何信息,但Properties文件里的信息将会直接覆盖该Bean的属性值。 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
    </bean>

</beans>

        Properties : 

dataSource.jdbc.driverClassName=com.mysql.jdbc.Driver
dataSource.jdbc.url=jdbc:mysql://localhost:3306/spring
dataSource.jdbc.username=root
dataSource.jdbc.password=system

        由于PropertyOverrideConfigurer容器后处理器,Spring容器使用ApplicationContext作为容器时,容器会自动检测容器后处理器,并使用该容器后处理器来处理Spring容器。

        beanId必须是容器中真是存在的Bean的id,否则程序将出错。

        如果有多个PropertyOverrideConfigurer对同一个Bean属性进行了覆盖,最后一次覆盖将会获胜。

      啦啦啦

 

`spring.cloud.gateway.routes.filters` 是 Spring Cloud Gateway 中用于配置 **局部过滤器(GatewayFilter)** 的关键部分,这些过滤器作用于特定路由,在请求被转发前或响应返回客户端前执行逻辑,如修改请求头、路径重写、限流、熔断等。 --- ## ✅ 过滤器分类 Spring Cloud Gateway 的过滤器分为两类: | 类型 | 说明 | |------|------| | **局部过滤器(Per-Route Filters)** | 配置在 `routes.filters` 下,仅对当前路由生效。 | | **全局过滤器(Global Filters)** | 实现 `GlobalFilter` 接口并注册为 Bean,对所有路由生效。 | 本文重点讲解 **`routes.filters` 的详细配置方式和常用内置过滤器用法**。 --- ## 🧩 常见过滤器完整配置示例(YAML) ```yaml spring: cloud: gateway: routes: - id: user-service-route uri: lb://user-service predicates: - Path=/api/users/** filters: # ----------------------------------------- # 1. StripPrefix: 去掉路径前缀 # /api/users/list → /users/list → 转发到 /list # ----------------------------------------- - StripPrefix=2 # ----------------------------------------- # 2. RewritePath: 正则重写路径 # 将 /api/(?<segment>.*) 重写为 /$\{segment} # 注意:$ 要转义为 $\,否则 YAML 解析失败 # ----------------------------------------- - RewritePath=/api/(?<segment>.*), /$\{segment} # ----------------------------------------- # 3. AddRequestHeader: 添加请求头 # ----------------------------------------- - AddRequestHeader=X-Request-Start, ${time_now} - AddRequestHeader=Authorization, Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... # ----------------------------------------- # 4. AddRequestParameter: 添加查询参数 # 请求变成 ?source=gateway&origin=proxy # ----------------------------------------- - AddRequestParameter=source, gateway - AddRequestParameter=origin, proxy # ----------------------------------------- # 5. AddResponseHeader: 添加响应头 # ----------------------------------------- - AddResponseHeader=X-Content-Source, gateway - AddResponseHeader=Access-Control-Allow-Origin, "*" # ----------------------------------------- # 6. PrefixPath: 在路径前添加前缀 # /users → /internal/users # ----------------------------------------- - PrefixPath=/internal # ----------------------------------------- # 7. SetPath: 设置新路径(支持占位符) # 如 /users/123 → /profiles/${segment}/info # ----------------------------------------- - SetPath=/{segment}/info # ----------------------------------------- # 8. SetStatus: 修改响应状态码 # ----------------------------------------- - SetStatus=200 # ----------------------------------------- # 9. RedirectTo: 重定向(需配合 no://op 使用) # ----------------------------------------- - RedirectTo=302, /login-new # ----------------------------------------- # 10. RemoveRequestHeader: 移除请求头(防泄漏) # ----------------------------------------- - RemoveRequestHeader=Proxy-Authorization - RemoveRequestHeader=Cookie # ----------------------------------------- # 11. DedupeResponseHeader: 去重响应头 # RETAIN_FIRST: 保留第一个;RETAIN_LAST: 保留最后一个 # ----------------------------------------- - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_FIRST # ----------------------------------------- # 12. RequestRateLimiter: 请求频率限制(基于 Redis + Lua) # key-resolver 必须是一个 SpEL 表达式引用的 Bean # ----------------------------------------- - Name: RequestRateLimiter Args: key-resolver: "#{@ipKeyResolver}" # 引用名为 ipKeyResolver 的 Bean redis-rate-limiter.replenishRate: 10 # 每秒补充 10 个令牌(稳定速率) redis-rate-limiter.burstCapacity: 20 # 最大突发请求数(峰值容量) # ----------------------------------------- # 13. CircuitBreaker: 熔断降级(集成 Resilience4j 或 Hystrix) # 当服务不可用时跳转到本地 fallback 页面或接口 # ----------------------------------------- - Name: CircuitBreaker Args: name: productCircuitBreaker # 断路器名称 fallbackUri: forward:/fallback/products # 熔断时调用本应用内的 fallback 接口 # ----------------------------------------- # 14. Hystrix (旧版): 已弃用,推荐使用 Resilience4j # ----------------------------------------- # - Name: Hystrix # Args: # name: fallbackCmd # fallbackUri: forward:/fallback/hystrix # ----------------------------------------- # 15. SecureHeaders: 添加安全响应头(OWASP 建议) # 自动添加 Content-Security-Policy 等 # ----------------------------------------- - SecureHeaders: # ----------------------------------------- # 16. SaveSession: 触发 Session 存储(用于 OAuth2 登录等场景) # ----------------------------------------- - SaveSession # ----------------------------------------- # 17. SetResponseHeader: 替换已有响应头(与 Add 不同) # 若已存在则覆盖 # ----------------------------------------- - SetResponseHeader=Cache-Control, no-cache # ----------------------------------------- # 18. Retry: 请求失败自动重试 # ----------------------------------------- - Name: Retry Args: retries: 3 # 最多重试 3 次 statuses: BAD_GATEWAY # 对哪些状态码重试 methods: GET, POST # 只对指定方法重试 backoff: firstBackoff: 100ms # 第一次延迟 maxBackoff: 500ms # 最大延迟 factor: 2 # 指数退避因子 basedOnPreviousValue: false # 是否基于上次时间计算 # ----------------------------------------- # 19. ModifyRequestBody: 修改请求体(需 Java 编码实现) # ----------------------------------------- # ❌ 不支持 YAML 配置,必须通过代码方式添加 # ----------------------------------------- # 20. ModifyResponseBody: 修改响应体 # ----------------------------------------- # ❌ 同样只能通过 Java 代码实现 ``` --- ## 🔧 内置过滤器详解(按功能划分) ### 1️⃣ 路径操作类 | 过滤器 | 说明 | |-------|------| | `StripPrefix=n` | 去掉前 n 层路径,例如 `/api/users/list` → `/list` | | `RewritePath` | 使用正则表达式重写路径,灵活性高 | | `PrefixPath` | 给路径加前缀,例如 `/users` → `/internal/users` | | `SetPath` | 完全设置新的路径,支持变量 `{segment}` | --- ### 2️⃣ 请求/响应头操作类 | 过滤器 | 说明 | |-------|------| | `AddRequestHeader` | 添加新的请求头 | | `AddResponseHeader` | 添加新的响应头 | | `SetResponseHeader` | 设置响应头(覆盖已有的) | | `RemoveRequestHeader` | 删除敏感请求头(如 Cookie、Proxy-Authorization) | --- ### 3️⃣ 参数操作类 | 过滤器 | 说明 | |-------|------| | `AddRequestParameter` | 添加查询参数 | --- ### 4️⃣ 流控与容错类 | 过滤器 | 说明 | |-------|------| | `RequestRateLimiter` | 基于 Redis 的限流,防止接口被刷 | | `CircuitBreaker` | 熔断机制,服务异常时降级处理 | | `Retry` | 自动重试失败请求(适用于幂等接口) | --- ### 5️⃣ 安全与会话类 | 过滤器 | 说明 | |-------|------| | `SecureHeaders` | 自动添加 OWASP 推荐的安全响应头 | | `SaveSession` | 显式保存 WebSession,常用于 OAuth2 登录流程中 | --- ### 6️⃣ 控制类 | 过滤器 | 说明 | |-------|------| | `RedirectTo` | 执行 HTTP 重定向 | | `SetStatus` | 修改最终返回的状态码 | | `DedupeResponseHeader` | 去除重复的响应头,避免 CORS 冲突 | --- ## 💡 特殊语法说明 ### ✅ SpEL 表达式引用 Bean ```yaml filters: - Name: RequestRateLimiter Args: key-resolver: "#{@ipKeyResolver}" ``` 表示从 Spring 容器中查找名为 `ipKeyResolver` 的 `KeyResolver` 类型 Bean。 对应的 Java 代码: ```java @Bean public KeyResolver ipKeyResolver() { return exchange -> Mono.just( Objects.requireNonNull(exchange.getRequest().getRemoteAddress()) .getAddress().getHostAddress() ); } ``` --- ### ✅ 多行写法(更清晰) ```yaml filters: - name: RewritePath args: regexp: "/api/(?<segment>.*)" replacement: "/${segment}" ``` 这种格式比单行更易读,尤其适合复杂参数。 --- ## ⚠️ 注意事项 1. **顺序很重要** - 过滤器按照配置顺序执行,例如先 `StripPrefix` 再 `AddRequestHeader`。 2. **`RewritePath` 中 `$` 必须转义为 `$\`** - 因为 YAML 会解析 `${}`,所以要用 `$\{path}` 来防止冲突。 3. **某些过滤器只能通过 Java 配置** - 如 `ModifyRequestBody` 和 `ModifyResponseBody`,无法直接在 YAML 中使用4. **性能影响** - 频繁使用 `RequestRateLimiter` 或 `CircuitBreaker` 会增加 Redis 调用开销,注意压测验证。 5. **日志调试** - 开启 DEBUG 日志查看过滤器执行过程: ```yaml logging: level: org.springframework.cloud.gateway: DEBUG ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值