Spring boot & Swagger 2 UI и пользовательское отображение запросов handlermapping - проблема отображения

У меня есть собственный RequestMappingHandlerMapping, и я использую Springfox-Swagger-UI. После добавления своего пользовательского сопоставления я не могу получить пользовательский интерфейс swagger по адресу http://localhost:8080/swagger-ui.html. Есть идеи?

Это моя конфигурация.

    @Configuration
       public class WebMvcConfig extends WebMvcConfigurationSupport {
    @Override
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        return new ApiVersionRequestMappingHandlerMapping("v");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
          .addResourceHandler("/webjars/**")
          .addResourceLocations("(META-INF/resources/webjars");
    }
}

Вот мой pom.xml:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.hateoas</groupId>
        <artifactId>spring-hateoas</artifactId>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.4.0</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.4.0</version>
    </dependency>
    <dependency>
        <groupId>javax.inject</groupId>
        <artifactId>javax.inject</artifactId>
        <version>1</version>
    </dependency>

5 ответов

Решение

Я наконец-то нашел это! Правильная конфигурация такая:

@Configuration
public class VersioningMappingHandlerConfig {

    @Bean
    public ApiVersionRequestMappingHandlerMapping customMappingHandlerMapping() {
        ApiVersionRequestMappingHandlerMapping handler = new ApiVersionRequestMappingHandlerMapping("v", 1, 1);
        handler.setOrder(-1);
        return handler;
    }

}

Примечание: нет extends WebMvcConfigurationSupport и имя боба customMappingHandlerMapping

Это работает для меня. Переопределение addResourceHandlers вместо регистрации автоконфигурации.

@Configuration
@EnableWebMvc
@EnableSwagger2
public class WebConfig extends WebMvcConfigurerAdapter {

    @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/")
    }
}

Когда вы переопределяете WebMvcConfigurationSupport, вы также переопределяете автоматическую настройку Spring Boot mvc (WebMvcAutoConfiguration). Следовательно, ресурсы, для которых требуется конфигурация весенней загрузки, работать не будут. Это не проблема, специфичная для чванства.

Вы можете найти больше информации об этом здесь:

https://github.com/spring-projects/spring-boot/issues/5004

Как предполагает проблема GitHub, в будущем в нее будут внесены изменения, чтобы облегчить ее. В настоящее время есть некоторые обходные пути, как предлагается там.

Быстрый и грязный способ сделать это - скопировать и вставить класс WebMvcAutoConfiguration в ваш собственный класс, вернуть свой собственный HandlerMapping из метода requestMappingHandlerMapping() EnableWebMvcConfiguration и зарегистрировать копию WebMvcAutoConfiguration в качестве класса автоматической конфигурации. Вы можете увидеть инструкции здесь:

http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html

Убедитесь, что вы поместили свою копию WebMvcAutoConfiguration в какой-то пакет, который не сканируется компонентом и не подбирается автоматически. Это должно быть просто зарегистрировано, как объяснено в ссылке выше.

Также убедитесь, что вы установили порядок своего пользовательского HandlerMapping на 0, прежде чем возвращать его из метода requestMappingHandlerMapping(), например так:

@Bean
@Primary
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
    // Must be @Primary for MvcUriComponentsBuilder to work

    ApiVersionRequestMappingHandlerMapping handlerMapping = new ApiVersionRequestMappingHandlerMapping("v");
    handlerMapping.setOrder(0);
    handlerMapping.setInterceptors(getInterceptors());
    handlerMapping.setContentNegotiationManager(mvcContentNegotiationManager());

    PathMatchConfigurer configurer = getPathMatchConfigurer();
    if (configurer.isUseSuffixPatternMatch() != null) {
        handlerMapping.setUseSuffixPatternMatch(configurer.isUseSuffixPatternMatch());
    }
    if (configurer.isUseRegisteredSuffixPatternMatch() != null) {
        handlerMapping.setUseRegisteredSuffixPatternMatch(configurer.isUseRegisteredSuffixPatternMatch());
    }
    if (configurer.isUseTrailingSlashMatch() != null) {
        handlerMapping.setUseTrailingSlashMatch(configurer.isUseTrailingSlashMatch());
    }
    if (configurer.getPathMatcher() != null) {
        handlerMapping.setPathMatcher(configurer.getPathMatcher());
    }
    if (configurer.getUrlPathHelper() != null) {
        handlerMapping.setUrlPathHelper(configurer.getUrlPathHelper());
    }

    return handlerMapping;
}

Переопределение requestMappingHandlerMapping() из WebMvcConfigurationSupport отключит автоматическую настройку пружинной загрузки. Для добавления пользовательских компонентов MVC вы можете использовать WebMvcRegistrations. Как, для предоставления пользовательских RequestMappingHandlerMappingМы можем переопределить getRequestMappingHandlerMapping()с заказным RequestMappingHandlerMappingизWebMvcRegistrationsAdapter и предоставить его через webMvcRegistrationsHandlerMapping(), Как,

@Configuration
class CustomRequestMappingHandlerMapping {

    @Bean
    public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
        return new WebMvcRegistrationsAdapter() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                return new ApiVersionRequestMappingHandlerMapping("v");
            }
        };
    }
}

В Spring Boot 2.0.0 есть более простой способ добиться этого.

Создать экземпляр WebMvcRegistrations интерфейс как компонент и переопределить соответствующий метод, чтобы вернуть настроенную версию этого объекта. Spring boot будет читать и использовать этот экземпляр.

В этом случае только getRequestMappingHandlerMapping() должен быть переопределен и возвращена пользовательская реализация

Приведенная выше информация является следствием на основе ссылок, предоставленных @Nazaret K. Дополнительная информация по адресу https://github.com/spring-projects/spring-boot/issues/5004

Это можно решить, используя WebMvcConfigurationSupport с добавлением обработчиков ресурсов для swagger:

@Configuration
public class MvcConfiguration extends WebMvcConfigurationSupport {
    @Value("${spring.application.name}")
    private String applicationName;

    //...irrelevant code here

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}
Другие вопросы по тегам