Java 如何在RequestFactory中有效地使用RestTemplate?

Java 如何在RequestFactory中有效地使用RestTemplate?,java,multithreading,performance,resttemplate,Java,Multithreading,Performance,Resttemplate,我正在从事一个项目,在这个项目中,我需要对运行Restful服务的服务器进行HTTP URL调用,该服务将响应作为JSON字符串返回。我在这里使用restemplate和httpcomponents客户端httprequestfactory来执行url 我使用httpcomponents客户端httprequestfactory在我的restemplate上设置了http请求超时(读取和连接超时) 以下是我的界面: public interface Client { // for sy

我正在从事一个项目,在这个项目中,我需要对运行Restful服务的服务器进行HTTP URL调用,该服务将响应作为JSON字符串返回。我在这里使用
restemplate
httpcomponents客户端httprequestfactory
来执行url

我使用
httpcomponents客户端httprequestfactory
在我的
restemplate
上设置了http请求超时(读取和连接超时)

以下是我的界面:

public interface Client {

    // for synchronous
    public String getSyncData(String key, long timeout);

    // for asynchronous
    public String getAsyncData(String key, long timeout);
}
下面是我的客户端接口的实现-

public class DataClient implements Client {

    private final RestTemplate restTemplate = new RestTemplate();
    private ExecutorService executor = Executors.newFixedThreadPool(10);

    // for synchronous call
    @Override
    public String getSyncData(String key, long timeout) {
        String response = null;

        try {
            Task task = new Task(key, restTemplate, timeout);

            // direct call, implementing sync call as async + waiting is bad idea. 
            // It is meaningless and consumes one thread from the thread pool per a call.               
            response = task.call();
        } catch (Exception ex) {
            PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, key);
        }

        return response;
    }

    // for asynchronous call
    @Override
    public Future<String> getAsyncData(String key, long timeout) {
        Future<String> future = null;

        try {
            Task task = new Task(key, restTemplate, timeout);
            future = executor.submit(task); 
        } catch (Exception ex) {
            PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, key);
        }

        return future;
    }
}

据我所知,您重复使用相同的
restemplate
对象,但每个
任务都执行这一行:
restemplate.setRequestFactory(clienthtprequestfactory())。这似乎有竞争条件,例如一个
任务
可以设置另一个
任务
将意外使用的
请求工厂

否则,您似乎正确地使用了
restemplate

你的超时多长时间改变一次?如果主要使用一个或两个超时,则可以使用带有预加载超时的
RequestFactory
构造函数创建一个或两个
restemplate
s。如果你是一个追求效率的人,那么创建一个
HashMap
,它在每次请求新超时时缓存一个带有特定超时的
restemplate


否则,查看和的代码,它们看起来并不特别繁重,因此反复调用它们可能不会造成太大的瓶颈。

FYI有一个AsyncRestTemplate spring 4。@AdamGent我明白了,它在我的场景中有用吗?AsyncRestTemplate可能完全消除对任务的需求,当它返回一个
未来时
。您可以选择在普通RestTemplate或异步RestTemplate上运行请求,而不是在直接执行任务或将任务提交给执行者之间进行选择。如何避免这种竞争条件?每个客户都将在其代码库中使用此库,因此他们将始终只设置一个超时,不会不断更改每次调用的超时值。一旦设置好,它将用于他们对该库的所有调用。修复竞争条件的简单方法是在创建任务之前创建一个新的RestTemplate。那么您根本不需要将超时传递给任务。如果一个库使用只有一个超时设置,我建议添加DataClient.setTimeout(int timeout)。然后,您可以使用一个RestTemplate,通过该函数设置一次超时,然后继续使用life。您能提供一个示例吗?这将帮助我更好地理解。哪一个例子?为了避免竞争条件,将“clientHttpRequestFactory”从任务移动到DataClient。然后任务创建行看起来就像“任务任务=新任务(键,新RestTemplate(clientHttpRequestFactory(超时))
class Task implements Callable<String> {

    private RestTemplate restTemplate;
    private String key;
    private long timeout; // in milliseconds

    public Task(String key, RestTemplate restTemplate, long timeout) {
        this.key = key;
        this.restTemplate = restTemplate;
        this.timeout = timeout;
    }

    public String call() throws Exception {

        String url = "some_url_created_by_using_key";

        // does this looks right the way I am setting request factory?
        // or is there any other effficient way to do this?
        restTemplate.setRequestFactory(clientHttpRequestFactory());
        String response = restTemplate.exchange(url, HttpMethod.GET, null, String.class);

        return response;
    }

    private static ClientHttpRequestFactory clientHttpRequestFactory() {
        // is it ok to create a new instance of HttpComponentsClientHttpRequestFactory everytime?
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setReadTimeout(timeout); // setting timeout as read timeout
        factory.setConnectTimeout(timeout); // setting timeout as connect timeout
        return factory;
    }   
}
String response = DataClientFactory.getInstance().getSyncData(keyData, 100);