Всем привет!!! Это мой первый пост на Хабре и я хочу поделиться с вами своим опытом в исследование нового для себя фреймворка.
Мне предоставился момент выбрать тему и подготовить презентацию для своей команды. Вдохновившись спикером Евгений Маренков, я решил выбрать данную тему. В процессе подготовки, я облазил много статей и репозиториев что бы компактно и эффективно донести нужную информацию.
Сейчас хочу поделиться ею в надежде, что кому-то она поможет в изучение Swagger (OpenApi 3.0)
Введение
Я на 99% уверен у многих из вас были проблемы с поиском документации для нужного вам контроллера. Многие если и находили ее быстро, но в конечном итоге оказывалось что она работает не так как описано в документации, либо вообще его уже нет.
Сегодня я вам докажу, что есть способы поддерживать документацию в актуальном виде и в этом мне будет помогать Open Source framework от компании SmartBear под названием Swagger, а с 2016 года он получил новое обновление и стал называться OpenAPI Specification.
Swagger - это фреймворк для спецификации RESTful API. Его прелесть заключается в том, что он дает возможность не только интерактивно просматривать спецификацию, но и отправлять запросы – так называемый Swagger UI.
Также возможно сгенерировать непосредственно клиента или сервер по спецификации API Swagger, для этого понадобиться Swagger Codegen.
Основные подходы
Swagger имеет два подхода к написанию документации:
Документация пишется на основании вашего кода.
Данный подход позиционируется как "очень просто". Нам достаточно добавить несколько зависимостей в проект, добавить конфигурацию и уже мы будем иметь нужную документацию, хоть и не настолько описанной какою мы хотели.
Код проекта становиться не очень читабельным от обилия аннотаций и описания в них.
Вся документация будет вписана в нашем коде (все контроллеры и модели превращаются в некий Java Swagger Code)
Подход не советуют использовать, если есть возможности, но его очень просто интегрировать.
Документация пишется отдельно от кода.
Данный подход требует знать синтаксис Swagger Specification.
Документация пишется либо в JAML/JSON файле, либо в редакторе Swagger Editor.
Swagger Tools
Swagger или OpenAPI framework состоит из 4 основных компонентов:
Swagger Core - позволяет генерировать документацию на основе существующего кода основываясь на Java Annotation.
Swagger Codegen - позволит генерировать клиентов для существующей документации.
Swagger UI - красивый интерфейс, который представляет документацию. Дает возможность просмотреть какие типы запросов есть, описание моделей и их типов данных.
Swagger Editor - Позволяет писать документацию в YAML или JSON формата.
Теперь давайте поговорим о каждом компоненте отдельно.
Swagger Core
Swagger Code - это Java-реализация спецификации OpenAPI
Для того что бы использовать Swagger Core во все орудие, требуется:
Java 8 или больше
Apache Maven 3.0.3 или больше
Jackson 2.4.5 или больше
Что бы внедрить его в проект, достаточно добавить две зависимости:
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.2</version>
</dependency>
Также можно настроить maven плагин, что бы наша документация при сборке проект генерировалсь в YAML
<plugin>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-maven-plugin</artifactId>
<version>0.3</version>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<apiDocsUrl>http://localhost:8080/v3/api-docs</apiDocsUrl>
<outputFileName>openapi.yaml</outputFileName>
<outputDir>${project.build.directory}</outputDir>
</configuration>
</plugin>
Дальше нам необходимо добавить конфиг в проект.
Для конфигурации Swagger необходимо добавить два бина. Где нам нужно будет описать название приложения, версию нашего API, так же можно добавить контакт разработчик который отвечает за данные API
@Bean
public GroupedOpenApi publicUserApi() {
return GroupedOpenApi.builder()
.group("Users")
.pathsToMatch("/users/**")
.build();
}
@Bean
public OpenAPI customOpenApi(@Value("${application-description}")String appDescription,
@Value("${application-version}")String appVersion) {
return new OpenAPI().info(new Info().title("Application API")
.version(appVersion)
.description(appDescription)
.license(new License().name("Apache 2.0")
.url("http://springdoc.org"))
.contact(new Contact().name("username")
.email("test@gmail.com")))
.servers(List.of(new Server().url("http://localhost:8080")
.description("Dev service"),
new Server().url("http://localhost:8082")
.description("Beta service")));
}
После добавление нужных нам зависимостей, у нас появятся новые аннотация с помощью которых можно документировать наш код.
Вот некоторые из них:
@Operation - Описывает операцию или обычно метод HTTP для определенного пути.
@Parameter - Представляет один параметр в операции OpenAPI.
@RequestBody - Представляет тело запроса в операции
@ApiResponse - Представляет ответ в операции
@Tag - Представляет теги для операции или определения OpenAPI.
@Server - Представляет серверы для операции или для определения OpenAPI.
@Callback - Описывает набор запросов
@Link - Представляет возможную ссылку времени разработки для ответа.
@Schema - Позволяет определять входные и выходные данные.
@ArraySchema - Позволяет определять входные и выходные данные для типов массивов.
@Content - Предоставляет схему и примеры для определенного типа мультимедиа.
@Hidden - Скрывает ресурс, операцию или свойство
Примеры использования:
@Tag(name = "User", description = "The User API")
@RestController
public class UserController {}
@Operation(summary = "Gets all users", tags = "user")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Found the users",
content = {
@Content(
mediaType = "application/json",
array = @ArraySchema(schema = @Schema(implementation = UserApi.class)))
})
})
@GetMapping("/users")
public List<UserApi> getUsers()
Swagger Codegen
Swagger Codegen - это проект, который позволяет автоматически создавать клиентские библиотеки API (создание SDK), заглушки сервера и документацию с учетом спецификации OpenAPI.
В настоящее время поддерживаются следующие языки / фреймворки:
API clients:
Java (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured)
Kotlin
Scala (akka, http4s, swagger-async-httpclient)
Groovy
Node.js (ES5, ES6, AngularJS with Google Closure Compiler annotations)
Haskell (http-client, Servant)
C# (.net 2.0, 3.5 or later)
C++ (cpprest, Qt5, Tizen)
Bash
Server stub:
Java (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy, Play Framework, PKMST)
Kotlin
C# (ASP.NET Core, NancyFx)
C++ (Pistache, Restbed)
Haskell (Servant)
PHP (Lumen, Slim, Silex, Symfony, Zend Expressive)
Python (Flask)
NodeJS
Ruby (Sinatra, Rails5)
Rust (rust-server)
API documentation generators:
HTML
Confluence Wiki
Other:
JMeter
Что бы внедрить его в проект, достаточно добавить зависимость, если используете Swagger:
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>2.4.18</version>
</dependency>
и если используете OpenApi 3.0, то:
<dependency>
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.24</version>
</dependency>
Можно настроить maven плагин, и уже на процессе сборки мы можем сгенерировать нужный для нас клиент либо мок сервиса.
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>3.3.4</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<generatorName>spring</generatorName>
<inputSpec>${project.basedir}/src/main/resources/api.yaml</inputSpec>
<output>${project.build.directory}/generated-sources</output>
<apiPackage>com.api</apiPackage>
<modelPackage>com.model</modelPackage>
<supportingFilesToGenerate>
ApiUtil.java
</supportingFilesToGenerate>
<configOptions>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<artifactVersion>${project.version}</artifactVersion>
<delegatePattern>true</delegatePattern>
<sourceFolder>swagger</sourceFolder>
<library>spring-mvc</library>
<interfaceOnly>true</interfaceOnly>
<useBeanValidation>true</useBeanValidation>
<dateLibrary>java8</dateLibrary>
<java8>true</java8>
</configOptions>
<ignoreFileOverride>${project.basedir}/.openapi-generator-ignore</ignoreFileOverride>
</configuration>
</execution>
</executions>
</plugin>
Также все это можно выполнить с помощью командной строки.
Запустив джарник codegen и задав команду help можно увидеть команды, которые предоставляет нам Swagger Codegen:
config-help - Справка по настройке для выбранного языка
generate - Сгенерировать код с указанным генератором
help - Отображение справочной информации об openapi-generator
list - Перечисляет доступные генераторы
meta - Генератор для создания нового набора шаблонов и конфигурации для Codegen. Вывод будет основан на указанном вами языке и будет включать шаблоны по умолчанию.
validate - Проверить спецификацию
version - Показать информацию о версии, используемую в инструментах
Для нас самые нужные команды это validate, которая быстро проверять на валидность спецификации и generate, с помощью которой мы можем сгенерировать Client на языке Java
java -jar openapi-generator-cli-4.3.1.jar validate -i openapi.yaml
java -jar openapi-generator-cli-4.3.1.jar generate -i openapi.yaml -g java --library jersey2 -o client-gener-new
Swagger UI
Swagger UI - позволяет визуализировать ресурсы API и взаимодействовать с ними без какой-либо логики реализации. Он автоматически генерируется из вашей спецификации OpenAPI (ранее известной как Swagger), а визуальная документация упрощает внутреннюю реализацию и использование на стороне клиента.
Вот пример Swagger UI который визуализирует документацию для моего pet-project:
Нажавши на кнопку "Try it out", мы можем выполнить запрос за сервер и получить ответ от него:
Swagger Editor
Swagger Editor - позволяет редактировать спецификации Swagger API в YAML внутри вашего браузера и просматривать документацию в режиме реального времени. Затем можно сгенерировать допустимые описания Swagger JSON и использовать их с полным набором инструментов Swagger (генерация кода, документация и т. Д.).
На верхнем уровне в спецификации OpenAPI 3.0 существует восемь объектов. Внутри этих верхнеуровневых объектов есть много вложенных объектов, но на верхнем уровне есть только следующие объекты:
openapi
info
servers
paths
components
security
tags
externalDocs
Для работы над документацией со спецификацией используется онлайн-редактор Swagger Редактор Swagger имеет разделенное представление: слева пишем код спецификации, а справа видим полнофункциональный дисплей Swagger UI. Можно даже отправлять запросы из интерфейса Swagger в этом редакторе.
Редактор Swagger проверит контент в режиме реального времени, и укажет ошибки валидации, во время кодирования документа спецификации. Не стоит беспокоиться об ошибках, если отсутствуют X-метки в коде, над которым идет работа.
Первым и важным свойством для документации это openapi. В объекте указывается версия спецификации OpenAPI. Для Swagger спецификации это свойство будет swagger:
openapi: "3.0.2"
Объект info содержит основную информацию о вашем API,включая заголовок, описание, версию, ссылку на лицензию, ссылку на обслуживания и контактную информацию. Многие из этих свойство являются не обязательными.
info:
title: "OpenWeatherMap API"
description: "Get the current weather, daily forecast for 16 days, and a three-hour-interval forecast for 5 days for your city."
version: "2.5"
termsOfService: "https://openweathermap.org/terms"
contact:
name: "OpenWeatherMap API"
url: "https://openweathermap.org/api"
email: "some_email@gmail.com"
license:
name: "CC Attribution-ShareAlike 4.0 (CC BY-SA 4.0)"
url: "https://openweathermap.org/price"
Объект servers указывает базовый путь, используемый в ваших запросах API. Базовый путь - это часть URL, которая находится перед конечной точкой. Объект servers обладает гибкой настройкой. Можно указать несколько URL-адресов:
servers:
- url: https://api.openweathermap.org/data/2.5/
description: Production server
- url: http://beta.api.openweathermap.org/data/2.5/
description: Beta server
- url: http://some-other.api.openweathermap.org/data/2.5/
description: Some other server
paths - Это та же “конечная точка” в соответствии с терминологии спецификации OpenAPI. Каждый объект path содержит объект operations - это методы GET, POST, PUT, DELETE:
paths:
/weather:
get:
Объект components уникален среди других объектов в спецификации OpenAPI. В components хранятся переиспользуемые определения, которые могут появляться в нескольких местах в документе спецификации. В нашем сценарии документации API мы будем хранить детали для объектов parameters и responses в объекте components
Conclusions
Документация стала более понятней для бизнес юзера так и для техническим юзерам (Swagger UI, Open Specifiation)
Может генерировать код для Java, PHP, .NET, JavaScrypt (Swager Editor, Swagger Codegen)
Можно проверять насколько совместимы изменения. Можно настраивать это в дженкинсе
Нет ни какой лишней документации к коде, код отдельно, документация отдельно
kolbaskinmax
Удобно генерацию документации совместить с авто-тестами API. У вас всегда будет целостный проект с актуальными доками.