Swagger 2 docs API with examples

Документация REST сервисов часто устаревает, при каких то небольших изменениях в коде. Для поддерживания документации сервисов в актуальном виде есть замечательный инструмент Swagger. Генерируется и обновляется автоматически, поддерживает форматы JSON, либо YAML.

Использовал:

Swagger Spring Boot H2 In-memory Database Spring Data JPA

Необходимо выполнить:
– Реализовать REST сервис на Spring Boot;
– Подключить фреймворк Swagger UI;

Для сборки Spring проекта удобно использовать Spring Initializr

Задаем структуру проекта и реализовываем небольшой REST сервис.

Далее необходимо добавить несколько зависимостей в pom.xml

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

Где artifactId springfox-swagger2 подключение документации по JSON API для Spring-приложений.
artifactId springfox-swagger-ui для возможности подключения UI интерфейса.

Для проекта Spring Boot необходимо добавить только один Bean с конфигурацией Swagger:

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }
}

Bean Docket содержит конфигурацию для Swagger 2, как по умолчанию так и с возможностью кастомизации.
Где,
@Configuration Spring аннотация, сообщает контейнеру Spring о наличии одного или нескольких компонентов, с которыми необходимо работать во время выполнения, также возможно конфигурирование через xml файлы;
@EnableSwagger2 аннотация включает поддержку Swagger 2 в классе для нашего Spring Boot приложения. Должна сопровождаться аннотацией @Configuration;
@Bean Стандартная Spring аннотация, создает и регистрирует компонент;
Docket основной механизм настройки API, инициализирован для спецификации Swagger. Интерфейс предоставляет конфигурацию по умолчанию и удобные методы для настройки;
.select() метод возвращает экземпляр ApiSelectorBuilder, который предоставляет способ управления endpoints, предоставляемыми Swagger;
.apis() определяет базовый пакет, который будет сканирован и будут созданы API для всех классов в нем.
Примеры:
.apis(RequestHandlerSelectors.any()) указывает на генерацию документации для всех пакетов.
.apis(RequestHandlerSelectors.basePackage(“ru.gotoqa.GameOfThronesService”)) ограничено пакетом GameOfThronesService.

.paths() метод дополнительно определяет, для каких путей в наших API мы хотим создать документацию.
Примеры:
.paths(PathSelectors.any()) включает все endpoints для создания документации.
.paths(regex(“/version1.*”)) все endpoints которые попадают под маску “/version1.*” будут задокументированы.
.paths(Predicates.or(PathSelectors.regex(“/version1.*”),PathSelectors.regex(“/version2.*”))) ограничение по нескольким endpoints.

Немного кастомизации из коробки

Через метод .apiInfo(apiInfo()) можно добавить информацию о владельце, компании etc.

    private ApiInfo apiInfo() {
        return new ApiInfo(
                "REST API Game Of Thrones Service",
                "",
                "API 1.0",
                "http://gotoqa.ru/cv/",
                new Contact("Roman", "www.gotoqa.ru", "n@company.com"),
                "License of API", "http://gotoqa.ru", Collections.emptyList());
    }
String title, 
String description, 
String version, 
String termsOfServiceUrl, 
Contact contact, 
String license, 
String licenseUrl, 
Collection<VendorExtension> vendorExtensions

Swagger Core аннотации для контроллера. Doc’s

@Api Помечает класс как Swagger resource.
@ApiModel Provides additional information about Swagger models.
@ApiModelProperty Adds and manipulates data of a model property.
@ApiOperation Описание HTTP метода
@ApiParam Adds additional meta-data for operation parameters.
@ApiResponse Describes a possible response of an operation.
@ApiResponses

A wrapper to allow a list of multiple ApiResponse objects.

@RestController
//@RequestMapping("/gameofthrones")
@Api(value="GameOfThronesService", description="Actor WEB Service")
public class ActorController {
 
    @Autowired
    private ActorRepository actorRepository;
 
    @GetMapping("/version1/actors")
    @ApiOperation(value = "Returns list of all Actors")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Successfully retrieved list"),
            @ApiResponse(code = 401, message = "You are not authorized to view the resource"),
            @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"),
            @ApiResponse(code = 404, message = "The resource you were trying to reach is not found")
    }
    )
    List<Actor> findAll(){
        return actorRepository.findAll();
    }
 
    @ResponseStatus(HttpStatus.CREATED)
    @PostMapping("/version1/actors")
    Actor newActor(@RequestBody Actor actor){
        return actorRepository.save(actor);
    }
 
    @GetMapping("/version1/actors/{id}")
    @ApiOperation(value = "Returns Actor data")
    Actor findOne(@ApiParam("Id of the Actors to be obtained. Cannot be empty.") @PathVariable Long id) {
        return actorRepository.findById(id)
                .orElseThrow(() -> new ActorNotFoundException(id));
    }

Аннотация @ApiModelProperty используется для описания модели БД.

@Getter
@Setter
@Entity
@NoArgsConstructor
public class Actor {
 
    @Id
    @GeneratedValue
    @ApiModelProperty(notes = "The database generated actor's ID")
    private Long id;
    @ApiModelProperty(notes = "Actor first name", required = true)
    private String firstName;
    @ApiModelProperty(notes = "Actor second name", required = true)
    private String lastName;
    @ApiModelProperty(notes = "Actor birthDay", required = true)
    private String birthDay;
 
    public Actor(String firstName, String lastName, String birthDay) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.birthDay = birthDay;
    }
}

В завершение пример UI работы Swagger (/swagger-ui.html)

Рассмотренные выше примеры не полностью охватывают функционал Swagger фреймворка. Из особо примечательных стоит упомянуть про возможность переопределения стандартных ответов HTTP методов и авторизация. Так как оба случая частные расписывать их использование не стал.

Ссылка на полную версию проекта на GitHub:
Github GameOfThronesService

Releated Post