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

Apache Camel REST接口缺失application/json Accept头报错排查

问题根因

异常由两个配置的组合逻辑触发:

  • 你在全局REST配置中使用了RestBindingMode.auto,该模式下Apache Camel会根据请求的Accept头自动选择响应序列化方式,当Accept头未携带application/json时,Camel不会自动触发Jackson的JSON序列化流程。
  • 接口上配置的.produces(MediaType.APPLICATION_JSON_VALUE)仅用于声明接口支持的响应类型,不会强制所有响应走JSON序列化。当Accept头不匹配时,Camel会尝试直接输出原始HouseJava对象,在后续响应写出阶段触发流操作异常,最终返回200状态码的空响应体,抛出日志里的java.io.IOException: Stream closed错误。

另外BaseRoute中手动实例化AnnotationConfigApplicationContext的代码是冗余的,Spring Boot会自动托管应用上下文,这段代码会造成不必要的重复上下文初始化,建议直接删除。

修复方案

二选一即可,优先选第一种,逻辑最简单最稳定。

方案1:全局强制JSON序列化(推荐)

将全局REST配置的绑定模式从auto改为json,强制所有REST接口响应都走JSON序列化逻辑,完全跳过基于Accept头的内容协商流程,无论请求是否携带application/json的Accept属性,都正常返回JSON响应。
修改后的BaseRoute代码:

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;

/**
 * 8080端口路由全局配置
 */
@Component
public class BaseRoute extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        restConfiguration()
                .component("servlet")
                .host("localhost").port(8080)
                // 替换原有的auto模式,强制JSON绑定
                .bindingMode(RestBindingMode.json);
    }
}

方案2:关闭严格请求校验+接口兜底JSON头

如果你需要保留auto绑定模式适配其他接口,可以关闭Camel REST的严格客户端请求校验,同时在接口中显式设置响应Content-Type兜底,当Accept头缺失或不匹配时默认返回JSON。
首先修改BaseRoute全局配置:

@Override
public void configure() throws Exception {
    restConfiguration()
            .component("servlet")
            .host("localhost").port(8080)
            .bindingMode(RestBindingMode.auto)
            // 关闭严格的Accept/Content-Type头校验
            .clientRequestValidation(false);
}

再修改HouseRoute的业务处理逻辑,显式设置响应头:

@Override
public void configure() throws Exception {
    rest(getRoute())
            .get()
                .produces(MediaType.APPLICATION_JSON_VALUE)
                .route()
                .process(exchange -> {
                    exchange.getMessage().setBody(house);
                    // 显式指定响应类型为JSON,避免内容协商失败
                    exchange.getMessage().setHeader("Content-Type", "application/json");
                })
                .endRest();
}
验证

修改完成后重启应用,发送不带Accept: application/json请求头的GET请求到/house/接口,即可正常返回序列化后的House对象JSON数据,不会再抛出流关闭异常,也不会返回空响应体。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 22:30:57