Spring Gateway响应转换过滤器报错:不支持application/json转JsonNode
Spring Gateway响应转换过滤器媒体类型不支持问题解决
问题场景
使用Spring Gateway构建代理服务,编写了响应转换过滤器,但运行时抛出媒体类型不支持的错误。
过滤器代码
import com.fasterxml.jackson.databind.JsonNode; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @Slf4j @Component public class ResponseTransformationGatewayFilterFactory extends AbstractGatewayFilterFactory<ResponseTransformationGatewayFilterFactory.Config> { public ResponseTransformationGatewayFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { ModifyResponseBodyGatewayFilterFactory.Config modifyConfig = new ModifyResponseBodyGatewayFilterFactory.Config(); // used string.class but same issue modifyConfig.setRewriteFunction(JsonNode.class, JsonNode.class, (exchange, originalResponseBody) -> { // Transform the response body JsonNode transformedBody = transformResponseBody(originalResponseBody); return Mono.just(transformedBody); }); return new ModifyResponseBodyGatewayFilterFactory(new ArrayList<>(), new HashSet<>(), new HashSet<>()).apply(modifyConfig); } private JsonNode transformResponseBody(JsonNode originalBody) { // we can get rid of fields here. return JsonResponseFilter.filter(originalBody, List.of("options")); // only add options with included providers } public static class Config { } }
报错信息
org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/json' not supported for bodyType=com.fasterxml.jackson.databind.JsonNode at org.springframework.web.reactive.function.BodyExtractors.readWithMessageReaders(BodyExtractors.java:205) ~[spring-webflux-6.0.12.jar:6.0.12] Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): *__checkpoint ⇢ Body from UNKNOWN [DefaultClientResponse]
解决方法
1. 依赖注入ModifyResponseBodyGatewayFilterFactory
你手动实例化ModifyResponseBodyGatewayFilterFactory时,传入的空集合导致它无法加载默认的消息转换器(比如Jackson的JSON转换器)。正确的做法是让Spring容器管理这个工厂类,通过构造注入获取实例:
修改后的过滤器代码:
import com.fasterxml.jackson.databind.JsonNode; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; import java.util.List; @Slf4j @Component public class ResponseTransformationGatewayFilterFactory extends AbstractGatewayFilterFactory<ResponseTransformationGatewayFilterFactory.Config> { private final ModifyResponseBodyGatewayFilterFactory modifyResponseBodyFilterFactory; // 构造注入Spring容器管理的工厂实例 public ResponseTransformationGatewayFilterFactory(ModifyResponseBodyGatewayFilterFactory modifyResponseBodyFilterFactory) { super(Config.class); this.modifyResponseBodyFilterFactory = modifyResponseBodyFilterFactory; } @Override public GatewayFilter apply(Config config) { ModifyResponseBodyGatewayFilterFactory.Config modifyConfig = new ModifyResponseBodyGatewayFilterFactory.Config(); modifyConfig.setRewriteFunction(JsonNode.class, JsonNode.class, (exchange, originalResponseBody) -> { JsonNode transformedBody = transformResponseBody(originalResponseBody); return Mono.just(transformedBody); }); // 使用注入的工厂类创建过滤器 return modifyResponseBodyFilterFactory.apply(modifyConfig); } private JsonNode transformResponseBody(JsonNode originalBody) { return JsonResponseFilter.filter(originalBody, List.of("options")); } public static class Config { } }
2. 确保Jackson依赖存在
检查项目依赖,确保jackson-databind和spring-boot-starter-webflux已经引入(Spring Gateway默认依赖webflux,通常会自动引入Jackson,但如果缺失需要手动添加):
Maven依赖示例:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
3. 可选:显式指定支持的媒体类型
如果仍有问题,可以在配置中显式指定支持的媒体类型,确保过滤器只处理JSON格式的响应:
import org.springframework.http.MediaType; import java.util.List; // 在apply方法中添加 modifyConfig.setSupportedMediaTypes(List.of(MediaType.APPLICATION_JSON));
原因说明
手动创建ModifyResponseBodyGatewayFilterFactory实例时,传入的空messageReaders、messageWriters集合会导致工厂无法加载Spring默认配置的JSON消息转换器,因此无法将application/json类型的响应体转换为JsonNode对象。通过依赖注入获取的工厂实例会自动加载这些转换器,从而解决媒体类型不支持的问题。
内容的提问来源于stack exchange,提问作者Lakshya
相关产品推荐
相关产品推荐

