自定义RequestMappingHandlerMapping会导致Swagger出错

时间:2017-03-15 03:55:11

标签: spring spring-boot annotations springfox

我使用最新版本的Spring创建了一个自定义<cflocation url="excelPath">,如下所示我可以定义自定义版本注释。

WebConfiguration,

RequestMappingHandlerMapping

CustomRequestMappingHandlerMapping,

@Configuration
@ConditionalOnClass({ ApiVersionedResource.class })
public class WebConfiguration  {

    @Bean
    @Primary
    public ContentNegotiationManager contentNegotiationManager() {
        ContentNegotiationManagerFactoryBean contentNegotiationManagerFactoryBean = new ContentNegotiationManagerFactoryBean();
        Map<String, MediaType> mediaTypes = new HashMap<>();
        mediaTypes.put("json", MediaType.APPLICATION_JSON);
        contentNegotiationManagerFactoryBean.addMediaTypes(mediaTypes);
        contentNegotiationManagerFactoryBean.afterPropertiesSet();
        return contentNegotiationManagerFactoryBean.getObject();
    }

    @Bean
    public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
        return new WebMvcRegistrationsAdapter() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                CustomRequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping();
                handlerMapping.setOrder(0);
                handlerMapping.setRemoveSemicolonContent(false);
                handlerMapping.setContentNegotiationManager(contentNegotiationManager());
                return handlerMapping;
            }
        };
    }
}

但是,这会在编译期间导致以下错误,我不知道是什么导致它。

public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
    @Override
    protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        ApiVersionedResource typeAnnotation = AnnotationUtils.findAnnotation(handlerType, ApiVersionedResource.class);
        return createCondition(typeAnnotation);
    }

    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        ApiVersionedResource methodAnnotation = AnnotationUtils.findAnnotation(method, ApiVersionedResource.class);
        return createCondition(methodAnnotation);
    }

    @Override
    protected boolean isHandler(Class<?> beanType) {
        return super.isHandler(beanType) && (AnnotationUtils.findAnnotation(beanType, ApiVersionedResource.class) != null);
    }

    private RequestCondition<?> createCondition(ApiVersionedResource versionMapping) {
        if (versionMapping != null) {
            return new ApiVersionedResourceRequestCondition(versionMapping.media(), versionMapping.version());
        }

        return null;
    }
}

特别是在最后,

2017-03-15 16:44:58.215 DEBUG 63518 --- [  restartedMain] r.h.v.CustomRequestMappingHandlerMapping : 6 request handler methods found on class com.test.web.rest.OrganizationResource: {public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.createOrganization(com.test.service.dto.OrgDetailsDTO) throws java.net.URISyntaxException={[/organizations],methods=[POST],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}, public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.updateOrganization(com.test.service.dto.OrgDetailsDTO) throws java.net.URISyntaxException={[/organizations],methods=[PUT],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}, public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.getAllOrganizations(org.springframework.data.domain.Pageable) throws java.net.URISyntaxException={[/organizations],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}, public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.deleteOrganization(java.lang.Long)={[/organizations/{id}],methods=[DELETE],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}, public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.searchOrganizations(java.lang.String,org.springframework.data.domain.Pageable) throws java.net.URISyntaxException={[/search/organizations],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}, public org.springframework.http.ResponseEntity com.test.web.rest.OrganizationResource.getOrganization(java.lang.Long)={[/organizations/{id}],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}}
2017-03-15 16:44:58.238  INFO 63518 --- [  restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/organizations],methods=[POST],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<com.test.service.dto.OrgDetailsDTO> com.test.web.rest.OrganizationResource.createOrganization(com.test.service.dto.OrgDetailsDTO) throws java.net.URISyntaxException
2017-03-15 16:44:58.239  INFO 63518 --- [  restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/organizations],methods=[PUT],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<com.test.service.dto.OrgDetailsDTO> com.test.web.rest.OrganizationResource.updateOrganization(com.test.service.dto.OrgDetailsDTO) throws java.net.URISyntaxException
2017-03-15 16:44:58.239  INFO 63518 --- [  restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/organizations],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<java.util.List<com.test.service.dto.OrgDetailsDTO>> com.test.web.rest.OrganizationResource.getAllOrganizations(org.springframework.data.domain.Pageable) throws java.net.URISyntaxException
2017-03-15 16:44:58.239  INFO 63518 --- [  restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/organizations/{id}],methods=[DELETE],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<java.lang.Void> com.test.web.rest.OrganizationResource.deleteOrganization(java.lang.Long)
2017-03-15 16:44:58.240  INFO 63518 --- [  restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/search/organizations],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<java.util.List<com.test.service.dto.OrgDetailsDTO>> com.test.web.rest.OrganizationResource.searchOrganizations(java.lang.String,org.springframework.data.domain.Pageable) throws java.net.URISyntaxException
2017-03-15 16:44:58.240  INFO 63518 --- [  restartedMain] r.h.v.CustomRequestMappingHandlerMapping : Mapped "{[/organizations/{id}],methods=[GET],custom=[API Versions = {media=application/vnd.test.onboarding, versions=[]}]}" onto public org.springframework.http.ResponseEntity<com.test.service.dto.OrgDetailsDTO> com.test.web.rest.OrganizationResource.getOrganization(java.lang.Long)
2017-03-15 16:44:58.314  WARN 63518 --- [  restartedMain] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'documentationPluginsBootstrapper' defined in URL [jar:file:/Users/kasunt/.m2/repository/io/springfox/springfox-spring-web/2.6.1/springfox-spring-web-2.6.1.jar!/springfox/documentation/spring/web/plugins/DocumentationPluginsBootstrapper.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webMvcRequestHandlerProvider' defined in URL [jar:file:/Users/kasunt/.m2/repository/io/springfox/springfox-spring-web/2.6.1/springfox-spring-web-2.6.1.jar!/springfox/documentation/spring/web/plugins/WebMvcRequestHandlerProvider.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'requestMappingHandlerMapping' is expected to be of type 'org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping' but was actually of type 'com.sun.proxy.$Proxy232'

2 个答案:

答案 0 :(得分:0)

我似乎通过如下重构WebConfiguration来解决问题。我不完全确定为什么将CustomRequestMappingHandlerMapping实例化为公共类不起作用。我很高兴听到任何能够想到原因的人。

@Configuration
@ConditionalOnClass({ ApiVersionedResource.class })
public class WebConfiguration {

    @Bean
    public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
        return new WebMvcRegistrationsAdapter() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                return new CustomRequestMappingHandlerMapping();
            }
        };
    }

    private final class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

        @Override
        protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
            ApiVersionedResource typeAnnotation = AnnotationUtils.findAnnotation(handlerType, ApiVersionedResource.class);
            return createCondition(typeAnnotation);
        }

        @Override
        protected RequestCondition<?> getCustomMethodCondition(Method method) {
            ApiVersionedResource methodAnnotation = AnnotationUtils.findAnnotation(method, ApiVersionedResource.class);
            return createCondition(methodAnnotation);
        }

        @Override
        protected boolean isHandler(Class<?> beanType) {
            return super.isHandler(beanType) && (AnnotationUtils.findAnnotation(beanType, ApiVersionedResource.class) != null);
        }

        private RequestCondition<?> createCondition(ApiVersionedResource versionMapping) {
            if (versionMapping != null) {
                return new ApiVersionedResourceRequestCondition(versionMapping.media(), versionMapping.version());
            }

            return null;
        }
    }
}

答案 1 :(得分:0)

在Spring Boot 2.0.0中,有一种更简单的方法可以实现此目的。

创建一个WebMvcRegistrations接口实例作为Bean,并重写适当的方法以返回该对象的定制版本。 Spring Boot将读取并使用该实例。

在这种情况下,只需要覆盖getRequestMappingHandlerMapping()并返回自定义实现