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 класс, который реализует интерфейс Callable, и мне нужно сгенерировать URL в зависимости от имеющегося у нас имени хоста, а затем сделать вызов SERVERS, используя 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
            }
        }
    }
}

Так что мой вопрос я должен объявить RestTemplate как статическая глобальная переменная? Или оно не должно быть статичным в этом сценарии?

4 ответа

Решение

В любом случае это не имеет значения, static или экземпляр.

RestTemplateметоды для выполнения HTTP-запросов поточнобезопасны, так что если у вас есть RestTemplate экземпляр за Task экземпляр или общий экземпляр для всех Task экземпляры не имеют значения (за исключением сбора мусора).

Лично я бы создал RestTemplate вне Task класс и передать его в качестве аргумента 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;
    }
}
Другие вопросы по тегам