无法让 springfox-swagger-ui 与 Spring MVC 一起使用

Posted

技术标签:

【中文标题】无法让 springfox-swagger-ui 与 Spring MVC 一起使用【英文标题】:Not able to get springfox-swagger-ui working with Spring MVC 【发布时间】:2015-07-06 00:30:01 【问题描述】:

我花了几天的时间寻找并找不到解决方案,大多数示例处理的是 spring boot 和 gradle,我只使用 spring mvc 和 maven。

如果我删除 springfox-swagger-ui 依赖项,则应用程序运行良好,并且以下内容按预期返回 JSON http:\\localhost:8080\restful\v2\api-docs?group=restful-api

由于某种原因,我的 spring 应用程序无法通过 swagger-ui.html,如果我设置 index.html,它会给出相同的响应

我已尝试添加:

    欢迎列出 web.xml 中的文件 资源处理程序 默认 Servlet 处理

都没有用。

应用配置

package au.com.speak.restful.spring;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import     org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages =  "au.com.speak.restful.api" )
public class AppConfig extends WebMvcConfigurerAdapter 

    // ========= Overrides ===========

    @Override
    public void addInterceptors(InterceptorRegistry registry) 
        registry.addInterceptor(new LocaleChangeInterceptor());
    

    // ========= Beans ===========

    @Bean(name = "localeResolver")
    public LocaleResolver getLocaleResolver() 
        return new CookieLocaleResolver();
    

    @Bean(name = "messageSource")
    public MessageSource getMessageSources() 
        ReloadableResourceBundleMessageSource messageSource = new     ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("/WEB-INF/resources/properties/error", "/WEB-INF/resources/properties/validation");
        messageSource.setCacheSeconds(0);

        return messageSource;
    

Swagger 配置

package au.com.speak.restful.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig  

    @Bean
    public Docket restfulApi() 
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("restful-api")
                .select()
                .build()
                .apiInfo(apiInfo());
    

    private ApiInfo apiInfo() 

        ApiInfo apiInfo = new ApiInfo(
                "My Apps API Title",
                "My Apps API Description",
                "My Apps API Version",
                "My Apps API terms of service",
                "My Apps API Contact Email",
                "My Apps API Licence Type",
                "My Apps API License URL"
        );
        return apiInfo;
    

我的代码如下:

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

    <display-name>example restful api</display-name>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <listener>
        <listener-class>
            org.springframework.security.web.session.HttpSessionEventPublisher
        </listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>                    org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            au.com.speak.restful.spring.AppConfig
            au.com.speak.restful.spring.PropertyConfig
            au.com.speak.restful.spring.SecurityConfig
            au.com.speak.restful.spring.ServiceConfig
            au.com.speak.restful.spring.PersistenceConfig
            au.com.speak.restful.spring.SwaggerConfig
        </param-value>
    </context-param>

    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j.xml</param-value>
    </context-param>

    <!--
        Reads request input using UTF-8 encoding
    -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--
        Apply Spring Security Filter to all Requests
     -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--
        Handles all requests into the application
    -->
    <servlet>
        <servlet-name>model</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>*</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>model</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

错误

2015-04-27 23:03:47,805 INFO   - Loading XML bean definitions from ServletContext resource [/swagger-ui.html]
2015-04-27 23:03:47,811 ERROR  - Context initialization failed
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 2 in XML document from ServletContext resource [/swagger-ui.html] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 7;  Element type "html" must be declared.
at   org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:399)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:452)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:663)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:629)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:677)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:548)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:489)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at  org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1231)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1144)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1031)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4913)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5200)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1618)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:463)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:413)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1466)
at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1307)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1399)
at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:828)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:323)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$240(TCPTransport.java:683)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$1/1746485750.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at     java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 7;     Element type "html" must be declared.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)
at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.handleStartElement(XMLDTDValidator.java:1906)
at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.startElement(XMLDTDValidator.java:742)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1363)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$ContentDriver.scanRootElementHook(XMLDocumentScannerImpl.java:1292)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3138)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:880)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:348)
at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:76)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadDocument(XmlBeanDefinitionReader.java:429)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:391)
... 66 more

【问题讨论】:

