Рубрики
Без рубрики

Введение в весенний ремотинг с HTTP Invokers

Быстрое и практическое руководство по использованию HTTP Invoker весной Remoting для вызова удаленных методов между клиентскими и серверных приложений.

Автор оригинала: baeldung.

Введение в весенний ремотинг с HTTP Invokers

1. Обзор

В некоторых случаях нам необходимо разложить систему на несколько процессов, каждый из которых берет на себя ответственность за другой аспект нашего применения. В этих сценариях не редкость, что один из процессов должен синхронно получать данные из другого.

Весенняя рамочная программа предлагает широкий спектр инструментов, которые Весенний ремотинг что позволяет нам ссылаться на удаленные службы, как если бы они были, по крайней мере в некоторой степени, доступны на местном уровне.

In this article, we will set up an application based on Spring’s HTTP invoker , which leverages native Java serialization and HTTP to provide remote method invocation between a client and a server application.

2. Определение службы

Допустим, мы должны внедрить систему, которая позволяет пользователям бронировать поездку в такси.

Давайте также предположим, что мы решили построить два различных приложения для получения этой цели:

  • приложение системы бронирования, чтобы проверить, можно ли обслуживать запрос такси, и
  • фронт-конец веб-приложение, которое позволяет клиентам забронировать свои поездки, обеспечивая наличие кабины было подтверждено

2.1. Интерфейс обслуживания

Когда мы используем Весенний ремотинг с HTTP invoker, мы должны определить наш удаленно callable сервис корыта интерфейс, чтобы весна создать прокси как на стороне клиента и сервера, которые инкапсулируют технические аспекты удаленного вызова. Итак, давайте начнем с интерфейса службы, которая позволяет нам забронировать такси:

public interface CabBookingService {
    Booking bookRide(String pickUpLocation) throws BookingException;
}

Когда служба может выделить такси, она возвращает Бронирование объект с кодом бронирования. Бронирование должен быть сериализируемым, потому что вызовщик HTTP Spring должен передавать свои экземпляры с сервера клиенту:

public class Booking implements Serializable {
    private String bookingCode;

    @Override public String toString() {
        return format("Ride confirmed: code '%s'.", bookingCode);
    }

    // standard getters/setters and a constructor
}

Если служба не в состоянии забронировать такси, BookingException брошен. В этом случае нет необходимости отмечать класс как Серийный потому что Исключение уже реализует его:

public class BookingException extends Exception {
    public BookingException(String message) {
        super(message);
    }
}

2.2. Упаковка Услуги

Интерфейс службы наряду со всеми пользовательскими классами, используемыми в качестве аргументов, типов возвратов и исключений, должен быть доступен как в классе клиента, так и на сервере. Один из наиболее эффективных способов сделать это, чтобы упаковать все из них в .jar файл, который может быть позже включен в качестве зависимости в сервере и пом.xml .

Таким образом, поместите весь код в специальный модуль Maven, называемый “api”; Для этого примера мы будем использовать следующие координаты Maven:

com.baeldung
api
1.0-SNAPSHOT

3. Серверное приложение

Давайте построим приложение для системы бронирования, чтобы выставить сервис с помощью Spring Boot.

3.1. Зависимость от Maven

Во-первых, вам нужно убедиться, что ваш проект использует Spring Boot:


    org.springframework.boot
    spring-boot-starter-parent
    2.4.0

Вы можете найти последнюю версию весенней загрузки здесь . Затем нам нужен веб-стартовый модуль:


    org.springframework.boot
    spring-boot-starter-web

И нам нужен модуль определения службы, который мы собрали на предыдущем этапе:


    com.baeldung
    api
    1.0-SNAPSHOT

3.2. Внедрение услуг

Во-первых, мы определяем класс, который реализует интерфейс службы:

public class CabBookingServiceImpl implements CabBookingService {

    @Override public Booking bookPickUp(String pickUpLocation) throws BookingException {
        if (random() < 0.3) throw new BookingException("Cab unavailable");
        return new Booking(randomUUID().toString());
    }
}

Давайте притворимся, что это вероятная реализация. Используя тест со случайным значением, мы сможем воспроизвести оба успешных сценария – когда была найдена доступная кабина и возвращен код бронирования – и неудачные сценарии – когда BookingException брошен, чтобы указать, что нет никакой доступной кабины.

3.3. Разоблачение Службы

Затем нам нужно определить приложение с фасолью типа HttpInvokerServiceЭкспортер в контексте. Он будет заботиться о разоблачении точки входа HTTP в веб-приложении, которое будет позже вызвано клиентом:

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Server {

    @Bean(name = "/booking") HttpInvokerServiceExporter accountService() {
        HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
        exporter.setService( new CabBookingServiceImpl() );
        exporter.setServiceInterface( CabBookingService.class );
        return exporter;
    }

    public static void main(String[] args) {
        SpringApplication.run(Server.class, args);
    }
}

