RestTemplate 默认不支持 JSON 自动序列化,因其初始化仅注册 StringHttpMessageConverter 和 ByteArrayHttpMessageConverter,未配置 MappingJackson2HttpMessageConverter;需手动添加或使用 RestTemplateBuilder 构造。

RestTemplate 为什么默认不支持 JSON 自动序列化
因为 RestTemplate 初始化时只注册了基础的 StringHttpMessageConverter 和 ByteArrayHttpMessageConverter,没配 Jackson2ObjectMapperFactoryBean 对应的 MappingJackson2HttpMessageConverter。你传个 new User("a", 18) 直接发出去,大概率是空体或 415 错误。
- 手动添加转换器:用
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()) - 更稳妥的做法是用
RestTemplateBuilder构造,它默认带 Jackson 支持:new RestTemplateBuilder().build() - 注意 Spring Boot 2.3+ 默认移除了 Jackson 依赖,如果项目没显式引入
spring-boot-starter-json,会静默失败
怎么给所有请求统一加 Header 和重试逻辑
靠 setInterceptors 配 ClientHttpRequestInterceptor,不是改 setRequestFactory 或重写 execute —— 后者绕过拦截器链,Header 和日志都会丢。
- Header 拦截器示例:
request.getHeaders().set("X-Trace-ID", MDC.get("traceId")),注意别覆盖已有值(用add而非set) - 重试不能在拦截器里死循环,要用
RetryTemplate包裹实际execution.execute()调用 - 拦截器中抛出的异常不会触发
@Retryable,那是 Spring Retry 的切面逻辑,和RestTemplate无关
ResponseEntity 中的 T 类型擦除导致泛型反序列化失败
写成 restTemplate.getForEntity(url, User.class) 没问题,但一旦涉及嵌套泛型(比如 List<user></user>),User.class 就不够用了 —— JVM 泛型擦除后,Jackson 不知道该构造什么类型。
- 必须用
ParameterizedTypeReference:new ParameterizedTypeReference<list>>() {}</list> - 别手写
new TypeReference<list>>() {}</list>,那是 Jackson 的类,RestTemplate只认 Spring 的ParameterizedTypeReference - 这个对象不能是局部变量 lambda 捕获的,否则可能因泛型信息丢失导致
Cannot construct instance
连接超时和读取超时到底设多少才合理
设成一样是常见错误。setConnectTimeout 控制 TCP 握手时间,setReadTimeout 控制响应体接收时间,两者量级和失败原因完全不同。
立即学习“Java免费学习笔记(深入)”;
- 内网调用:connect 可设 500ms,read 设 2–5s;公网第三方 API:connect 至少 3s,read 根据 SLA 定(比如支付接口常要 15s)
- 用
HttpComponentsClientHttpRequestFactory替代默认的SimpleClientHttpRequestFactory,后者不支持连接池,高并发下容易耗尽本地端口 - 别在每次请求前临时改
setConnectTimeout—— 这会同步修改整个RestTemplate实例,影响其他线程
拦截器里做日志时最容易忽略响应体流只能读一次。想打印 body 又不影响后续处理,得用 BufferingClientHttpRequestInterceptor 或自己包装 ClientHttpResponse,不然下游拿到的就是空流。


















