Java RestTemplate 应该是静态的全局声明?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21145558/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
RestTemplate should be static globally declared?
提问by AKIWEB
I am using Java Callable Future in my code. Below is my main code which uses the future and callables -
我在我的代码中使用 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();
}
}
Below is my Task
class which implements the Callable interface and I need to generate URL depending on the hostname we have and then make a call to SERVERS using RestTemplate
. If there is any exception in the first hostname, then I will generate URL for another hostname and I will try making a call.
下面是我的Task
类,它实现了 Callable 接口,我需要根据我们拥有的主机名生成 URL,然后使用RestTemplate
. 如果第一个主机名有任何异常,那么我将为另一个主机名生成 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
}
}
}
}
So my question should I declare RestTemplate
as static global variable? Or it should not be static in this scenario?
所以我的问题应该声明RestTemplate
为静态全局变量吗?或者在这种情况下它不应该是静态的?
采纳答案by Sotirios Delimanolis
It doesn't matter either way, static
or instance.
无论哪种方式static
或实例都无关紧要。
RestTemplate
's methods for making HTTP requests are thread safe so whether you have a RestTemplate
instance per Task
instance or a shared instance for all Task
instances is irrelevant (except for garbage collection).
RestTemplate
用于发出 HTTP 请求的方法是线程安全的,因此是RestTemplate
每个Task
实例都有一个实例还是所有Task
实例的共享实例都无关紧要(垃圾收集除外)。
Personally, I would create the RestTemplate
outside the Task
class and pass it as an argument to a Task
constructor. (Use Inversion of Control whenever possible.)
就个人而言,我会RestTemplate
在Task
类的外部创建并将其作为参数传递给Task
构造函数。(尽可能使用控制反转。)
回答by Vidya
From a concurrency standpoint, it doesn't matter. RestTemplate
is thread safe, so a single instance or multiple instances is irrelevant to proper functioning of the program.
从并发的角度来看,这无关紧要。RestTemplate
是线程安全的,因此单个实例或多个实例与程序的正常运行无关。
But you might want to consider AsyncRestTemplate
instead as shown here.
但是,你可能要考虑AsyncRestTemplate
如图所示,而不是在这里。
Also, as others mention, you should consider an IoC approach to separate the creation of your REST client from its use. Thisarticle by Martin Fowler is the seminal discussion on the topic.
此外,正如其他人提到的,您应该考虑使用 IoC 方法将 REST 客户端的创建与其使用分开。Martin Fowler 的这篇文章是对该主题的开创性讨论。
回答by Edwin Dalorzo
In my particular case I have found some reasons why one might want to have more than one instance of RestTemplate
.
在我的特殊情况下,我发现了一些原因,为什么人们可能想要拥有多个RestTemplate
.
The RestTemplate is a way to invoke a remote endpoint, but HTTP integration looks deceivingly simple and when you start finding special scenarios that do not apply to all your API calls is when you realize you need a way to define some settings in a case by case basis.
RestTemplate 是一种调用远程端点的方法,但 HTTP 集成看起来非常简单,当您开始寻找不适用于所有 API 调用的特殊场景时,您就会意识到需要一种方法来逐个定义一些设置基础。
Examples of such scenarios are the following:
此类场景的示例如下:
- We have different teams in the company, and by mistake we didn't agree on the time format we wanted to use in our our models. Now, different APIs from different teams use different time formats which forced us to define different JSON mapper settings for those cases. This may also happen if you have to invoke third party services.
- Not all the APIs we call have the same service level agreements or behave the same all over the year. In high season some APIs may have to support more traffic, etc. This means that the connection timeout settings may be different for different APIs and sometimes even depending on the requirements. So, settings like connection timeout, read timeout and write timeout may be configured differently depending on the service you're invoking.
- Perhaps circuit breaker setting, like those of Hytrix, may need to be configured per service, and so having a RestTemplate instance per service allows more ability to configure settings in a case by case basis.
- 我们公司有不同的团队,我们错误地在模型中使用的时间格式不一致。现在,来自不同团队的不同 API 使用不同的时间格式,这迫使我们为这些情况定义不同的 JSON 映射器设置。如果您必须调用第三方服务,也可能会发生这种情况。
- 并非我们调用的所有 API 都具有相同的服务级别协议或全年表现相同。在旺季,一些 API 可能需要支持更多流量等。这意味着不同 API 的连接超时设置可能不同,有时甚至取决于需求。因此,连接超时、读取超时和写入超时等设置可能会根据您调用的服务进行不同的配置。
- 也许断路器设置,就像 Hytrix 的那些一样,可能需要为每个服务配置,因此每个服务都有一个 RestTemplate 实例允许更多地根据具体情况配置设置。
回答by Dherik
As already said, RestTemplate is thread safe.
如前所述,RestTemplate 是线程安全的。
But, for unit test, use a static variable will bring to you some problems to mock his calls. So, consider to inject the RestTemplate using the class constructor:
但是,对于单元测试,使用静态变量会给你带来一些问题来模拟他的调用。因此,考虑使用类构造函数注入 RestTemplate:
@Service
class LoginService {
private final RestTemplate restTemplate;
public LoginService(final RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
}