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 доступны многие другие шаблоны интеграции и манипуляции с данными: