2017-08-23 120 views
10

我用招摇用于记录一个RestEasy的API的端点,以及我所服务使用servlet的swagger.json描述用这样的方法:服务swagger.json从资源类

public void init(ServletConfig config) throws ServletException 
{ 
    super.init(config); 
    BeanConfig beanConfig = new BeanConfig(); 
    beanConfig.setHost("localhost:8080");  
    beanConfig.setBasePath("/api"); 
    beanConfig.setResourcePackage("my.rest.resources"); 
    beanConfig.setScan(true);  
} 

,我可以访问swagger.jsonlocalhost:8080/api/swagger.json。 然而,我的合作者想避免比RestEasy的servlet的其他额外的servlet,我不知道我是否能服务于招摇从资源类生成的方法JSON,这样的事情:

@GET 
@Path("/myswagger") 
@Produces("application/json") 
public String myswagger(@Context UriInfo uriInfo) 
{ 
    Swagger swagger = new Swagger(); 
    // Do something to retrieve the Swagger Json as a string 
    // ... 
    return(swaggerJsonString); 
} 

,然后访问swagger通过localhost:8080/api/myswagger生成json。这可能吗?

回答

4

可能的和非常简单的

import com.fasterxml.jackson.core.JsonProcessingException; 
import io.swagger.annotations.*; 
import io.swagger.jaxrs.Reader; 
import io.swagger.models.Swagger; 
import io.swagger.util.Json; 

import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType; 
import java.net.HttpURLConnection; 
import java.util.HashSet; 
import java.util.Set; 


@SwaggerDefinition(
     info = @Info(
       title = "title", 
       version = "0.2", 
       description = "description", 
       termsOfService = "termsOfService", 
       contact = @Contact(
         name = "contact", 
         url = "http://contact.org", 
         email = "[email protected]" 
       ), 
       license = @License(
         name = "Apache2", 
         url = "http://license.org/license" 
       ) 
     ), 
     host = "host.org", 
     basePath = "", 
     schemes = SwaggerDefinition.Scheme.HTTPS 
) 
public class SwaggerMain { 

    @Path("/a") 
    @Api(value = "/a", description = "aaa") 
    public class A { 

     @GET 
     @Path("/getA") 
     @Produces(MediaType.APPLICATION_JSON) 
     @ApiOperation(value = "Method for A.") 
     @ApiResponses(value = { 
       @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "OK"), 
       @ApiResponse(code = HttpURLConnection.HTTP_UNAUTHORIZED, message = "Unauthorized"), 
       @ApiResponse(code = HttpURLConnection.HTTP_NOT_FOUND, message = "Not found"), 
       @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "Internal server problems") 
     }) 
     public String getA() { 
      return "Hello, A"; 
     } 

    } 

    @Path("/b") 
    @Api(value = "/b", description = "bbb") 
    public class B { 
     @GET 
     @Path("/getA") 
     @Produces(MediaType.APPLICATION_JSON) 
     @ApiOperation(value = "Method for B.") 
     @ApiResponses(value = { 
       @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "OK"), 
       @ApiResponse(code = HttpURLConnection.HTTP_UNAUTHORIZED, message = "Unauthorized"), 
       @ApiResponse(code = HttpURLConnection.HTTP_NOT_FOUND, message = "Not found"), 
       @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "Internal server problems") 
     }) 
     public String getA() { 
      return "Hello, B"; 
     } 
    } 

    public static void main(String[] args) { 
     Set<Class<?>> classes = new HashSet<Class<?>>(); 
     classes.add(SwaggerMain.class); 
     classes.add(A.class); 
     classes.add(B.class); 
     Swagger swagger = new Reader(new Swagger()).read(classes); 
     try { 
      System.out.println(Json.mapper().writeValueAsString(swagger));; 
     } catch (JsonProcessingException e) { 
      e.printStackTrace(); 
     } 
    } 

} 

给出JSON:

{ 
    "swagger": "2.0", 
    "info": { 
    "description": "description", 
    "version": "0.2", 
    "title": "title", 
    "termsOfService": "termsOfService", 
    "contact": { 
     "name": "contact", 
     "url": "http://contact.org", 
     "email": "[email protected]" 
    }, 
    "license": { 
     "name": "Apache2", 
     "url": "http://license.org/license" 
    } 
    }, 
    "host": "host.org", 
    "tags": [ 
    { 
     "name": "a" 
    }, 
    { 
     "name": "b" 
    } 
    ], 
    "schemes": [ 
    "https" 
    ], 
    "paths": { 
    "https://stackoverflow.com/a/getA": { 
     "get": { 
     "tags": [ 
      "a" 
     ], 
     "summary": "Method for A.", 
     "description": "", 
     "operationId": "getA", 
     "produces": [ 
      "application/json" 
     ], 
     "parameters": [], 
     "responses": { 
      "200": { 
      "description": "OK" 
      }, 
      "401": { 
      "description": "Unauthorized" 
      }, 
      "404": { 
      "description": "Not found" 
      }, 
      "500": { 
      "description": "Internal server problems" 
      } 
     } 
     } 
    }, 
    "/b/getA": { 
     "get": { 
     "tags": [ 
      "b" 
     ], 
     "summary": "Method for B.", 
     "description": "", 
     "operationId": "getA", 
     "produces": [ 
      "application/json" 
     ], 
     "parameters": [], 
     "responses": { 
      "200": { 
      "description": "OK" 
      }, 
      "401": { 
      "description": "Unauthorized" 
      }, 
      "404": { 
      "description": "Not found" 
      }, 
      "500": { 
      "description": "Internal server problems" 
      } 
     } 
     } 
    } 
    } 
} 
+0

