Объедините несколько документов API Swagger в один документ “источник истины”, чтобы разработчики могли более удобно использовать API-интерфейсы .
Распространенная проблема существует для разработчиков сервисов, особенно в среде микросервисов, и ее можно описать следующим образом.
Проблема
“Хорошо сформулированная проблема – это наполовину решенная проблема” – Чарльз Кеттеринг
Представьте, что команда инженеров-программистов работает над группой микросервисов. Интерфейсные разработчики заняты заботой об эстетике и удобстве использования с точки зрения конечного пользователя, и им нужно знать, как подключить приложение к API, чтобы удовлетворить их и, следовательно, требования конечного пользователя.
Что делать, если у меня несколько микросервисов, и я хочу, чтобы мои конечные точки были задокументированы в одном месте? Например, для удобства интерфейсных разработчиков. Сторонней реализацией документации в данном случае является пользовательский интерфейс Swagger. Большинство попыток решить эту проблему, которые были обнаружены во время обзора литературы, зависели от предоставленного Swagger-UI средства выпадающего меню на swagger-ui.html домашняя страница. Это решение означало, что потребителю потребуется вручную получить доступ к каждому документу swagger, чтобы найти подходящую услугу.
Инжир. 1.1 Эта метка “Консолидированная” по умолчанию имеет значение “По умолчанию”; она была изменена в исходном коде. Именно этот раскрывающийся список используется для управления тем, для какого из API просматривать документацию, в других решениях этой проблемы .
Обзор литературы
Возможно, “Прославленный Google” было бы более точным названием для этого раздела, поэтому, оправдав ожидания, я продолжу.
Как упоминалось ранее, попытки решить эту проблему, возникавшие в прошлом, использовали возможности Swagger UI в раскрывающемся меню в правом верхнем углу главной страницы, как показано выше, для выбора API, для которого требуется просмотреть документацию.
Здесь приведен пример, в котором сервер Eureka используется для обнаружения каждой службы, подлежащей документированию. Eureka – это инструмент обнаружения сервисов; дополнительную информацию, касающуюся серверов Eureka, можно найти здесь . Несмотря на элегантность, считалось, что иметь экземпляр Eureka исключительно для этой цели было бы излишним, и потребителю не хватило бы целостного представления обо всех услугах, имеющихся в их распоряжении.
Это еще один пример , который, хотя и не имеет реализации обнаружения сторонних служб, оставляет нам необходимость вручную выбирать и исследовать каждую конечную точку в отдельности.
В этом решении вместо использования стороннего средства обнаружения служб разработчик просто настроил необходимые конечные точки. Это был вариант, который пришел мне в голову, и это придало мне уверенности в том, что я смогу осуществить свое намерение.
Решение
“Решение часто оказывается более красивым, чем головоломка”. – Ричард Докинз
Это решение представляет собой приложение для загрузки с пружиной, которое, также используя Springfox, объединяет все настроенные конечные точки (внутри application.yml
) в один документ swagger. Его относительно просто настроить:
endpoints: # a list of sample base urls, note, omit "/v2/api-docs" - name: UnusedName_key url: https://api_server1.eon.de username: joe_bloggs password: joe_bloggs_pa55w0rd! - name: UnusedName2_key url: https://api_server2.eon.de username: joe_bloggs2 password: joe_bloggs2_pa55w0rd!
Как и в случае с Swagger-UI, процесс документирования ожидает, что Json, описывающий каждую конечную точку, будет присутствовать в настроенных URL-адресах (+ '/v2/api-doc'
). Есть еще два соображения.
Следующее относится, по крайней мере, к версии Swagger 2.x. Необходимо было жестко запрограммировать Json в виде строк, чтобы они были доступны по адресу "/swagger-ресурсы/конфигурация/пользовательский интерфейс"
и "/чванство-ресурсы"
. Инструменты разработки Chrome помогли мне, наряду с некоторыми подсказками коллеги, прийти к этому осознанию. Это будет описано позже, в разделе Конфигурация .
Также было необходимо, чтобы Json, специфичный для наших API, был доступен по адресу '/v2/api-docs'
, что сделало необходимым предоставить Контроллер
с вышеуказанным RequestMapping
, который вернул консолидированное Json
представление всех API, подлежащих документированию, что подводит меня ко второй части нашей реализации.
Консолидация чванства Json
достигается следующим образом: GSON Google используется для создания Карты
“индивидуума” Json
представления документации каждого API.
Следующий шаг – объединить их в одну Карту
, содержащую все данные. Карты
, как вы увидите, очень хорошо поддаются объединению. Разработчик может использовать любые средства, которые он выберет, для получения консолидированного Карты
представления. Это, например, сделает свое дело: после создания переменной с именем оригинал
, которая является Картой
это равно первой Карте
в списке Карт
, подлежащих объединению, которая была передана в функцию глубокого слияния
maps.forEach(map -> { updateInfo(titles, map); // this has no effect in the merging process, // rather it does work relating to the final // title of the document for (Object key : map.keySet()) { if (map.get(key) instanceof Map && original.get(key) instanceof Map) { Map originalChild = (Map) original.get(key); Map newChild = (Map) map.get(key); original.put(key, deepMerge(List.of(originalChild, newChild))); } else if (map.get(key) instanceof List && original.get(key) instanceof List) { List originalChild = (List) original.get(key); List newChild = (List) map.get(key); for (Object each : newChild) { if (!originalChild.contains(each)) { originalChild.add(each); } } } else { original.put(key, map.get(key)); } } }); return original;
GSON возвращает свой собственный Реализация Map
для представления пар ключ-значение Json, это позволяет использовать рекурсию, как указано выше, для объединения всех карт в одну супер-карту , которая затем преобразуется обратно, снова используя GSON Google, в Json для отображения, как если бы это был единый API, отображаемый пользовательским интерфейсом Swagger. Они будут отображаться в алфавитном порядке, сгруппированные по API.
Конфигурация
Конфигурация этого приложения для загрузки консолидированной пружины с чванством обрабатывается внутри application.yml
. Этот раздел конфигурации относится, в основном, к конфигурации Swagger-UI.
Json, возвращаемый при отображении запроса “/swagger-ресурсы/конфигурация/пользовательский интерфейс”, содержит, среди прочего, флаг “фильтр”, который, несмотря на то, что его значение является логическим, по умолчанию имеет значение true.
Я воспользовался возможностью удалить это свойство, приняв значение по умолчанию, учитывая, что для поиска может потребоваться большое количество консолидированных API. Единственное свойство, необходимое для правильного отображения документа Swagger, – это “supportedSubmitMethods”, и даже это значение по умолчанию равно все когда для него установлен пустой список. Я явно добавил все методы для целей документации.
// /swagger-resources/configuration/ui uiConfigurationMap.put("supportedSubmitMethods", Arrays.asList( "get", "put", "post", "delete", "options", "head", "patch", "trace" ));
Я должен выделить вышеупомянутую часть конфигурации (или ее отсутствие), “фильтр”. Именно возможность фильтрации, представленная здесь, является веским аргументом в пользу этого метода консолидации, в зависимости от раскрывающегося списка, который используется в других усилиях по консолидации.
Как и в приведенной выше конфигурации, есть возможность изменить некоторые статические значения, появляющиеся в готовом документе, это достигается, по сути, переопределением Json, расположенного по адресу или возвращаемого по пути “/swagger-ресурсы”, это также жестко запрограммировано. В обоих случаях вышеупомянутого жесткого кодирования конфигурации используется следующий шаблон программного кодирования: “защищенная статическая” строка, например |/Ресурс чванства , был объявлен. Обратите внимание, это не объявлено окончательным; это потому, что позже оно будет установлено равным jsonized Карта
, заполненная внутри статического блока, а затем возвращенная пользовательским контроллером.
// /swagger-resources static { MapswaggerResourceMap = new LinkedTreeMap<>(); swaggerResourceMap.put("name", "Consolidated"); swaggerResourceMap.put("url", "/v2/api-docs"); swaggerResourceMap.put("swaggerVersion", "2.0"); swaggerResource = "[" + new Gson().toJson(swaggerResourceMap) + "]"; }
Заголовок документа по умолчанию представляет собой просто разделенный точкой с запятой список всех рекомендуемых API. Этот список сначала составляется и размещается в виде списка на сводной Карте
с ключом “информация” (info.title). Затем этот список используется для создания заголовка следующим образом:
map.get(INFO).put(TITLE, String.join(SEMICOLON, (Iterable extends CharSequence>) map.get(INFO).get(TITLE)))
Кроме того, этот заголовок можно настроить, включив следующее в приложение.yml
.
swagger-vars: docTitle : 'Consolidated Doc, for example'
Готовый Продукт
На следующем снимке экрана изображена консолидация пользовательского интерфейса swagger из четырех подключенных API, при этом пользователь с большим эффектом использует функциональность фильтра.
Рис. 1.2 Снимок экрана домашней страницы с включенной фильтрацией .
Зависимости
Для того чтобы это скомпилировать, потребуется java 12.
Внутри pom.xml , Я объявил о следующих примечательных зависимостях.
Springfox Это позволяет взаимодействовать между Spring и Swagger.
io.springfox springfox-swagger-ui 2.9.2
GSON от Google Это используется для отмены сортировки строк json, а затем для повторного маршалирования объединенной карты
обратно в консолидированную строку Json.
com.google.code.gson gson 1.4
Краткое описание процесса
Предоставьте пользователю механизм настройки URL-адресов для консолидируемых API.
Возьмите Json каждого из целевых API-интерфейсов; затем мы преобразуем каждую строку Json в некоторую реализацию Map
, затем мы объединяем эти Карты
. Наконец, мы преобразуем это объединенное Сопоставьте
с Json и сделайте этот Json доступным для отображения пользовательского интерфейса swagger.
Между тем, Springfox также сделал бы другие Json доступными для Swagger-Ui на основе аннотаций, предоставленных разработчиком. Мы просто создаем контроллеры, которые управляют компиляцией этих метаданных.
Докер
В Docker Hub доступен образ docker, включающий приложение spring boot, и, создав контейнер из этого образа, вы увидите рабочий пример этого приложения, которое объединяет 4 API.
Чтобы создать контейнер из этого образа, вы должны сначала установить docker на свой локальный компьютер. Затем просто выполните следующую команду:
$> docker container run -p 80:8080 declantreanor/swaggerui:final
Затем приложение будет доступно для просмотра по URL-адресу http://localhost/swagger-ui.html
Имя пользователя/пароль, которые вам будет предложено ввести, – боб/боб.
Автономный режим
Существует автономный режим; Предполагая, что была предпринята хотя бы одна попытка онлайн, после этого Json
, захваченный во время этой онлайн-попытки, будет использоваться для будущих попыток, если, конечно, эта попытка не будет предпринята онлайн, и в этом случае она будет проходить в обычном режиме.
Существуют четкие варианты использования этой функции, которые были достигнуты с помощью простого ввода-вывода файлов.
Открытый Исходный код
Этот инструмент доступен для использования в соответствии с лицензионным соглашением с открытым исходным кодом; и его можно клонировать отсюда: Этот инструмент доступен для использования в соответствии с лицензионным соглашением с открытым исходным кодом; и его можно клонировать отсюда:
Излишне говорить, что это приложение объединит любую группу документации API swagger , а не только Java.
Оригинал: “https://dev.to/eon/how-to-consolidate-api-documentation-in-a-spring-boot-microservices-environment-dgd”