【问题标题】:How to integrate Swagger with Maven + Java + Jersey +Tomcat如何将 Swagger 与 Maven + Java + Jersey +Tomcat 集成
【发布时间】:2014-11-04 18:49:05
【问题描述】:

我似乎无法理解如何集成 Swagger 来生成 API 文档。 网址:####:8080/MyService/rest/users/getall
我在代码和依赖项中添加了注释。
我尝试访问:####:8080/MyService/rest/ 但说找不到。

//web.xml

     <servlet>
     <servlet-name>mycompany-users-serlvet</servlet-name>
     <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
     <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>com.users.services.mycompany,com.wordnik.swagger.jersey.listing</param-value>
    </init-param> `
    <servlet>
  <servlet-name>JerseyJaxrsConfig</servlet-name>
  <servlet-class>com.wordnik.swagger.jersey.config.JerseyJaxrsConfig</servlet-class>
  <init-param>
    <param-name>api.version</param-name>
    <param-value>1.0.0</param-value>
  </init-param>
  <init-param>
    <param-name>swagger.api.basepath</param-name>
    <param-value>####:8080/MyService/rest/</param-value> //not sure What this should be?
  </init-param>
  <load-on-startup>2</load-on-startup>`

【问题讨论】:

    标签: java rest maven servlets swagger


    【解决方案1】:

    如果您已将文件从https://github.com/wordnik/swagger-ui 正确复制到您的项目(目录dist 必须复制到您的src/main/webapp),那么您可以访问http://.../MyService/index.html 上的API 文档。不要忘记修改index.html,以便 Swagger 知道在哪里加载 API 文档:

    window.swaggerUi = new SwaggerUi({
        url: "http://localhost:8080/MyService/rest/api-docs",
    

    如果rest 是您在类javax.ws.rs.core.Application 的实现中使用注释@ApplicationPath 定义的应用程序路径,则web.xml 中的API 基本路径必须设置为http://.../MyService/rest

    这里是我通常做的一个例子(我不使用web.xml进行配置):

    @ApplicationPath( "api" )
    public class MyRestApplication extends Application
    {
       @Override
       public Set<Class<?>> getClasses( )
       {
           Set<Class<?>> resources = new HashSet<Class<?>>( );
           resources.add( ApiListingResource.class );
           resources.add( ApiDeclarationProvider.class );
           resources.add( ApiListingResourceJSON.class );
           resources.add( ResourceListingProvider.class );
           resources.add( Ping.class ); // my own resource class
           swaggerConfiguration( );
           return resources;
       }
    
       private void swaggerConfiguration( )
       {
          SwaggerConfig swaggerConfig = new SwaggerConfig( );
          ConfigFactory.setConfig( swaggerConfig );
          swaggerConfig.setApiVersion( "0.0.1" ); 
          swaggerConfig.setBasePath( "http://localhost:8080/MyService/api" );
          ScannerFactory.setScanner( new DefaultJaxrsScanner( ) );
          ClassReaders.setReader( new DefaultJaxrsApiReader( ) );
       }
    }
    

    【讨论】:

      【解决方案2】:

      swagger.api.basepath 参数不是,您的 Swagger 安装会保留 index.html。它是 Swagger 使用的一个参数,用于为您提供通过 Swagger UI 调用 REST 端点的能力,因此它被呈现到 Swagger 使用的链接中。

      您下载 Swagger UI 并将其放入您的 WebContent 文件夹中。然后,您可以在 http://localhost:8080/swagger/ 加载 Swagger UI。

      web.xml 应该是这样的:

      <servlet>
          <servlet-name>jersey-servlet</servlet-name>
          <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
          <init-param>
              <param-name>javax.ws.rs.Application</param-name>
              <param-value>### Your Application or ResourceConfig ###</param-value>
           </init-param>
          <init-param>
              <param-name>jersey.config.server.provider.packages</param-name>
              <param-value>io.swagger.jaxrs.listing,
                          ### com.your.rest.package ###
              </param-value>
          </init-param>
      
          <load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>jersey-servlet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
      </servlet-mapping>
      
      ...
      
      
      <servlet>
          <servlet-name>JerseyJaxrsConfig</servlet-name>
          <servlet-class>io.swagger.jersey.config.JerseyJaxrsConfig</servlet-class>
          <init-param>
              <param-name>api.version</param-name>
              <param-value>1.0.0</param-value>
          </init-param>
          <init-param>
              <param-name>swagger.api.basepath</param-name>
              <param-value>/MyService/rest</param-value>
          </init-param>
          <init-param>
              <param-name>scan.all.resources</param-name>
              <param-value>true</param-value>
          </init-param>
          <load-on-startup>2</load-on-startup>
      </servlet>
      

      【讨论】:

        【解决方案3】:

        这里是使用spring、tomcat、jersey、maven、swagger的最简单的例子。 下面是项目结构。

        HelloWorldService 的代码。

        package com.rest;
        import com.wordnik.swagger.annotations.Api;
        import com.wordnik.swagger.annotations.ApiOperation;
        import com.wordnik.swagger.annotations.ApiResponse;
        import com.wordnik.swagger.annotations.ApiResponses;
        
        import javax.ws.rs.GET;
        import javax.ws.rs.Path;
        import javax.ws.rs.PathParam;
        import javax.ws.rs.Produces;
        import javax.ws.rs.core.MediaType;
        
        /**
         * Created by neerbans on 11/3/2016.
         */
        
        @Path("/hello")
        @Api( value = "/hello", description = "print hello world")
        public class HelloWorldService {
        
            @ApiOperation(
                    value = "method api",
                    notes = "method api notes"
            )
            @ApiResponses(value = {
                    @ApiResponse(code = 200, message = "success"),
                    @ApiResponse(code = 500, message = "error")
            })
            @Produces({MediaType.TEXT_PLAIN})
            @GET
            @Path("/{param}")
            public String getMsg(
                    @PathParam("param")
                    String msg
            ) {
        
                String output = "Jersey say : " + msg;
        
                return output;
            }
        
        }
        

        SwaggerApp.class

        package com.rest;
        
        import com.wordnik.swagger.config.ConfigFactory;
        import com.wordnik.swagger.config.ScannerFactory;
        import com.wordnik.swagger.config.SwaggerConfig;
        import com.wordnik.swagger.jaxrs.config.ReflectiveJaxrsScanner;
        import com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider;
        import com.wordnik.swagger.jaxrs.listing.ApiListingResource;
        import com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON;
        import com.wordnik.swagger.jaxrs.listing.ResourceListingProvider;
        import com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader;
        import com.wordnik.swagger.reader.ClassReaders;
        import org.glassfish.jersey.message.MessageProperties;
        import org.glassfish.jersey.server.ResourceConfig;
        import org.glassfish.jersey.server.ServerProperties;
        
        import javax.annotation.PostConstruct;
        
        /**
         * Created by neerbans on 11/3/2016.
         */
        public class SwaggerApp extends ResourceConfig {
        
            public SwaggerApp() {
                register(HelloWorldService.class);
        
                register(ApiListingResource.class);
                register(ApiDeclarationProvider.class);
                register(ApiListingResourceJSON.class);
                register(ResourceListingProvider.class);
        
                property(MessageProperties.XML_FORMAT_OUTPUT, true);
                property(ServerProperties.TRACING, "ALL");
            }
        
            @PostConstruct
            public void initializeSwaggerConfiguration() {
        
                final ReflectiveJaxrsScanner scanner = new ReflectiveJaxrsScanner();
                scanner.setResourcePackage("com.rest");
                ScannerFactory.setScanner(scanner);
                ClassReaders.setReader(new DefaultJaxrsApiReader());
                final SwaggerConfig config = ConfigFactory.config();
                config.setApiVersion("1.0");
                config.setBasePath("http://localhost:8080/jax-rs/rest");
            }
        }
        

        applicationContext.xml

        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
            <context:component-scan base-package="com.rest" />
            <context:annotation-config />
        </beans>
        

        Web.xml

        <!DOCTYPE web-app PUBLIC
         "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
         "http://java.sun.com/dtd/web-app_2_3.dtd" >
        
        <web-app>
          <display-name>Archetype Created Web Application</display-name>
            
            <!--<servlet>-->
                <!--<servlet-name>jersey-servlet</servlet-name>-->
                <!--<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>-->
                <!--<init-param>-->
                    <!--<param-name>com.sun.jersey.config.property.packages</param-name>-->
                    <!--<param-value>com.rest</param-value>-->
                <!--</init-param>-->
                <!--<load-on-startup>1</load-on-startup>-->
            <!--</servlet>-->
            
            <context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:applicationContext.xml</param-value>
            </context-param>
            
            <listener>
                <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
            </listener>
        
            <listener>
                <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
            </listener>
        
            <servlet>
                <servlet-name>Jersey Web Application</servlet-name>
                <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
                <init-param>
                    <param-name>javax.ws.rs.Application</param-name>
                    <param-value>com.rest.SwaggerApp</param-value>
                </init-param>
                <load-on-startup>1</load-on-startup>
            </servlet>
            
            <servlet-mapping>
                <servlet-name>Jersey Web Application</servlet-name>
                <url-pattern>/rest/*</url-pattern>
            </servlet-mapping>
        </web-app>
        

        pom.xml

        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
            <parent>
                <artifactId>nb</artifactId>
                <groupId>com.edifecs</groupId>
                <version>1.0-SNAPSHOT</version>
            </parent>
            <modelVersion>4.0.0</modelVersion>
            <artifactId>jax-rs</artifactId>
            <packaging>war</packaging>
            <name>jax-rs Maven Webapp</name>
            <url>http://maven.apache.org</url>
            <dependencies>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>3.8.1</version>
                    <scope>test</scope>
                </dependency>
                <dependency>
                    <groupId>org.glassfish.jersey.containers</groupId>
                    <artifactId>jersey-container-servlet</artifactId>
                    <version>2.22.2</version>
                </dependency>
                <dependency>
                    <groupId>com.wordnik</groupId>
                    <artifactId>swagger-jaxrs_2.10</artifactId>
                    <version>1.3.12</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                    <version>4.1.4.RELEASE</version>
                </dependency>
            </dependencies>
            <build>
                <finalName>jax-rs</finalName>
            </build>
        </project>
        

        设置项目后。构建它并在 Tomcat webapps 文件夹中部署 war 文件。
        运行 Tomcat 并点击以下 URL:

        http://localhost:8080/jax-rs/rest/api-docs

        对于 swagger-ui

        http://localhost:8080/jax-rs

        【讨论】:

        【解决方案4】:

        我在使用 BeanConfig 和普通的 HttpServlet 设置 Swagger 方面有很好的经验

        public class SwaggerBootstrap extends HttpServlet {
        
            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
        
                BeanConfig beanConfig = new BeanConfig();
                beanConfig.setVersion("1.0.0");
                beanConfig.setTitle("MyAppWeb App UI");
                // description can accept markdown
                beanConfig.setDescription("This is an overview of all the REST endpoints. Find out more about Swagger at [http://swagger.io](http://swagger.io)");
                beanConfig.setSchemes(new String[]{"https"});
                beanConfig.setHost("localhost:8443");
                beanConfig.setBasePath("/app");
                beanConfig.setResourcePackage("com.myapp.web.app");
                // enables scan
                beanConfig.setScan(true);
            }
        }
        

        com.myapp.web.app 资源包是我放置所有泽西岛资源的地方)

        然后,我刚刚在 web.xml 中注册了 servlet

        <servlet>
            <servlet-name>SwaggerBootstrap</servlet-name>
            <servlet-class>com.myapp.web.app.SwaggerBootstrap</servlet-class>
            <load-on-startup>2</load-on-startup>
        </servlet>
        

        当然,我必须注册列表才能使所有这些工作

        <servlet>
            <servlet-name>Jersey REST Service</servlet-name>
            <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>jersey.config.server.provider.packages</param-name>
                <param-value>
                  io.swagger.jaxrs.listing;
                  ...
            </param-value>
        </init-param>
        

        Reference in github

        【讨论】: