如何通过RestTemplate在反序列化前查看API响应内容?
问题场景
你在使用Spring的RestTemplate调用API时遇到了这样的困扰:API文档存在错误,导致DesignatedDto无法正常完成响应反序列化,之前只能联系开发者拿到真实响应才能解决问题。现在想知道有没有无需联系开发者,就能在反序列化前查看原始API响应的方法——而且不能用String::class.java替代DesignatedDto::class.java接收响应,因为会触发如下错误:
org.springframework.web.client.RestClientException: Error while extracting response for type [class java.lang.String] and content type [text/html;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of
java.lang.Stringout of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance ofjava.lang.Stringout of START_OBJECT token at [Source: (PushbackInputStream); line: 6, column: 1]
实用解决方案
这里有几个在Spring生态内就能实现的靠谱方法,完全满足你的需求:
1. 用ResponseEntity<byte[]>接收原始响应
这是最直接的方式,字节数组能完整保留响应的原始格式,不会触发任何自动解析:
val response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, ByteArray::class.java) // 将字节数组转为字符串查看,注意匹配API响应的编码(通常是UTF-8) val rawResponse = String(response.body!!, Charsets.UTF_8) println("原始API响应内容:$rawResponse") // 确认响应无误后,再手动反序列化到目标DTO val objectMapper = ObjectMapper() val dto = objectMapper.readValue(rawResponse, DesignatedDto::class.java)
这种方式既拿到了原始响应内容,之后也能正常完成反序列化,完美避开了直接用String接收的解析错误。
2. 开启RestTemplate的DEBUG日志
Spring的RestTemplate支持通过日志打印完整的请求和响应细节,不需要修改业务代码,只需要在日志配置中开启对应包的DEBUG级别:
# 若使用application.properties配置 logging.level.org.springframework.web.client.RestTemplate=DEBUG
开启后,日志会输出完整的响应头、响应体内容,你可以直接从日志里查看原始响应。注意:生产环境请关闭该配置,避免敏感数据泄露。
3. 自定义拦截器拦截响应
如果需要精准控制哪些请求需要查看响应(比如只在调试特定接口时启用),可以写一个自定义拦截器:
class ResponseLoggingInterceptor : ClientHttpRequestInterceptor { override fun intercept(request: HttpRequest, body: ByteArray, execution: ClientHttpRequestExecution): ClientHttpResponse { val response = execution.execute(request, body) // 读取响应体内容并打印 val responseBody = StreamUtils.copyToString(response.body, Charsets.UTF_8) println("拦截到的API响应:$responseBody") // 必须重新包装响应体,因为输入流只能读取一次 return BufferingClientHttpResponseWrapper(response) } }
然后将这个拦截器添加到你的RestTemplate实例中:
restTemplate.interceptors.add(ResponseLoggingInterceptor())
这种方式不会影响正常的反序列化流程,还能灵活控制拦截范围。
内容的提问来源于stack exchange,提问作者Doo Hyun Shin