我知道这不是很有帮助,但是您的配置似乎非常密集,有几件事可以简化您的配置,您应该尝试使用 AbstractAnnotationConfigDispatcherServletInitializer 的子类而不是 web.xml 。它使所有这些 xml 配置文件消失。其次,您应该能够使用WebMvcConfigurerAdapter 注册一些过滤器等,并且所有 contextConfigLocation 都应该转换为 bean 导入。 已通过将以下内容添加到 AppConfig 中进行修复。 @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/"); 【参考方案1】:

通过将以下内容添加到 AppConfig 中进行修复。

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

【讨论】:

大部分教程都没有提到这一点,因为它们使用的是 SpringBoot。参考this blog post。 你拯救了我的一天,我使用 Spring Boot 并在更改 spring.mvc.static-path-pattern 后遇到了问题 这对我来说在 spring boot 2.2.2 升级中的一个项目中失败了【参考方案2】:

我遇到这个错误是因为springfox-swagger2springfox-swagger-ui之间的版本不匹配,两个依赖的版本必须相同。

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

【讨论】:

对我来说 swagger-ui 依赖不匹配,从 swagger-ui 依赖中删除 对象解决了我的问题。像这样&lt;dependency&gt; &lt;groupId&gt;io.springfox&lt;/groupId&gt; &lt;artifactId&gt;springfox-swagger-ui&lt;/artifactId&gt; &lt;/dependency&gt;【参考方案3】:

我不知道swagger的新版本有什么不同,但我使用的是1.0.2版本。我也在使用swagger-spring-mvc-ui-0.4.jar来获取swagger API jsp文件和css。

Maven 依赖项

    <dependency>
        <groupId>com.mangofactory</groupId>
        <artifactId>swagger-springmvc</artifactId>
        <version>1.0.2</version>
    </dependency>

我将它与 Spring MVC 4.1.5 一起使用。以下是我用来生成 swagger api json 文件的唯一文件。

SwaggerConfig.java

import static org.ajar.swaggermvcui.SwaggerSpringMvcUi.WEB_JAR_RESOURCE_LOCATION;
import static org.ajar.swaggermvcui.SwaggerSpringMvcUi.WEB_JAR_RESOURCE_PATTERNS;
import static org.ajar.swaggermvcui.SwaggerSpringMvcUi.WEB_JAR_VIEW_RESOLVER_PREFIX;
import static org.ajar.swaggermvcui.SwaggerSpringMvcUi.WEB_JAR_VIEW_RESOLVER_SUFFIX;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.mangofactory.swagger.configuration.SpringSwaggerConfig;
import com.mangofactory.swagger.models.dto.ApiInfo;
import com.mangofactory.swagger.plugin.EnableSwagger;
import com.mangofactory.swagger.plugin.SwaggerSpringMvcPlugin;

@EnableSwagger
public class SwaggerConfig extends WebMvcConfigurerAdapter 
    private SpringSwaggerConfig springSwaggerConfig;

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

    @Bean
    public SwaggerSpringMvcPlugin customImplementation() 
        this.springSwaggerConfig.defaultSwaggerPathProvider()
                .setApiResourcePrefix("api");
        return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
                .apiInfo(apiInfo());// .includePatterns(".*swagger.*");
    

    private ApiInfo apiInfo() 
        ApiInfo apiInfo = new ApiInfo("My APIs",
                "RESTful APIs available under My Portal", "#",
                "deepankarsirt@gmail.com", "License Information", "#");
        return apiInfo;
    

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
        registry.addResourceHandler(WEB_JAR_RESOURCE_PATTERNS)
                .addResourceLocations(WEB_JAR_RESOURCE_LOCATION)
                .setCachePeriod(0);
    

    @Bean
    public InternalResourceViewResolver getInternalResourceViewResolver() 
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix(WEB_JAR_VIEW_RESOLVER_PREFIX);
        resolver.setSuffix(WEB_JAR_VIEW_RESOLVER_SUFFIX);
        return resolver;
    

    @Override
    public void configureDefaultServletHandling(
            DefaultServletHandlerConfigurer configurer) 
        configurer.enable();
    

我的休息控制器

@RestController
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public class CommonUtilityServices 

    @Autowired
    private CommonUtilityService commonUtilityService;

    @ApiOperation(value = "Is Unique", notes = "This service checks if a value is already present in DB or not.<br>Below is the sample JSON object. <br> <pre><code class=\"json\"><span class=\"attribute\"><span class=\"attribute\">\"dbField\"</span></span> : <span class=\"value\"><span class=\"string\"><span class=\"value\"><span class=\"string\">\"organization.name\"</span></span></span></span>, <span class=\"attribute\"><span class=\"attribute\">\"fieldValue\" : <span class=\"value\"><span class=\"string\"><span class=\"value\"><span class=\"string\">\"novopay\"</span></span></span></span></code></pre><br>'dbField' accepts value 'tableDB.DBField' format.<br>'fieldValue' is the value needs to be check for uniqueness.")
    @ApiResponses(value = 
            @ApiResponse(code = 202, message = "Request Accepted"),
            @ApiResponse(code = 400, message = "Bad Request") )
    @RequestMapping(value = "/isUnique", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody ResponseEntity<Boolean> isUnique(
            HttpServletRequest request, @RequestBody String jsonStr) 
        try 
            ObjectMapper mapper = new ObjectMapper();
            Map<?, ?> myMap = mapper.readValue(jsonStr.toString(),
                    HashMap.class);
            String dbField = (String) myMap.get("dbField");
            String fieldValue = (String) myMap.get("fieldValue");
            String whereClause = (String) myMap.get("whereClause");
            return new ResponseEntity<Boolean>(
                    commonUtilityService
                            .isValueAlreadyInDB(dbField, fieldValue, whereClause),
                    HttpStatus.ACCEPTED);
         catch (IOException | RuntimeException e) 
            return new ResponseEntity<Boolean>(HttpStatus.BAD_REQUEST);
        
    

除了上述所有更改之外,我还在swagger-spring-mvc-ui-0.4.jar 中制作了sdoc.jsp 文件的本地副本,并更改​​了它默认指向的url。

<script type="text/javascript">
$(function() 
    window.swaggerUi = new SwaggerUi(
        url: "/portal/api/api-docs", //New URL
        dom_id: "swagger-ui-container",
        supportedSubmitMethods: ['get', 'post', 'put', 'delete'],
        onComplete: function(swaggerApi, swaggerUi) 
            log("Loaded SwaggerUI");

请注意,我在 web.xml 文件中没有任何更改,并且 SwaggerConfig 类正在使用 spring annotations/component-scan 加载

【讨论】:

【参考方案4】:

虽然问题的作者没有使用 Spring Boot - 我决定在这里发帖以帮助其他人。 对我来说,使用 Spring Security 和 Spring Boot 的 Spring 5.0.0.M5 它通过在我的 pom.xml 中添加这两个依赖项来工作:

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

然后在我的 SpringBootApp 类中,我添加了 swagger 注释和相应的 Bean:

@SpringBootApplication
@EnableSwagger2
public class SpringBootApp extends WebMvcConfigurerAdapter 
    @Bean
    public Docket api() 
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    

    [...]

之后,我的应用程序根目录中提供了 api 文档,恰好是 /:http://localhost:8080/swagger-ui.html

通过这种方式,您甚至不需要单独的 SwaggerConfig,如下所述:http://www.baeldung.com/swagger-2-documentation-for-spring-rest-api

【讨论】:

【参考方案5】:

我在使用 Swagger 3.0.0 和 Spring Boot 2.2.4 时遇到了这个问题。

我发现的问题是 io.springfox:springfox-boot-starter:3.0.0 包含 io.springfox:springfox-swagger2:jar:2.9.2。我从 springfox-boot-starter 中明确包含了这个依赖,并包含了 springfox-swagger2 的 3.0.0 版本:

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-boot-starter</artifactId>
  <version>3.0.0</version>
  <exclusions>
    <exclusion>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger2</artifactId>
  <version>3.0.0</version>
</dependency>

这解决了 CNFE。

【讨论】:

以上是关于无法让 springfox-swagger-ui 与 Spring MVC 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

Swagger

Swagger

SpringBoot配置Swagger

SpringBoot配置Swagger

SpringBoot配置Swagger

使用Swagger生成简单接口文档