Spring 里发 HTTP 请求最常见还是 RestTemplate。虽然官方已经推 WebClient,但存量项目里 RestTemplate 到处都是——写起来简单、同步阻塞、跟传统 Servlet 模型贴合。
注册 Bean
@Configuration
public class RestConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
注入用:
@Autowired
private RestTemplate restTemplate;
或者构造器注入(推荐):
private final RestTemplate rt;
public UserService(RestTemplate rt) { this.rt = rt; }
GET
最简单:
String json = restTemplate.getForObject(
"https://api.example.com/users/1",
String.class);
带 URL 参数(占位符按顺序填):
String url = "https://api.example.com/users/{id}?type={type}";
String json = restTemplate.getForObject(url, String.class, 1, "vip");
返回对象:
@Data
public class User {
private Integer id;
private String name;
}
User u = restTemplate.getForObject(
"https://api.example.com/users/1",
User.class);
Jackson 会自动反序列化——User 里字段名和 JSON 对得上就行。
POST
发 JSON:
Map<String, Object> body = new HashMap<>();
body.put("username", "admin");
body.put("password", "12345");
String result = restTemplate.postForObject(
"https://api.example.com/login",
body,
String.class);
RestTemplate 会把 Map 序列化成 JSON 并设 Content-Type: application/json(前提是有 Jackson)。
表单:
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("username", "admin");
form.add("password", "12345");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, String>> req = new HttpEntity<>(form, headers);
String result = restTemplate.postForObject(url, req, String.class);
自定义 Header
带 Token 的接口:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + token);
Map<String, Object> body = new HashMap<>();
body.put("name", "test");
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(body, headers);
ResponseEntity<String> resp = restTemplate.exchange(
"https://api.example.com/create",
HttpMethod.POST,
entity,
String.class);
if (resp.getStatusCode().is2xxSuccessful()) {
System.out.println(resp.getBody());
}
exchange 是最灵活的方法——可以自由选择 HTTP method、传 headers、拿完整的 ResponseEntity。
超时配置(生产必配)
默认没有超时。远端 hang 住就一直等:
@Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5_000); // 连接超时
factory.setReadTimeout(10_000); // 读超时
return new RestTemplate(factory);
}
更强大的选择:Apache HttpClient 5:
@Bean
public RestTemplate restTemplate() {
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(Timeout.ofSeconds(5))
.setResponseTimeout(Timeout.ofSeconds(10))
.build();
CloseableHttpClient http = HttpClients.custom()
.setDefaultRequestConfig(config)
.setMaxConnTotal(100)
.setMaxConnPerRoute(20)
.build();
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory(http);
return new RestTemplate(factory);
}
带连接池、更好的性能、支持重试。
上传文件
FileSystemResource file = new FileSystemResource("/path/to/a.zip");
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", file);
body.add("desc", "备份");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> req = new HttpEntity<>(body, headers);
String result = restTemplate.postForObject(
"https://api.example.com/upload",
req, String.class);
忽略 SSL
自签证书内网服务:
SSLContext ssl = SSLContexts.custom()
.loadTrustMaterial((chain, authType) -> true)
.build();
CloseableHttpClient http = HttpClients.custom()
.setConnectionManager(
PoolingHttpClientConnectionManagerBuilder.create()
.setSSLSocketFactory(
SSLConnectionSocketFactoryBuilder.create()
.setSslContext(ssl)
.setHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build())
.build())
.build();
生产上少这么干,会漏中间人。
Spring Boot 3 之后怎么办
Spring Framework 6 起 RestTemplate 进入维护模式——不再加新功能,但不会立刻删。新项目推荐:
RestClient(Spring 6.1+)— 同步、fluent API,最平滑的替代WebClient— 响应式(reactive),跟 Reactor 生态整合
RestClient 示例:
RestClient client = RestClient.create();
User u = client.get()
.uri("https://api.example.com/users/{id}", 1)
.retrieve()
.body(User.class);
比 RestTemplate 好看得多。老项目不用急着换,新代码优先用 RestClient。
一句话总结
RestTemplate:GET 用 getForObject、POST 用 postForObject 或 exchange、复杂场景走 exchange 拿 ResponseEntity。生产必配超时和连接池。新项目改用 RestClient。