Стоит отметить, что весенний HTTP вызывает использует название HttpInvokerServiceЭкспортер фасоли в качестве относительного пути для URL конечной точки HTTP.

Теперь мы можем начать серверное приложение и поддерживать его в работе во время настройки клиент-приложения.

4. Клиентская заявка

Давайте напишем клиентское заявление.

4.1. Зависимость от Maven

Мы будем использовать то же определение службы и ту же версию Spring Boot, которую мы использовали на серверной стороне. Нам по-прежнему нужна зависимость от веб-стартера, но так как нам не нужно автоматически запускать встроенный контейнер, мы можем исключить стартер Tomcat из зависимости:


    org.springframework.boot
    spring-boot-starter-web
    
        
            org.springframework.boot
            spring-boot-starter-tomcat
        
    

4.2. Осуществление клиентов

Давайте реализуем клиента:

@Configuration
public class Client {

    @Bean
    public HttpInvokerProxyFactoryBean invoker() {
        HttpInvokerProxyFactoryBean invoker = new HttpInvokerProxyFactoryBean();
        invoker.setServiceUrl("http://localhost:8080/booking");
        invoker.setServiceInterface(CabBookingService.class);
        return invoker;
    }

    public static void main(String[] args) throws BookingException {
        CabBookingService service = SpringApplication
          .run(Client.class, args)
          .getBean(CabBookingService.class);
        out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037"));
    }
}

@Bean аннотированный () метод создает экземпляр HttpInvokerProxyFactoryBean . Мы должны предоставить URL-адрес, на который удаленный сервер реагирует через setServiceUrl () метод.

Подобно тому, что мы сделали для сервера, мы также должны предоставить интерфейс службы, которую мы хотим вызвать удаленно через setServiceInterface () метод.

HttpInvokerProxyFactoryBean реализует весенний ФабрикаБин . ФабрикаБин определяется как фасоль, но контейнер Spring IoC будет вводить объект, который он создает, а не сам завод. Вы можете найти более подробную информацию о ФабрикаБин в нашем завод фасоли статьи .

основной () метод bootstraps самостоятельное применение и получает экземпляр CabBookingService из контекста. Под капотом этот объект является всего лишь прокси, созданным HttpInvokerProxyFactoryBean который заботится обо всех технических характеристиках, связанных с выполнением удаленного вызова. Благодаря этому мы теперь можем легко использовать прокси, как мы сделали бы, если бы реализация службы была доступна на местном уровне.

Давайте за запустите приложение несколько раз, чтобы выполнить несколько удаленных вызовов, чтобы проверить, как клиент ведет себя, когда кабина доступна, а когда нет.

5. Пещерный Эмптор

Когда мы работаем с технологиями, которые позволяют удаленных призывов, Есть некоторые подводные камни, мы должны быть хорошо осведомлены.

5.1. Остерегайтесь сетевых исключений

Мы всегда должны ожидать неожиданного, когда мы работаем с ненадежным ресурсом, как сеть.

Допустим, клиент ссылается на сервер, в то время как он не может быть достигнут – либо из-за проблемы сети или потому, что сервер не работает – то Spring Remoting поднимет ДистанционноеДоступиеЭксцепция это RuntimeException.

Компилятор не заставит нас включить вызов в блок try-catch, но мы всегда должны рассмотреть возможность сделать это, чтобы правильно управлять сетевыми проблемами.

5.2. Объекты передаются по стоимости, а не по ссылке

Весенний ремотинг HTTP маршалы метод аргументы и вернул значения для передачи их в сети. Это означает, что сервер действует на копию предоставленного аргумента и клиент действует на копию результата, созданного сервером.

Поэтому мы не можем ожидать, например, что вызов метода на результирующем объекте изменит статус одного и того же объекта на стороне сервера, потому что нет никакого общего объекта между клиентом и сервером.

5.3. Остерегайтесь мелкозернистых интерфейсов

Вызов метода через границы сети значительно медленнее, чем вызов его на объект в том же процессе.

По этой причине, как правило, это хорошая практика для определения служб, которые должны быть удаленно вызваны с грубым зернистых интерфейсов, которые способны завершить бизнес-транзакций, требующих меньшего количества взаимодействий, даже за счет более громоздкий интерфейс.

6. Заключение

На этом примере мы увидели, как легко с Spring Remoting вызвать удаленный процесс.

Решение несколько менее открыто, чем другие широко распространенные механизмы, такие как REST или веб-сервисы, но в сценариях, где все компоненты разрабатываются с Spring, оно может представлять собой жизнеспособную и гораздо более быструю альтернативу.

Как обычно, вы найдете источники более на GitHub .