SpringBoot 升级 RestTemplateBuilder 从 1.5.14 到 2.1.5
SpringBoot upgrade RestTemplateBuilder from 1.5.14 to 2.1.5
我的这段代码在使用 RestTemplateBuilder 1.5.14
的项目上运行良好
this.restTemplate = restTemplateBuilder
.setConnectTimeout(connectTimeout)
.setReadTimeout(readTimeout)
.requestFactory(new MyHttpComponentFactoryBuilder()
.build())
.build();
更新到RestTemplateBuilder 2.1.5
后我有这段代码:
this.restTemplate = restTemplateBuilder
.setConnectTimeout(Duration.ofMillis(connectTimeout))
.setReadTimeout(Duration.ofMillis(readTimeout))
.requestFactory(new MyHttpComponentFactoryBuilder().build().getClass())
.build();
但是当 运行 代码时,我有一个 InvocationTargetException / NullPointerException
在删除行 .requestFactory(new MyHttpComponentFactoryBuilder().build().getClass())
时消失,但调试 new MyHttpComponentFactoryBuilder().build().getClass()
不为空
我也尝试了建议的解决方案:
...
.requestFactory(new MyRequestFactorySupplier())
...
class MyRequestFactorySupplier implements Supplier<ClientHttpRequestFactory> {
@Override
public ClientHttpRequestFactory get() {
// Using Apache HTTP client.
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
HttpClient httpClient = clientBuilder.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
requestFactory.setBufferRequestBody(false); // When sending large amounts of data via POST or PUT, it is recommended to change this property to false, so as not to run out of memory.
return requestFactory;
}
}
但我也有 InvocationTargetException / NullPointerException
尝试删除 .getClass()
调用,如果 .requestFactory 调用 指向 class RestTemplateBuilder
的 requestFactory(Class<? extends ClientHttpRequestFactory> requestFactory)
方法,请分享您的 MyHttpComponentFactoryBuilder
class
的代码片段
以下代码显示了您需要如何为简单案例创建模板。
RestTemplate tmpl = new RestTemplateBuilder().setConnectTimeout(Duration.ofMillis(200))
.setReadTimeout(Duration.ofMillis(100))
.requestFactory(org.springframework.http.client.SimpleClientHttpRequestFactory.class)
.build();
最好能提供MyHttpComponentFactoryBuilder
class的源代码。但我的建议是创建一个扩展 SimpleClientHttpRequestFactory
class 的 class MyHttpComponentFactory
将您的代码从 MyHttpComponentFactoryBuilder
迁移到它。
这应该有效(使用 lambda)
.requestFactory(() -> new MyHttpComponentFactoryBuilder().build())
您在这里不再需要构建器,因为供应商会按需构建 ClientHttpRequestFactory。将 RequestFactorySupplier 和 RestTemplateBuilder 定义为 beans。
@Bean
Supplier<ClientHttpRequestFactory> myRequestFactorySupplier() {
return () -> {
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
HttpClient httpClient = clientBuilder.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
requestFactory.setConnectTimeout(5000);
requestFactory.setReadTimeout(5000);
requestFactory.setBufferRequestBody(false);
return requestFactory;
};
}
@Bean
public RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder();
}
像这样在控制器中使用工厂。
@RestController
public class TestController {
private final RestTemplate restTemplate;
public TestController(
RestTemplateBuilder restTemplateBuilder,
Supplier<ClientHttpRequestFactory> myRequestFactorySupplier
) {
this.restTemplate = restTemplateBuilder
.requestFactory(myRequestFactorySupplier)
.build();
}
当然你也可以使用专门的 class.
public class MyRequestFactorySupplier implements Supplier<ClientHttpRequestFactory> {
@Override
public ClientHttpRequestFactory get() {
// Using Apache HTTP client.
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
HttpClient httpClient = clientBuilder.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
requestFactory.setBufferRequestBody(false); // When sending large amounts of data via POST or PUT, it is recommended to change this property to false, so as not to run out of memory.
return requestFactory;
}
}
按照您的建议在控制器中使用它:
public TestController(
RestTemplateBuilder restTemplateBuilder,
Supplier<ClientHttpRequestFactory> myRequestFactorySupplier
) {
this.restTemplate = restTemplateBuilder
.setConnectTimeout(Duration.ofMillis(5000))
.setReadTimeout(Duration.ofMillis(5000))
.requestFactory(new MyRequestFactorySupplier())
.build();
}
我在我的 github wiki 页面上写了详细的注释,请检查肯定会有帮助
示例如下:
public String retrieveData(String id, String name) {
HttpHeaders headers =createHeader();
String requestJson = "{\"name\":\"" + name + "\"}";
HttpEntity<String> request = new HttpEntity<String>(requestJson, headers);
// external call time
long startTime = System.currentTimeMillis();
ResponseEntity<String> response = customRestTemplate().exchange(externalUrl, HttpMethod.POST, request,
String.class);
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime); // divide by 1000000 to get milliseconds.
log.info("{\"RestTemplateDemo\":{\"id\":\"" + id + "\",\"external call duration\":" + duration + "}}");
ObjectMapper mapper = new ObjectMapper();
return response.getBody();
}
我的这段代码在使用 RestTemplateBuilder 1.5.14
this.restTemplate = restTemplateBuilder
.setConnectTimeout(connectTimeout)
.setReadTimeout(readTimeout)
.requestFactory(new MyHttpComponentFactoryBuilder()
.build())
.build();
更新到RestTemplateBuilder 2.1.5
后我有这段代码:
this.restTemplate = restTemplateBuilder
.setConnectTimeout(Duration.ofMillis(connectTimeout))
.setReadTimeout(Duration.ofMillis(readTimeout))
.requestFactory(new MyHttpComponentFactoryBuilder().build().getClass())
.build();
但是当 运行 代码时,我有一个 InvocationTargetException / NullPointerException
在删除行 .requestFactory(new MyHttpComponentFactoryBuilder().build().getClass())
时消失,但调试 new MyHttpComponentFactoryBuilder().build().getClass()
不为空
我也尝试了建议的解决方案:
...
.requestFactory(new MyRequestFactorySupplier())
...
class MyRequestFactorySupplier implements Supplier<ClientHttpRequestFactory> {
@Override
public ClientHttpRequestFactory get() {
// Using Apache HTTP client.
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
HttpClient httpClient = clientBuilder.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
requestFactory.setBufferRequestBody(false); // When sending large amounts of data via POST or PUT, it is recommended to change this property to false, so as not to run out of memory.
return requestFactory;
}
}
但我也有 InvocationTargetException / NullPointerException
尝试删除 .getClass()
调用,如果 .requestFactory 调用 指向 class RestTemplateBuilder
的 requestFactory(Class<? extends ClientHttpRequestFactory> requestFactory)
方法,请分享您的 MyHttpComponentFactoryBuilder
class
以下代码显示了您需要如何为简单案例创建模板。
RestTemplate tmpl = new RestTemplateBuilder().setConnectTimeout(Duration.ofMillis(200))
.setReadTimeout(Duration.ofMillis(100))
.requestFactory(org.springframework.http.client.SimpleClientHttpRequestFactory.class)
.build();
最好能提供MyHttpComponentFactoryBuilder
class的源代码。但我的建议是创建一个扩展 SimpleClientHttpRequestFactory
class 的 class MyHttpComponentFactory
将您的代码从 MyHttpComponentFactoryBuilder
迁移到它。
这应该有效(使用 lambda)
.requestFactory(() -> new MyHttpComponentFactoryBuilder().build())
您在这里不再需要构建器,因为供应商会按需构建 ClientHttpRequestFactory。将 RequestFactorySupplier 和 RestTemplateBuilder 定义为 beans。
@Bean
Supplier<ClientHttpRequestFactory> myRequestFactorySupplier() {
return () -> {
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
HttpClient httpClient = clientBuilder.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
requestFactory.setConnectTimeout(5000);
requestFactory.setReadTimeout(5000);
requestFactory.setBufferRequestBody(false);
return requestFactory;
};
}
@Bean
public RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder();
}
像这样在控制器中使用工厂。
@RestController
public class TestController {
private final RestTemplate restTemplate;
public TestController(
RestTemplateBuilder restTemplateBuilder,
Supplier<ClientHttpRequestFactory> myRequestFactorySupplier
) {
this.restTemplate = restTemplateBuilder
.requestFactory(myRequestFactorySupplier)
.build();
}
当然你也可以使用专门的 class.
public class MyRequestFactorySupplier implements Supplier<ClientHttpRequestFactory> {
@Override
public ClientHttpRequestFactory get() {
// Using Apache HTTP client.
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
HttpClient httpClient = clientBuilder.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
requestFactory.setBufferRequestBody(false); // When sending large amounts of data via POST or PUT, it is recommended to change this property to false, so as not to run out of memory.
return requestFactory;
}
}
按照您的建议在控制器中使用它:
public TestController(
RestTemplateBuilder restTemplateBuilder,
Supplier<ClientHttpRequestFactory> myRequestFactorySupplier
) {
this.restTemplate = restTemplateBuilder
.setConnectTimeout(Duration.ofMillis(5000))
.setReadTimeout(Duration.ofMillis(5000))
.requestFactory(new MyRequestFactorySupplier())
.build();
}
我在我的 github wiki 页面上写了详细的注释,请检查肯定会有帮助
示例如下:
public String retrieveData(String id, String name) {
HttpHeaders headers =createHeader();
String requestJson = "{\"name\":\"" + name + "\"}";
HttpEntity<String> request = new HttpEntity<String>(requestJson, headers);
// external call time
long startTime = System.currentTimeMillis();
ResponseEntity<String> response = customRestTemplate().exchange(externalUrl, HttpMethod.POST, request,
String.class);
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime); // divide by 1000000 to get milliseconds.
log.info("{\"RestTemplateDemo\":{\"id\":\"" + id + "\",\"external call duration\":" + duration + "}}");
ObjectMapper mapper = new ObjectMapper();
return response.getBody();
}