这工作得很好,谢谢!我通过返回'Swagger'对象来设法服务于端点的swagger json! – user1981275

+0

我喜欢Hugues M.和egorlitvinenko的答案,两种解决方案都能正常工作。我会接受egorlitvinenko的解决方案,因为他的解决方案实际上就是我所要求的。 – user1981275

1

假设您可以从您的Java应用程序访问json文件,那么您应该只能读取json文件并将其作为方法的字符串返回值返回。

作为一个超级简单的例子:

String swaggerJsonString = new String(Files.readAllBytes(Paths.get("swagger.json"))); 

你必须弄清楚如何找到该文件在您的应用程序的路径。

2

因此,您尝试使用automatic scanning and registration将swagger连接到您的resteasy应用程序。

使用自动扫描时,swagger-core无法自动检测资源。要解决这个问题,你必须告诉swagger-core扫描哪些软件包。建议的解决方案是使用BeanConfig方法(很可能是作为Servlet)。

所以你做到了这一点,但现在你想要的不需要单独的servlet。

您应该不会尝试手动将swagger挂接到您的应用程序的每个资源提供商&。你应该用@Api(我假设你已经这么做了)注释它们,然后,因为你使用RESTEasy,所以你可以将你的BeanConfig移动到你现有的resteasy Application或者自定义的那个,在任何情况下都会被采用由您现有的resteasy servlet来维护。请参阅using a custom Application subclass

import io.swagger.jaxrs.config.BeanConfig; 
import javax.ws.rs.core.Application; 
import java.util.HashSet; 
import java.util.Set; 

public class MyApplication extends Application { 

    public MyApplication() { 
     BeanConfig beanConfig = new BeanConfig(); 
     beanConfig.setVersion("1.0"); 
     beanConfig.setSchemes(new String[] { "http" }); 
     beanConfig.setTitle("My API"); // <- mandatory 
     beanConfig.setHost("localhost:8080");  
     beanConfig.setBasePath("/api"); 
     beanConfig.setResourcePackage("my.rest.resources"); 
     beanConfig.setScan(true); 
    } 

    @Override 
    public Set<Class<?>> getClasses() { 
     Set<Class<?>> set = new HashSet<Class<?>>(); 
     set.add(MyRestResourceFoo.class); // Add your own application's resources and providers 
     set.add(io.swagger.jaxrs.listing.ApiListingResource.class); 
     set.add(io.swagger.jaxrs.listing.SwaggerSerializers.class); 
     return set; 
    } 
} 

你的资源&商应保持干净的代码扬鞭除了注释。例如,下面是一个简单的echo服务:

import io.swagger.annotations.Api; 
import io.swagger.annotations.ApiOperation; 

import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.PathParam; 
import javax.ws.rs.core.Response; 

@Api 
@Path("/echo") 
public class EchoRestService { 

    @ApiOperation(value = "Echoes message back") 
    @GET 
    @Path("/{param}") 
    public Response printMessage(@PathParam("param") String msg) { 
     String result = "Echoing: " + msg; 
     return Response.status(200).entity(result).build(); 
    } 
} 

接着参观http://localhost:8080/api/swagger.json得到JSON字符串(与.yaml相同)。

我推an example to GitHub,这是非常简单的,并根据您现有的应用程序,你可能会需要更多的细节,但它可以帮助您开始。

+0

谢谢您的回答,您的GitHub例子,只保留注解中的资源类的提示!我将swagger'beanconfig'添加到我的'Application'子类中,这似乎工作正常!如果你不介意的话,我有两个问题(下一个评论) – user1981275

+0

在''getClasses'子Application',您明确指定的资源类。这甚至是必要的吗?它工作正常的我,如果我只是'返回null' ... – user1981275

+0

我的第二个问题是有点小白问题(新到Java和Web的东西)......我想玩的SwagEasy例如,但我不知道如何部署(我正在使用wildfly)。 8080/swageasy':当我复制'swageasy.war'到wildfly的'独立/部署/'目录,我不能在本地主机'找资源。我也尝试过'wildfly-maven-plugin',但没有成功。我错过了什么? – user1981275