1. Обзор
В настоящее время интерфейсные и серверные компоненты часто разделяют веб-приложение. Обычно мы предоставляем API в качестве бэкэнд-компонента для интерфейсного компонента или интеграции сторонних приложений.
В таком сценарии важно иметь надлежащие спецификации для внутренних API. В то же время документация по API должна быть информативной, читаемой и простой в использовании.
Кроме того, справочная документация должна одновременно описывать каждое изменение в API. Выполнение этого вручную-утомительное упражнение, поэтому автоматизация процесса была неизбежна.
В этом уроке мы рассмотрим Swagger 2 для веб-службы Spring REST , используя реализацию Springfox спецификации Swagger 2.
Если вы не знакомы с Swagger, посетите его веб-страницу , чтобы узнать больше, прежде чем продолжить этот учебник.
Дальнейшее чтение:
Создайте клиент Spring Boot REST с помощью Swagger
Введение в документы весеннего ОТДЫХА
Введение в Asciidoctor на Java
2. Целевой проект
Создание службы REST, которую мы будем использовать, не входит в рамки этой статьи. Если у вас уже есть подходящий проект, используйте его. Если нет, то эти ссылки-хорошее место для начала:
- Создайте REST API с помощью Spring 4 и статьи Java Config
- Создание веб-службы RESTful
3. Добавление зависимости Maven
Как упоминалось выше, мы будем использовать реализацию Springfox спецификации Swagger. Последнюю версию можно найти на Maven Central .
Чтобы добавить его в ваш проект Maven, нам нужна зависимость в pom.xml файл:
io.springfox springfox-swagger2 2.9.2
3.1. Зависимость от весенней загрузки
Для проектов, основанных на Spring Boot, достаточно добавить одну springfox-boot-starter зависимость :
io.springfox springfox-boot-starter 3.0.0
Мы можем добавить любые другие стартеры, которые нам нужны, с версией, управляемой родителем Spring Boot:
org.springframework.boot spring-boot-starter-parent 2.4.0
4. Интеграция Swagger 2 В Проект
4.1. Конфигурация Java
Конфигурация Swagger в основном сосредоточена вокруг Docket bean:
@Configuration public class SpringFoxConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); } }
После определения компонента Docket его метод select() возвращает экземпляр Api Selector Builder , который предоставляет способ управления конечными точками, предоставляемыми Swagger.
Мы можем настроить предикаты для выбора Обработчика запросов с помощью Селекторов обработчиков запросов и Селекторов путей . Использование any() для обоих сделает документацию для всего нашего API доступной через Swagger.
4.2. Конфигурация Без Пружинной Загрузки
В простых весенних проектах нам нужно явно включить wagger2. Для этого мы должны использовать @EnableSwagger2WebMvc в нашем классе конфигурации :
@Configuration @EnableSwagger2WebMvc public class SpringFoxConfig { }
Кроме того, без Spring Boot у нас нет роскоши автоматической настройки наших обработчиков ресурсов.
Пользовательский интерфейс Swagger добавляет набор ресурсов, которые мы должны настроить как часть класса, расширяющего WebMvcConfigurerAdapter и аннотированного @EnableWebMvc:
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); }
4.3. Проверка
Чтобы убедиться, что Springfox работает, мы можем посетить этот URL-адрес в нашем браузере:
http://localhost:8080/spring-security-rest/api/v2/api-docs
Результатом является ответ JSON с большим количеством пар ключ-значение, который не очень удобочитаем для человека. К счастью, Swagger предоставляет Swagger UI для этой цели.
5. Чванливый ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС
Swagger UI-это встроенное решение, которое значительно упрощает взаимодействие пользователя с документацией API, созданной Swagger.
5.1. Включение пользовательского интерфейса Springfox Swagger
Чтобы использовать пользовательский интерфейс Swagger, нам нужно добавить дополнительную зависимость Maven:
io.springfox springfox-swagger-ui 2.9.2
Теперь мы можем протестировать его в вашем браузере, посетив:
http://localhost:8080/your-app-root/swagger-ui/
В нашем случае, кстати, точный URL будет:
http://localhost:8080/spring-security-rest/api/swagger-ui/
Результат должен выглядеть примерно так:
5.2. Изучение документации Swagger
В ответе Swagger находится список всех контроллеров , определенных в нашем приложении. Нажав на любой из них, вы увидите список допустимых методов HTTP ( DELETE , GET , HEAD , OPTIONS , PATCH , POST , PUT ).
Расширение каждого метода предоставляет дополнительные полезные данные, такие как статус ответа, тип содержимого и список параметров. Также можно попробовать каждый метод с помощью пользовательского интерфейса.
Способность Swagger синхронизироваться с нашей кодовой базой имеет решающее значение. Чтобы продемонстрировать это, мы можем добавить новый контроллер в наше приложение:
@RestController public class CustomController { @RequestMapping(value = "/custom", method = RequestMethod.POST) public String custom() { return "custom"; } }
Теперь, если мы обновим документацию Swagger, мы увидим custom-controller в списке контроллеров. Как мы знаем, в ответе Свэггера показан только один метод ( POST ).
6. Весенний отдых данных
Springfox обеспечивает поддержку Spring Data REST через свою библиотеку springfox-data-rest .
Spring Boot позаботится об автоматической настройке, если обнаружит spring-boot-starter-data-rest на пути к классу .
Теперь давайте создадим сущность с именем User :
@Entity public class User { @Id private Long id; private String firstName; private int age; private String email; // getters and setters }
Затем мы создадим UserRepository , чтобы добавить операции CRUD для объекта User :
@Repository public interface UserRepository extends CrudRepository{ }
Наконец, мы импортируем конфигурацию Spring Data Rest класс в SpringFox Config класс:
@EnableSwagger2WebMvc @Import(SpringDataRestConfiguration.class) public class SpringFoxConfig { //... }
Примечание: Мы использовали аннотацию @EnableSwagger2WebMvc для включения Swagger, поскольку она заменила аннотацию @EnableSwagger2 в версии 3 библиотек.
Давайте перезапустим приложение, чтобы сгенерировать спецификации для API Spring Data REST:
Мы видим, что Springfox сгенерировал спецификации для сущности User с помощью HTTP-методов, таких как GET , POST, PUT, PATCH, и DELETE.
7. Валидация бобов
Springfox также поддерживает проверку bean аннотаций через свою библиотеку springfox-bean-validators .
Во-первых, мы добавим зависимость Maven в ваш pom.xml :
io.springfox springfox-bean-validators 2.9.2
Опять же, если мы используем Spring Boot, нам не нужно явно указывать вышеуказанную зависимость .
Далее, давайте добавим несколько аннотаций проверки, таких как @NotNull и @Min к сущности User :
@Entity public class User { //... @NotNull(message = "First Name cannot be null") private String firstName; @Min(value = 15, message = "Age should not be less than 15") @Max(value = 65, message = "Age should not be greater than 65") private int age; }
Наконец, мы импортируем конфигурацию плагинов BeanValidator в класс SpringFox Config :
@EnableSwagger2 @Import(BeanValidatorPluginsConfiguration.class) public class SpringFoxConfig { //... }
Давайте посмотрим на изменения в спецификациях API:
Здесь мы можем заметить, что Пользователь модель имеет * обязательный на имя . Кроме того, минимальные и максимальные значения определяются для возраста .
8. Плагин
Чтобы добавить определенные функции в спецификации API, мы можем создать плагин Springfox. Плагин может предлагать различные функции, от обогащения моделей и свойств до пользовательских списков API и значений по умолчанию.
Springfox поддерживает создание плагина через свой модуль spi . Модуль spi предоставляет несколько интерфейсов, таких как Model Builder Plugin , Model PropertyBuilder Plugin и ApiListingBuilderPlugin , которые действуют как крючок расширения для реализации пользовательского плагина.
Чтобы продемонстрировать возможности, давайте создадим плагин для обогащения свойства email модели User . Мы будем использовать плагин Model PropertyBuilder интерфейс и установим значения pattern и example .
Во-первых, давайте создадим плагин Аннотации электронной почты класс и переопределим метод supports , чтобы разрешить любой тип документации , такой как Swagger 1.2 и Swagger 2:
@Component @Order(Validators.BEAN_VALIDATOR_PLUGIN_ORDER) public class EmailAnnotationPlugin implements ModelPropertyBuilderPlugin { @Override public boolean supports(DocumentationType delimiter) { return true; } }
Затем мы переопределим метод apply плагина Model PropertyBuilder для установки значений свойств конструктора:
@Override public void apply(ModelPropertyContext context) { Optionalemail = annotationFromBean(context, Email.class); if (email.isPresent()) { context.getSpecificationBuilder().facetBuilder(StringElementFacetBuilder.class) .pattern(email.get().regexp()); context.getSpecificationBuilder().example("[email protected]"); } }
Таким образом, спецификации API покажут шаблон и пример значения свойства, аннотированные аннотацией @Email .
Затем мы добавим @Email аннотацию к объекту User :
@Entity public class User { //... @Email(regexp=".*@.*\\..*", message = "Email should be valid") private String email; }
Наконец, мы включим плагин аннотаций электронной почты в классе Springfox Config , зарегистрировавшись в качестве компонента:
@Import({BeanValidatorPluginsConfiguration.class}) public class SpringFoxConfig { //... @Bean public EmailAnnotationPlugin emailPlugin() { return new EmailAnnotationPlugin(); } }
Давайте проверим Плагин аннотаций электронной почты в действии:
Мы можем видеть, что значение pattern является одним и тем же регулярным выражением (.*@.*\\..*) из электронной почты свойства Пользователя сущности.
Аналогично, значение example ( [email protected] ) такое же, как определено в apply методе EmailAnnotationPlugin .
9. Расширенная конфигурация
Компонент Docket нашего приложения может быть настроен таким образом, чтобы мы могли лучше контролировать процесс создания документации API.
9.1. API фильтрации для ответа Swagger
Не всегда желательно раскрывать документацию для всего API. Мы можем ограничить ответ Swagger, передав параметры в api() и пути() методы класса Docket .
Как видно выше, Селекторы обработчиков запросов позволяют использовать предикаты any или none , но также могут использоваться для фильтрации API в соответствии с базовым пакетом, аннотациями классов и аннотациями методов.
Селекторы путей обеспечивают дополнительную фильтрацию с помощью предикатов, которые сканируют пути запросов нашего приложения. Мы можем использовать any() , none(), regex () или ant() .
В приведенном ниже примере мы проинструктируем Swagger включать только контроллеры из определенного пакета с определенными путями, используя предикат ant() :
@Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("com.baeldung.web.controller")) .paths(PathSelectors.ant("/foos/*")) .build(); }
9.2. Пользовательская информация
Swagger также предоставляет некоторые значения по умолчанию в своем ответе, которые мы можем настроить, такие как “Документация Api”, “Создано по электронной почте контакта” и “Apache 2.0”.
Чтобы изменить эти значения, мы можем использовать метод apiInfo(ApiInfo apiInfo) — класс ApiInfo , содержащий пользовательскую информацию об API:
@Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("com.example.controller")) .paths(PathSelectors.ant("/foos/*")) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfo( "My REST API", "Some custom description of API.", "API TOS", "Terms of service", new Contact("John Doe", "www.example.com", "[email protected]"), "License of API", "API license URL", Collections.emptyList()); }
9.3. Пользовательские методы Ответных сообщений
Swagger позволяет глобально переопределять ответные сообщения методов HTTP через Docket ‘s global Response Message () |/метод.
Во-первых, нам нужно проинструктировать Суэггера не использовать ответные сообщения по умолчанию. Предположим, мы хотим переопределить 500 и 403 ответные сообщения для всех методов GET .
Для этого необходимо добавить некоторый код в блок инициализации Docket (исходный код исключен для ясности):
.useDefaultResponseMessages(false) .globalResponseMessage(RequestMethod.GET, newArrayList(new ResponseMessageBuilder() .code(500) .message("500 message") .responseModel(new ModelRef("Error")) .build(), new ResponseMessageBuilder() .code(403) .message("Forbidden!") .build()));
10. Пользовательский интерфейс Swagger С защищенным OAuth API
Пользовательский интерфейс Swagger предоставляет ряд очень полезных функций, которые мы хорошо рассмотрели здесь. Но мы не можем использовать большинство из них, если наш API защищен и недоступен.
Давайте посмотрим, как мы можем разрешить Swagger доступ к API, защищенному OAuth, используя тип предоставления кода авторизации в этом примере.
Мы настроим Swagger для доступа к нашему защищенному API с помощью Схемы безопасности и Контекста безопасности поддержки:
@Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2).select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build() .securitySchemes(Arrays.asList(securityScheme())) .securityContexts(Arrays.asList(securityContext())); }
10.1. Конфигурация безопасности
Мы определим Конфигурацию безопасности bean в нашей конфигурации Swagger и установим некоторые значения по умолчанию:
@Bean public SecurityConfiguration security() { return SecurityConfigurationBuilder.builder() .clientId(CLIENT_ID) .clientSecret(CLIENT_SECRET) .scopeSeparator(" ") .useBasicAuthenticationWithAccessCodeGrant(true) .build(); }
10.2. Схема обеспечения безопасности
Далее мы определим нашу Схему безопасности ; она используется для описания того, как защищен наш API (базовая аутентификация, OAuth2, …).
В нашем случае здесь мы определим схему OAuth, используемую для защиты нашего сервера ресурсов:
private SecurityScheme securityScheme() { GrantType grantType = new AuthorizationCodeGrantBuilder() .tokenEndpoint(new TokenEndpoint(AUTH_SERVER + "/token", "oauthtoken")) .tokenRequestEndpoint( new TokenRequestEndpoint(AUTH_SERVER + "/authorize", CLIENT_ID, CLIENT_SECRET)) .build(); SecurityScheme oauth = new OAuthBuilder().name("spring_oauth") .grantTypes(Arrays.asList(grantType)) .scopes(Arrays.asList(scopes())) .build(); return oauth; }
Обратите внимание, что мы использовали тип предоставления кода авторизации, для которого нам необходимо предоставить конечную точку токена и URL-адрес авторизации нашего сервера авторизации OAuth2.
И вот области, которые нам нужно определить:
private AuthorizationScope[] scopes() { AuthorizationScope[] scopes = { new AuthorizationScope("read", "for read operations"), new AuthorizationScope("write", "for write operations"), new AuthorizationScope("foo", "Access foo API") }; return scopes; }
Они синхронизируются с областями, которые мы фактически определили в нашем приложении для /foos API.
10.3. Контекст безопасности
Наконец, нам нужно определить Контекст безопасности для нашего примера API:
private SecurityContext securityContext() { return SecurityContext.builder() .securityReferences( Arrays.asList(new SecurityReference("spring_oauth", scopes()))) .forPaths(PathSelectors.regex("/foos.*")) .build(); }
Обратите внимание, как имя, которое мы использовали здесь в ссылке — spring_oauth — синхронизируется с именем, которое мы использовали ранее в SecurityScheme .
10.4. Испытание
Теперь, когда у нас все настроено и готово к работе, давайте взглянем на наш пользовательский интерфейс Swagger и попробуем получить доступ к API Foo.
Мы можем получить доступ к пользовательскому интерфейсу Swagger локально:
http://localhost:8082/spring-security-oauth-resource/swagger-ui.html
Как мы видим, новая кнопка авторизации теперь существует из-за наших конфигураций безопасности:
Когда мы нажимаем кнопку Авторизации, мы видим следующее всплывающее окно, чтобы авторизовать наш пользовательский интерфейс Swagger для доступа к защищенному API:
Обратите внимание, что:
- Мы уже можем видеть CLIENT_ID и CLIENT_SECRET, так как мы предварительно настроили их ранее (но мы все еще можем их изменить).
- Теперь мы можем выбрать области, которые нам нужны.
Вот как помечен защищенный API:
И теперь, наконец, мы можем поразить наш API!
Конечно, почти само собой разумеется, что теперь, когда эта конфигурация безопасности активна, мы должны быть осторожны с тем, как мы раскрываем пользовательский интерфейс Swagger извне.
11. Заключение
В этой статье мы настроили Swagger 2 для создания документации для API Spring REST. Мы также изучили способы визуализации и настройки результатов Swagger. И, наконец, мы рассмотрели простую конфигурацию OAuth для Swagger.
Полную реализацию этого руководства можно найти в проекте GitHub . Чтобы увидеть настройку в загрузочном проекте, проверьте этот модуль GitHub .
Для раздела OAuth код доступен в нашем репозитории spring-security-oauth .
И если вы изучаете отдых с весной , перейдите к уроку 1 из модуля 7, чтобы глубоко погрузиться в настройку Swagger с помощью Spring и Spring Boot.