RestTemplate应该是全局声明的静态吗?

我在我的代码中使用Java Callable Future。 下面是我使用未来和callables的主要代码 –

public class TimeoutThread { public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newFixedThreadPool(5); Future future = executor.submit(new Task()); try { System.out.println("Started.."); System.out.println(future.get(3, TimeUnit.SECONDS)); System.out.println("Finished!"); } catch (TimeoutException e) { System.out.println("Terminated!"); } executor.shutdownNow(); } } 

下面是我的Task类,它实现了Callable接口,我需要根据我们拥有的主机名生成URL,然后使用RestTemplate调用SERVERS。 如果第一个主机名中有任何exception,那么我将为另一个主机名生成URL,我将尝试拨打电话。

 class Task implements Callable { private static RestTemplate restTemplate = new RestTemplate(); @Override public String call() throws Exception { //.. some code for(String hostname : hostnames) { if(hostname == null) { continue; } try { String url = generateURL(hostname); response = restTemplate.getForObject(url, String.class); // make a response and then break break; } catch (Exception ex) { ex.printStackTrace(); // use logger } } } } 

所以我的问题是我应该将RestTemplate声明为静态全局变量吗? 或者在这种情况下它不应该是静态的?

它无关紧要, static或实例。

RestTemplate用于发出HTTP请求的方法是线程安全的,因此无论每个Task实例有一个RestTemplate实例还是所有Task实例的共享实例都是无关紧要的(垃圾收集除外)。

就个人而言,我会在Task类之外创建RestTemplate ,并将其作为参数传递给Task构造函数。 (尽可能使用控制反转。)

从并发的角度来看,这没关系。 RestTemplate是线程安全的,因此单个实​​例或多个实例与程序的正常运行无关。

但您可能需要考虑AsyncRestTemplate ,如此处所示。

此外,正如其他人所提到的,您应该考虑使用IoC方法将REST客户端的创建与其使用分开。 Martin Fowler撰写的这篇文章是关于该主题的开创性讨论。

在我的特定情况下,我发现了为什么人们可能希望拥有多个RestTemplate实例的RestTemplate

RestTemplate是一种调用远程端点的方法,但是HTTP集成看起来很简单,当你开始发现不适用于所有API调用的特殊场景时,你会发现需要一种方法来定义一个案例中的一些设置基础。

此类方案的示例如下:

  • 我们公司有不同的团队,我们错误地认为我们想要在我们的模型中使用的时间格式。 现在,来自不同团队的不同API使用不同的时间格式,这迫使我们为这些案例定义不同的JSON映射器设置。 如果您必须调用第三方服务,也可能发生这种情况。
  • 并非所有我们调用的API都具有相同的服务级别协议,或者全年都表现相同。 在旺季,一些API可能必须支持更多流量等。这意味着连接超时设置可能因不同的API而有所不同,有时甚至取决于要求。 因此,根据您正在调用的服务,可能会以不同方式配置连接超时,读取超时和写入超时等设置。
  • 也许像Hytrix那样的断路器设置可能需要按服务进行配置,因此每个服务具有RestTemplate实例允许更多地根据具体情况配置设置。