使用Spring AI对接OpenRouter调用DALL-E 3生成图片时,出现HttpMessageConverter不匹配异常
使用Spring AI对接OpenRouter调用DALL-E 3生成图片时,出现HttpMessageConverter不匹配异常
看起来你遇到的问题是Spring AI在解析OpenRouter的响应时“水土不服”——它返回了text/html格式的内容,但Spring AI的OpenAI客户端默认只认application/json格式,导致找不到合适的转换器处理响应。我帮你梳理下问题根源和解决步骤:
问题根源分析
- API端点与格式不匹配:OpenRouter的API路径、响应规则和原生OpenAI有差异,你当前配置的
base-url可能不对,且OpenRouter对请求头有额外要求(比如Referer),如果没满足会返回错误页面(也就是text/html格式的内容)。 - Spring AI默认转换器限制:原生的
MappingJackson2HttpMessageConverter只处理application/json类型的响应,遇到text/html直接“罢工”。 - 模型名称可能有误:OpenRouter上调用DALL-E3需要带厂商前缀,不是单纯的
dall-e-3。
一步步解决问题
1. 修正配置文件(application.properties)
调整Base URL并添加OpenRouter强制要求的请求头:
spring.application.name=ImageGenerator spring.ai.openai.api-key=你的OpenRouter API密钥 # OpenRouter的正确v1版本Base URL spring.ai.openai.base-url=https://openrouter.ai/api/v1 logging.level.org.springframework.ai=DEBUG server.port=8081 # OpenRouter上的DALL-E3模型名称带前缀 spring.ai.openai.image.options.model=openai/dall-e-3 # OpenRouter要求的请求头,测试环境可以填本地地址 spring.ai.openai.image.options.headers[HTTP-Referer]=https://localhost:8081 spring.ai.openai.image.options.headers[X-Title]=ImageGeneratorDemo
2. 自定义RestTemplate处理text/html响应
创建配置类,让转换器能把text/html格式的响应当成JSON解析:
package com.image_generator.ImageGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.client.RestTemplate; import java.util.ArrayList; import java.util.List; @Configuration public class OpenRouterConfig { @Bean public RestTemplate openRouterRestTemplate() { RestTemplate restTemplate = new RestTemplate(); MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); // 给JSON转换器添加text/html的支持 List<MediaType> supportedTypes = new ArrayList<>(jsonConverter.getSupportedMediaTypes()); supportedTypes.add(MediaType.TEXT_HTML); jsonConverter.setSupportedMediaTypes(supportedTypes); // 替换原有的转换器 restTemplate.getMessageConverters().removeIf(c -> c instanceof MappingJackson2HttpMessageConverter); restTemplate.getMessageConverters().add(jsonConverter); return restTemplate; } }
3. 配置适配OpenRouter的Image客户端
用更灵活的OpenAiImageClient替代OpenAiImageModel,注入自定义的RestTemplate:
package com.image_generator.ImageGenerator; import org.springframework.ai.openai.OpenAiImageClient; import org.springframework.ai.openai.OpenAiImageOptions; import org.springframework.ai.openai.api.OpenAiImageApi; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class OpenAiImageConfig { @Value("${spring.ai.openai.api-key}") private String apiKey; @Value("${spring.ai.openai.base-url}") private String baseUrl; @Bean public OpenAiImageApi openAiImageApi(RestTemplate openRouterRestTemplate) { return new OpenAiImageApi(baseUrl, apiKey, openRouterRestTemplate); } @Bean public OpenAiImageClient openAiImageClient(OpenAiImageApi openAiImageApi) { return new OpenAiImageClient(openAiImageApi, OpenAiImageOptions.builder().build()); } }
4. 修改Controller适配新客户端
调整代码使用OpenAiImageClient,同时注意b64_json格式的返回值处理:
package com.image_generator.ImageGenerator; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; import org.springframework.ai.openai.OpenAiImageClient; import org.springframework.ai.openai.OpenAiImageOptions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class AIController { @Autowired private OpenAiImageClient openAiImageClient; @GetMapping("image/{prompt}") public String generateImage(@PathVariable String prompt) { System.out.println("prompt = " + prompt); try { ImageResponse imageResponse = openAiImageClient.call( new ImagePrompt(prompt, OpenAiImageOptions.builder() .responseFormat("b64_json") .model("openai/dall-e-3") .height(1024) .quality("standard") .width(1024) .n(1) .build()) ); // 注意:b64_json格式返回的是base64字符串,不是URL String result = imageResponse.getResult().getOutput().getB64Json(); if (result == null) { result = imageResponse.getResult().getOutput().getUrl(); } System.out.println("生成结果 =========== " + result); return result; } catch (Exception e) { e.printStackTrace(); return "生成失败:" + e.getMessage(); } } }
5. 升级Spring AI版本(可选但推荐)
你的pom.xml里用的是1.0.0版本,建议升级到最新稳定版(比如1.1.4),对第三方API的兼容性更好:
<properties> <java.version>17</java.version> <spring-ai.version>1.1.4</spring-ai.version> </properties>
最后检查点
- 确认你的OpenRouter API密钥有效,且已经开通了DALL-E3的访问权限
- 测试时如果还是返回text/html,大概率是请求头没设置对,重点检查
HTTP-Referer
内容来源于stack exchange
相关产品推荐
相关产品推荐

