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

Apache Camel с пружинным ботинком

Узнайте о Apache Camel с помощью Spring Boot.

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

1. Обзор

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

Эти мосты между услугами и технологиями называются маршрутами. Маршруты реализуются на движке ( CamelContext ), и они взаимодействуют с так называемыми “сообщениями обмена”.

2. Зависимости Maven

Для начала нам нужно будет включить зависимости для Spring Boot, Camel, Rest API с Swagger и JSON:


    
        org.apache.camel
        camel-servlet-starter
        ${camel.version}
    
    
        org.apache.camel
        camel-jackson-starter
        ${camel.version}
    
    
        org.apache.camel
        camel-swagger-java-starter
        ${camel.version}
    
    
        org.apache.camel
        camel-spring-boot-starter
        ${camel.version}
        
    
        org.springframework.boot
        spring-boot-starter-web
        ${spring-boot-starter.version}
    

Последние версии зависимостей Apache Camel можно найти здесь .

3. Основной Класс

Давайте сначала создадим Spring Boot Приложение :

@SpringBootApplication
@ComponentScan(basePackages="com.baeldung.camel")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

4. Конфигурации верблюда для пружинного ботинка

Теперь давайте настроим наше приложение с помощью Spring, начиная с файлов конфигурации (свойств).

Например, давайте настроим журнал для нашего приложения в файле application.properties в файле src/main/resources :

logging.config=classpath:logback.xml
camel.springboot.name=MyCamel
server.address=0.0.0.0
management.address=0.0.0.0
management.port=8081
endpoints.enabled = true
endpoints.health.enabled = true

В этом примере показан файл application.properties , который также задает путь к конфигурации обратного входа. Установив IP-адрес на “0.0.0.0”, мы полностью ограничиваем доступ admin и management на веб-сервере, предоставляемом Spring Boot. Кроме того, мы предоставляем необходимый сетевой доступ к конечным точкам наших приложений, а также к конечным точкам проверки работоспособности.

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

server:
  port: 8080
camel:
  springboot:
    name: ServicesRest
management:
  port: 8081
endpoints:
  enabled: false
  health:
    enabled: true
quickstart:
  generateOrderPeriod: 10s
  processOrderPeriod: 30s

5. Настройка сервлета Camel

Один из способов начать использовать Camel-зарегистрировать его как сервлет, чтобы он мог перехватывать HTTP-запросы и перенаправлять их в наше приложение.

Как уже упоминалось ранее, начиная с версии 2.18 и ниже Camel, мы можем воспользоваться преимуществами нашего application.yml – путем создания параметра для нашего конечного URL-адреса. Позже он будет введен в наш Java-код:

baeldung:
  api:
    path: '/camel'

Возвращаясь к нашему классу Application , нам нужно зарегистрировать сервлет Camel в корне нашего контекстного пути, который будет введен из ссылки baeldung.api.path в application.yml при запуске приложения:

@Value("${baeldung.api.path}")
String contextPath;

@Bean
ServletRegistrationBean servletRegistrationBean() {
    ServletRegistrationBean servlet = new ServletRegistrationBean
      (new CamelHttpTransportServlet(), contextPath+"/*");
    servlet.setName("CamelServlet");
    return servlet;
}

Начиная с версии 2.19 Camel, эта конфигурация была удалена, поскольку сервлет Camel по умолчанию установлен в “/camel” .

6. Построение маршрута

Давайте начнем создавать маршрут, расширив класс RouteBuilder из Camel и установив его как @Component , чтобы процедура сканирования компонентов могла найти его во время инициализации веб-сервера:

@Component
class RestApi extends RouteBuilder {
    @Override
    public void configure() {
        CamelContext context = new DefaultCamelContext();
        
        restConfiguration()...
        rest("/api/")... 
        from("direct:remoteService")...
    }
}

В этом классе мы переопределяем метод configure() из класса Camel RouteBuilder .

Camel всегда нужен CamelContext экземпляр – основной компонент, в котором хранятся входящие и исходящие сообщения.

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

6.1. Маршрут конфигурации rest()

Затем мы создаем НОВОЕ объявление для конечных точек, которые мы планируем создать в методе rest Configuration() :

restConfiguration()
  .contextPath(contextPath) 
  .port(serverPort)
  .enableCORS(true)
  .apiContextPath("/api-doc")
  .apiProperty("api.title", "Test REST API")
  .apiProperty("api.version", "v1")
  .apiContextRouteId("doc-api")
  .component("servlet")
  .bindingMode(RestBindingMode.json)

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

Затем мы добавим документацию Swagger к URI, названию и версии, которые мы ранее установили. По мере создания методов/конечных точек для нашей веб-службы REST документация Swagger будет автоматически обновляться.

Этот контекст Swagger сам по себе является верблюжьим маршрутом, и мы можем увидеть некоторую техническую информацию о нем в журнале сервера во время процесса запуска. Наш пример документации по умолчанию подается по адресу http://localhost:8080/camel/api-doc.

6.2. Маршрут отдыха()

