You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将GlobalFilter中的自定义对象传递至Spring WebFlux控制器?

问题原因与解决方案

情况1:控制器属于Spring Cloud Gateway自身

你的代码逻辑本身没问题,但大概率是GlobalFilter的执行顺序导致过滤器在控制器之后运行,属性还未存入就进入了控制器处理流程。

修复步骤:

  • 给GlobalFilter指定优先级,确保它在请求到达控制器前执行。可通过实现Ordered接口或添加@Order注解设置顺序,数值越小优先级越高。
  • 确保MyCustomObject类具备基础的getter/setter方法(可通过Lombok的@Data注解简化)。

示例代码:

GlobalFilter实现(带优先级):

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        MyCustomObject obj = new MyCustomObject();
        obj.setSomeField("test value");
        // 存入ServerWebExchange属性
        exchange.getAttributes().put("MyObject", obj);
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        // 设置比默认请求处理过滤器更高的优先级
        return Ordered.HIGHEST_PRECEDENCE + 10;
    }
}

网关内部控制器:

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;

@RestController
public class GatewayController {

    @GetMapping("/test")
    public ResponseEntity<String> getSomething(ServerWebExchange exchange) {
        MyCustomObject obj = exchange.getAttribute("MyObject");
        if (obj != null) {
            return ResponseEntity.ok("获取到对象:" + obj.getSomeField());
        }
        return ResponseEntity.badRequest().body("未获取到对象");
    }
}

情况2:控制器属于下游业务服务

网关的ServerWebExchange与下游服务的ServerWebExchange是完全独立的实例,无法直接共享内存中的对象。此时需要通过HTTP请求头或请求参数将对象信息传递给下游服务。

方案:将对象序列化为JSON存入请求头,下游解析

网关GlobalFilter代码:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {

    private final ObjectMapper objectMapper;

    // 注入Jackson序列化工具
    public CustomGlobalFilter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        try {
            MyCustomObject obj = new MyCustomObject();
            obj.setSomeField("downstream test");
            // 将对象序列化为JSON字符串
            String objJson = objectMapper.writeValueAsString(obj);
            // 添加到请求头,注意头名称符合HTTP规范
            exchange.getRequest().mutate()
                    .header("X-Custom-Object", objJson)
                    .build();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        // 确保在路由转发前执行
        return Ordered.HIGHEST_PRECEDENCE + 10;
    }
}

下游服务控制器代码:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DownstreamController {

    private final ObjectMapper objectMapper;

    public DownstreamController(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @GetMapping("/downstream-test")
    public ResponseEntity<String> getSomething(@RequestHeader("X-Custom-Object") String objJson) {
        try {
            // 将JSON字符串反序列化为自定义对象
            MyCustomObject obj = objectMapper.readValue(objJson, MyCustomObject.class);
            return ResponseEntity.ok("下游获取到对象:" + obj.getSomeField());
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.badRequest().body("解析对象失败");
        }
    }
}

注意事项:

  • 若自定义对象体积较大,不建议用请求头传递(HTTP头存在大小限制),可改用分布式缓存(如Redis)存储对象,将缓存Key通过请求头传递给下游服务,下游根据Key从缓存获取。
  • MyCustomObject类需保证可序列化,可通过Lombok的@Data、@NoArgsConstructor注解快速生成必要方法。

内容的提问来源于stack exchange,提问作者Akshay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 14:06:25