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



我在代码中使用Java Callable Future。下面是我的主要代码,它使用未来和可调用-

public class TimeoutThread {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(5);
Future<String> 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类,它实现了可调用接口,我需要根据主机名生成URL,然后使用RestTemplate调用SERVERS。如果第一个主机名中有任何异常,那么我将为另一个主机名生成URL,并尝试进行调用。

class Task implements Callable<String> {
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客户端的创建与其使用分开。马丁·福勒的这篇文章是关于这个话题的开创性讨论。

在我的特殊情况下,我发现了一些原因,说明为什么人们可能想要拥有多个RestTemplate实例。

RestTemplate是一种调用远程端点的方法,但HTTP集成看起来非常简单,当你开始发现不适用于所有API调用的特殊场景时,你就会意识到你需要一种方法来逐个定义一些设置。

此类场景的示例如下:

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

如前所述,RestTemplate是线程安全的。

但是,对于单元测试,使用静态变量会给模拟他的调用带来一些问题。因此,考虑使用类构造函数注入RestTemplate:

@Service
class LoginService {
private final RestTemplate restTemplate;
public LoginService(final RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
}

相关内容

  • 没有找到相关文章

最新更新