Теперь давайте реализуем вызов метода rest() из метода configure () , перечисленного выше:

rest("/api/")
  .id("api-route")
  .consumes("application/json")
  .post("/bean")
  .bindingMode(RestBindingMode.json_xml)
  .type(MyBean.class)
  .to("direct:remoteService");

Этот метод довольно прост для тех, кто знаком с API. id – это идентификация маршрута внутри CamelContext . Следующая строка определяет тип MIME. Режим привязки определен здесь, чтобы показать, что мы можем установить режим в конфигурации rest() .

Метод post() добавляет операцию в API, генерируя конечную точку ” POST/be “, в то время как MyBean (обычный компонент Java с целочисленным идентификатором и строковым именем ) определяет ожидаемые параметры.

Аналогично, действия HTTP, такие как GET, PUT и DELETE, также доступны в форме get() , put() , delete() .

Наконец, метод to() создает мост к другому маршруту. Здесь он говорит Верблюду искать в своем контексте/движке другой маршрут, который мы собираемся создать, – который называется и определяется значением/id ” direct:… “, соответствующим маршруту, определенному в методе from () .

6.3. Маршрут from() С преобразованием()

При работе с Camel маршрут получает параметры, а затем преобразует, преобразует и обрабатывает эти параметры. После этого он отправляет эти параметры на другой маршрут, который пересылает результат на желаемый вывод (файл, базу данных, SMTP-сервер или ответ REST API).

В этой статье мы создаем только другой маршрут внутри метода configure () , который мы переопределяем. Это будет маршрут назначения для нашего последнего маршрута to() :

from("direct:remoteService")
  .routeId("direct-route")
  .tracing()
  .log(">>> ${body.id}")
  .log(">>> ${body.name}")
  .transform().simple("Hello ${in.body.name}")
  .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200));

Метод from() следует тем же принципам и имеет много тех же методов, что и метод rest () , за исключением того, что он использует контекстные сообщения верблюда. Это причина для параметра ” direct-route “, который создает ссылку на вышеупомянутый метод rest().to() .

Доступны многие другие преобразования , включая извлечение в виде примитивов Java (или объектов) и отправку их на уровень сохранения. Обратите внимание, что маршруты всегда считываются из входящих сообщений, поэтому цепные маршруты будут игнорировать исходящие сообщения.

Наш пример готов, и мы можем попробовать его:

  • Выполните команду приглашения: mvn spring-boot:run
  • Сделайте запрос на публикацию в http://localhost:8080/camel/api/bean с параметрами заголовка: Тип содержимого: приложение/json и полезная нагрузка {“id”: 1,”имя”: “Мир”}
  • Мы должны получить код возврата 201 и ответ: Привет, Мир

6.4. ПРОСТОЙ язык Сценариев

В примере выводится ведение журнала с использованием метода tracing () . Обратите внимание, что мы использовали заполнители $ {} ; они являются частью языка сценариев, принадлежащего Camel под названием SIMPLE. Он применяется к сообщениям, которыми обмениваются по маршруту, например к телу входящего сообщения.

В нашем примере мы используем SIMPLE для вывода в журнал атрибутов компонента, которые находятся внутри тела сообщения Camel.

Мы также можем использовать его для выполнения простых преобразований, как было показано с помощью метода transform () .

6.5. Маршрут from() С процессом()

Давайте сделаем что – то более значимое, например вызов уровня сервиса для возврата обработанных данных. ПРОСТОЙ не предназначен для тяжелой обработки данных, поэтому давайте заменим transform() на process() метод:

from("direct:remoteService")
  .routeId("direct-route")
  .tracing()
  .log(">>> ${body.id}")
  .log(">>> ${body.name}")
  .process(new Processor() {
      @Override
      public void process(Exchange exchange) throws Exception {
          MyBean bodyIn = (MyBean) exchange.getIn().getBody();
          ExampleServices.example(bodyIn);
          exchange.getIn().setBody(bodyIn);
      }
  })
  .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200));

Это позволяет нам извлечь данные в компонент, тот же самый, который ранее был определен в методе type () , и обработать его в нашем слое ExampleServices .

Поскольку ранее мы установили binding Mode() в JSON, ответ уже находится в правильном формате JSON, сгенерированном на основе нашего POJO. Это означает, что для класса Example Services :

public class ExampleServices {
    public static void example(MyBean bodyIn) {
        bodyIn.setName( "Hello, " + bodyIn.getName() );
        bodyIn.setId(bodyIn.getId() * 10);
    }
}

Тот же HTTP-запрос теперь возвращается с кодом ответа 201 и телом: {“id”: 10,”name”: “Hello, World”} .

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

С помощью нескольких строк кода нам удалось создать относительно полное приложение. Все зависимости создаются, управляются и запускаются автоматически с помощью одной команды. Более того, мы можем создавать API, которые связывают воедино все виды технологий.

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

Этот пример REST можно найти на GitHub .

Наконец, помимо API filter() , process() , transform () и marshall () , в Camel доступны многие другие шаблоны интеграции и манипуляции с данными: