我已经阅读了一些有关在使用SPRING管理Beans的Java Web应用程序中实现REST客户端的教程。
我发现每个例子每次执行REST请求时都会创建一个新的RestTemplate。
通常Web应用程序使用单例Spring Bean。
因此,我想知道在Spring配置应用程序时使用RestTemplate的最佳实践是什么?
使用单例RestTemplate?
还是在每个请求中创建新的RestTemplate?
请给出建议并描述所有情况。
我已经阅读了一些有关在使用SPRING管理Beans的Java Web应用程序中实现REST客户端的教程。
我发现每个例子每次执行REST请求时都会创建一个新的RestTemplate。
通常Web应用程序使用单例Spring Bean。
因此,我想知道在Spring配置应用程序时使用RestTemplate的最佳实践是什么?
使用单例RestTemplate?
还是在每个请求中创建新的RestTemplate?
请给出建议并描述所有情况。
@Configuration
public class ProductServiceConfig {
@Value("${product.username}")
private String productServiceUsername;
@Value("${product.password}")
private String productServicePassword;
@Bean(name = "restTemplateForProductService")
public RestTemplate prepareRestTemplateForProductService() {
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(productServiceUsername, productServicePassword));
RequestConfig.Builder requestBuilder = RequestConfig.custom();
requestBuilder = requestBuilder.setConnectTimeout(1000);
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
httpClientBuilder.setDefaultRequestConfig(requestBuilder.build());
CloseableHttpClient httpClient = httpClientBuilder.build();
HttpComponentsClientHttpRequestFactory rf = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(rf);
}
}
这样,您可以设置REST调用所需的各种参数,如超时或凭据等。当您想要使用时,只需执行
@Autowired
RestTemplate restTemplateForProductService;
restTemplateForProductService.......
相对于使用new RestTemplate()
的另一个优势是,如果您需要通过REST调用不同的服务,则可以定义多个bean(具有不同的配置),返回RestTemplates并使用名称进行自动装配。
/**
* Rest template client
*/
private static final RestTemplate TEMPLATE = new RestTemplate(new RestClientRequestFactory());
static{
//Set your options here
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.featuresToEnable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID);
builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
builder.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter();
jsonMessageConverter.setObjectMapper(builder.build());
TEMPLATE.setMessageConverters(Arrays.asList(jsonMessageConverter));
}
或者在@Configuration类中声明一个Spring Bean:
@Bean
public RestTemplate restTemplate(){
RestTemplate template = new RestTemplate(new RestClientRequestFactory())
//customize
return template;
}
如果您查看RestTemplate类,则应避免过多地调用默认构造函数:
public RestTemplate() {
this.messageConverters = new ArrayList();
this.errorHandler = new DefaultResponseErrorHandler();
this.uriTemplateHandler = new DefaultUriTemplateHandler();
this.headersExtractor = new RestTemplate.HeadersExtractor();
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
this.messageConverters.add(new ResourceHttpMessageConverter());
this.messageConverters.add(new SourceHttpMessageConverter());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) {
this.messageConverters.add(new AtomFeedHttpMessageConverter());
this.messageConverters.add(new RssChannelHttpMessageConverter());
}
if (jackson2XmlPresent) {
this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
} else if (jaxb2Present) {
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jackson2Present) {
this.messageConverters.add(new MappingJackson2HttpMessageConverter());
} else if (gsonPresent) {
this.messageConverters.add(new GsonHttpMessageConverter());
}
}