gpt4 book ai didi

rest - SwaggerSpringMvcPlugin 不适用于 Spring MVC

转载 作者:行者123 更新时间:2023-12-04 14:27:17 25 4
gpt4 key购买 nike

我在 REST 后端项目中使用以下组件:

  • Spring MVC:4.1.2.RELEASE(最新)
  • Hibernate4 对象映射器:2.4.3(最新)
  • Swagger:0.9.1(最新)
  • Javaee-web-api: 7.0 (servlet 3.1)

  • 我正在使用基于 XML 的 bean 配置,并且我能够使用 Swagger 启动并运行基本设置,在 Spring XML 配置文件中使用以下内容:
     <mvc:annotation-driven/> <!-- Required so swagger-springmvc can access spring's RequestMappingHandlerMapping  -->

    <bean class="com.mangofactory.swagger.configuration.SpringSwaggerConfig" />

    然后我从 https://github.com/wordnik/swagger-ui 克隆了 Swagger-UI GIT 存储库并将 dist 文件夹复制到我的/webapp/docs 文件夹中。这样做之后,我能够在以下 URL 上使用基于 JS 的 UI:
    http://localhost:9090/docs/index.html (works so far).

    问题是 都没有试试看 按钮工作,可用于直接使用 JSON 与您的 REST API 交互。没用的原因是没有走正确的 基本网址路径 与我的 Controller 交谈:
    http://localhost:9090/rest/addresses (actual controller location)
    http://localhost:9090/addresses (swagger's attempt to talk to the API)

    经过一些在线研究后,我发现我可能更好地使用 SwaggerSpringMvcPlugin 使用更灵活的方法,如 https://github.com/martypitt/swagger-springmvc 所述。 .

    这是我的 Swagger 配置类文件:
    @Configuration
    @EnableSwagger
    public class MySwaggerConfig {

    private SpringSwaggerConfig springSwaggerConfig;

    @Autowired
    public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
    this.springSwaggerConfig = springSwaggerConfig;
    }

    @Bean
    public SwaggerSpringMvcPlugin customImplementation(){
    return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
    .includePatterns(".*");
    }
    }

    这是我的全部 Spring mvc xml 文件:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="be.exampley.backend.web.rest"/>

    <bean id="hibernateAwareObjectMapper" class="be.example.backend.util.HibernateAwareObjectMapper"/>

    <mvc:annotation-driven>
    <mvc:message-converters>
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"
    p:prettyPrint="true"
    p:supportedMediaTypes-ref="supportedMediaTypes"
    p:objectMapper-ref="hibernateAwareObjectMapper"/>
    </mvc:message-converters>
    </mvc:annotation-driven>

    <util:list id="supportedMediaTypes">
    <value>application/json</value>
    <value>text/plain</value>
    </util:list>

    <context:annotation-config/>

    <mvc:default-servlet-handler/>

    <context:property-placeholder location="classpath:swagger.properties"/>

    <bean name="swaggerConfig" class="be.example.backend.configuration.MySwaggerConfig"/>

    </beans>

    摘自我的 的相关部分web.xml 文件:
    <servlet>
    <servlet-name>restServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/spring/mvc-rest-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
    <servlet-name>restServlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

    这是我的 swagger.properties 文件,由于某种原因根本没有考虑。
    documentation.services.basePath=/rest/
    documentation.services.version=2.0

    我在应用程序启动期间得到的堆栈跟踪:
        org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mySwaggerConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void be.example.backend.configuration.MySwaggerConfig.setSpringSwaggerConfig(com.mangofactory.swagger.configuration.SpringSwaggerConfig); nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.mangofactory.swagger.configuration.SpringSwaggerConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.List com.mangofactory.swagger.configuration.SpringSwaggerConfig.handlerMappings; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] found for dependency [collection of org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1204)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:798)
    at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:444)
    at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:789)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:294)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1341)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1334)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:741)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:497)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:163)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.server.Server.start(Server.java:387)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.Server.doStart(Server.java:354)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.runner.Runner.run(Runner.java:509)
    at org.eclipse.jetty.runner.Runner.main(Runner.java:557)
    ...
    Caused by:
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] found for dependency [collection of org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1261)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:961)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:904)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:527)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1204)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1081)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1006)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:904)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:600)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1204)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:798)
    at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:444)
    at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:789)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:294)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1341)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1334)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:741)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:497)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:163)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.server.Server.start(Server.java:387)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.Server.doStart(Server.java:354)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.runner.Runner.run(Runner.java:509)
    at org.eclipse.jetty.runner.Runner.main(Runner.java:557)

    我在某处读到,类型为 org...RequestMappingHandlerMapping 的 Noqualifying bean 表明我可能会错过 mvc:注释驱动在我的 XML 中,但情况并非如此。

    我一直在寻找几个小时来找到解决方案,但到目前为止都失败了。事实上,在它的基本配置中(使用 SpringSwaggerConfig )它可以工作 90%(除了 试试看 按钮......),让我不想放弃 Swagger 然而。它看起来真的很酷,并且是记录 API 的好方法。

    所以如果有人能帮助我解决这个问题,我将不胜感激。摇摇晃晃的岩石!

    亲切的问候,
    巴特

    最佳答案

    我可能在以下问题上绊倒了,RequestMappingHandlerMapping 的“没有找到用于自动连接的匹配 bean”:http://forum.spring.io/forum/spring-projects/web/112154-unable-to-autowire-requestmappinghandlermapping-in-controller

    与此同时,我已经切换到基于 Java 的配置来替换我的 XML。这也解决了 Autowiring 问题。特此我的解决方案供其他人引用,其中包括更改 apiResourcePrefix 并使用 swagger.properties 外部配置文件。

    我的 web.xml 文件:

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/business.xml</param-value>
    </context-param>

    <servlet>
    <servlet-name>restServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>be.example.backend.configuration.MvcConfig</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
    <servlet-name>restServlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

    我的 business.xml 作为根应用程序上下文:
    <context:annotation-config/>
    <context:component-scan base-package="be.example.backend"/>
    ...

    我的 MvcConfig.java 作为MVC配置文件:
    @EnableWebMvc
    @ComponentScan(basePackages = {"be.example.backend"})
    @Configuration
    public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    List<MediaType> supportedMediaTypes = new ArrayList<>();
    supportedMediaTypes.add(MediaType.APPLICATION_JSON);
    supportedMediaTypes.add(MediaType.TEXT_PLAIN);

    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(new HibernateAwareObjectMapper());
    converter.setPrettyPrint(true);
    converter.setSupportedMediaTypes(supportedMediaTypes);
    converters.add(converter);

    super.configureMessageConverters(converters);
    }
    }

    我的 SwaggerConfig.java 作为 Swagger 配置文件:
    @EnableWebMvc
    @EnableSwagger
    @PropertySource("classpath:swagger.properties")
    @ComponentScan(basePackages = {"be.example.backend"})
    @Configuration
    public class SwaggerConfig implements ServletContextAware {

    @Autowired
    private Environment environment;

    private SpringSwaggerConfig springSwaggerConfig;

    private ServletContext servletContext;

    @Autowired
    public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
    this.springSwaggerConfig = springSwaggerConfig;
    }

    @Bean
    public SwaggerSpringMvcPlugin customImplementation() {
    RelativeSwaggerPathProvider relativeSwaggerPathProvider = new RelativeSwaggerPathProvider(servletContext);
    relativeSwaggerPathProvider.setApiResourcePrefix(environment.getProperty("swagger.resource_prefix"));
    return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
    .pathProvider(relativeSwaggerPathProvider);
    }


    @Override
    public void setServletContext(ServletContext servletContext) {
    this.servletContext = servletContext;
    }
    }

    我的 swagger.properties 外部属性文件:
    swagger.resource_prefix=rest

    这个解决方案对我有用,我现在可以通过 swagger-ui 享受 swagger 功能。

    希望其他人也能享受它!

    关于rest - SwaggerSpringMvcPlugin 不适用于 Spring MVC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26918127/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com