Spring Boot中RestTemplate代码迁移至RestClient求助
问题描述
需要将Spring Boot项目中的RestTemplate请求代码迁移为RestClient实现,原RestTemplate代码如下:
private byte[] request(Data data) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<ResponseData> entity = new HttpEntity<>(data, headers); return restTemplate.exchange(url + uri, HttpMethod.POST, entity, byte[].class).getBody(); }
尝试了四种写法均未正常工作,代码如下:
写法一
private byte[] request(Data data) { return restClientBuilder.baseUrl(url) .build() .post() .uri(uri) .contentType(MediaType.APPLICATION_JSON) .body(data) .retrieve() .onStatus(HttpStatusCode::isError, new ApiErrorHandler()) .toEntity(byte[].class).getBody(); }
写法二
private byte[] request(Data data) { return restClientBuilder.baseUrl(url) .build() .post() .uri(uri) .contentType(MediaType.APPLICATION_JSON) .body(data) .retrieve() .onStatus(HttpStatusCode::isError, new ApiErrorHandler()) .body(byte[].class); }
写法三
private byte[] request(Data data) { return restClientBuilder.baseUrl(url) .build() .post() .uri(uri) .contentType(MediaType.APPLICATION_JSON) .body(data) .exchange((request, res) -> res.getBody().readAllBytes()); }
写法四
private byte[] requestD(Data data) { return restClientBuilder.baseUrl(url) .build() .post() .uri(uri) .contentType(MediaType.APPLICATION_JSON) .body(data) .retrieve() .onStatus(HttpStatusCode::isError, new ApiErrorHandler()) .toEntity(new ParameterizedTypeReference<byte[]>() { }).getBody(); }
正确实现方案
以下是与原RestTemplate代码完全等效的RestClient实现,同时解决了之前写法的潜在问题:
private byte[] request(Data data) { // 建议提前初始化RestClient实例并注入Spring容器,避免每次请求重复build RestClient restClient = restClientBuilder.baseUrl(url).build(); return restClient.post() .uri(uri) .contentType(MediaType.APPLICATION_JSON) .body(data) .retrieve() .onStatus(HttpStatusCode::isError, (request, response) -> { // 确保ApiErrorHandler正确处理错误并抛出异常,中断正常响应流程 new ApiErrorHandler().handle(request, response); }) .body(new ParameterizedTypeReference<byte[]>() {}); }
常见问题排查
- ApiErrorHandler实现问题:
前三种写法逻辑本身无错误,大概率是ApiErrorHandler未正确实现ResponseErrorHandler接口,或者handle方法没有抛出异常。错误处理逻辑必须抛出异常,才能中断RestClient的正常响应解析流程。 - 写法三的资源泄漏:
exchange中直接调用res.getBody().readAllBytes()需要手动关闭输入流,否则会导致连接池资源泄漏。优先使用retrieve()方式,RestClient会自动管理资源。 - 重复构建RestClient:
每次请求调用build()会重复创建客户端实例,影响性能。建议在配置类中初始化RestClient并注入容器,直接使用注入的实例即可。
简化版(无自定义错误处理)
如果不需要自定义错误处理,可以省略onStatus,RestClient会默认抛出对应状态码的异常:
private byte[] request(Data data) { return restClient.post() .uri(uri) .contentType(MediaType.APPLICATION_JSON) .body(data) .retrieve() .body(byte[].class); }
内容的提问来源于stack exchange,提问作者Jorge Rabello
相关产品推荐
相关产品推荐

