Spring升级后RestTemplate报UnknownContentTypeException问题求助
你遇到的这个问题在Spring Boot版本升级后很常见,核心原因要么是测试环境下接口实际返回了HTML错误页面而非预期的JSON,要么是升级后RestTemplate默认缺少处理text/html类型转JSON的消息转换器。下面是分步排查和解决方法:
第一步:确认接口实际返回的内容
首先要排除接口在测试环境下是否正常工作。你可以临时修改调用代码,把响应类型改成String,看看实际返回的是什么:
def response = restTemplateForTenant(ACME_TENANT, acmeUser_1).getForEntity(url("ApiUrl"), String.class) println "响应状态码: ${response.statusCode}" println "响应内容: ${response.body}"
如果输出的是类似Whitelabel Error Page的HTML内容,那问题出在接口本身——测试环境下它没有正常运行(比如依赖缺失、测试配置错误导致4xx/5xx错误),这时候需要先修复接口的测试环境问题。
第二步:添加支持text/html的JSON转换器
如果确认接口返回的是JSON但Content-Type头被设为text/html,或者升级后RestTemplate默认不再支持这种类型解析,你需要手动给RestTemplate添加能处理text/html的MappingJackson2HttpMessageConverter:
修改你的RestTemplateFactory.getRestTemplate方法,在创建RestTemplate后插入以下代码:
public static RestTemplate getRestTemplate(String baseUrl) { RestTemplate restTemplate = new RestTemplate(); // 新增:添加支持text/html的Jackson转换器 MappingJackson2HttpMessageConverter htmlJsonConverter = new MappingJackson2HttpMessageConverter(); htmlJsonConverter.setSupportedMediaTypes(Arrays.asList( MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, // 允许解析text/html类型的JSON MediaType.TEXT_PLAIN )); // 把自定义转换器放到列表最前面,确保优先使用 restTemplate.getMessageConverters().add(0, htmlJsonConverter); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(baseUrl)); restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); // ... 保留原有的错误处理器代码 return restTemplate; }
默认情况下,MappingJackson2HttpMessageConverter只处理application/json等标准JSON媒体类型,添加text/html支持后,RestTemplate就能正确解析这种类型的JSON响应了。
第三步:检查RestTemplate默认配置的变化
Spring Boot 2.2.x相对于2.1.x,在RestTemplateAutoConfiguration中对默认消息转换器的配置有细微调整,可能移除了对非标准JSON媒体类型的默认支持。手动添加自定义转换器可以覆盖这种默认行为,确保你的RestTemplate能适配接口返回的内容类型。
额外排查点
- 确认测试用的接口URL是否正确:比如是否包含了正确的上下文路径、测试端口,避免因为404错误返回HTML错误页面。
- 优化错误处理器:你自定义的
ResponseErrorHandler中handleError方法是空实现,这会导致接口返回错误状态码时不会抛出异常,而是继续尝试解析响应——如果此时响应是错误页面,就会触发UnknownContentTypeException。可以考虑在handleError中添加日志或抛出异常,方便排查问题:@Override public void handleError(ClientHttpResponse httpResponse) throws IOException { throw new HttpClientErrorException(httpResponse.getStatusCode(), httpResponse.getStatusText(), httpResponse.getHeaders(), StreamUtils.copyToByteArray(httpResponse.getBody()), StandardCharsets.UTF_8); }
内容的提问来源于stack exchange,提问作者Daniel Haughton

